From bc3e068e2e73caf6019096401d90cae22ed2d44f Mon Sep 17 00:00:00 2001 From: Bobak Oftadeh <bobakoftadeh@outlook.com> Date: Tue, 19 Jun 2018 09:46:59 -0700 Subject: [PATCH] Client logger implemented --- bigbluebutton-html5/client/main.jsx | 14 ++-- .../log-client/server/methods/logClient.js | 22 +++--- .../imports/startup/client/auth.js | 27 ++++++- .../imports/startup/client/logger.js | 74 +++++++++++++++++++ .../imports/ui/services/auth/index.js | 53 ++++++++++++- bigbluebutton-html5/package-lock.json | 39 ++++++++++ bigbluebutton-html5/package.json | 2 + .../private/config/settings-development.json | 6 ++ 8 files changed, 216 insertions(+), 21 deletions(-) mode change 100644 => 100755 bigbluebutton-html5/client/main.jsx create mode 100755 bigbluebutton-html5/imports/startup/client/logger.js mode change 100644 => 100755 bigbluebutton-html5/imports/ui/services/auth/index.js diff --git a/bigbluebutton-html5/client/main.jsx b/bigbluebutton-html5/client/main.jsx old mode 100644 new mode 100755 index 2fee67cb38..9878237374 --- a/bigbluebutton-html5/client/main.jsx +++ b/bigbluebutton-html5/client/main.jsx @@ -2,15 +2,19 @@ import React from 'react'; import { Meteor } from 'meteor/meteor'; import { render } from 'react-dom'; -import { log } from '/imports/ui/services/api'; import renderRoutes from '/imports/startup/client/routes'; +import logger from '/imports/startup/client/logger'; Meteor.startup(() => { render(renderRoutes(), document.getElementById('app')); - - // Log all uncaught exceptions to the server - // TODO: There is no StackTrace on the ErrorEvent object + // Logs all uncaught exceptions to the client logger window.addEventListener('error', (e) => { - log('error', e); + const stack = e.error.stack; + let message = e.error.toString(); + + // Checks if stack includes the message, if not add the two together. + (stack.includes(message)) ? message = stack : message += `\n${stack}`; + logger.error(message); }); }); + diff --git a/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js b/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js index 160e5a72b0..f116152949 100755 --- a/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js +++ b/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js @@ -7,23 +7,19 @@ const logClient = function (type, log, ...args) { const logContents = { ...args }; if (User) { - const { - meetingId, name, intId, extId, authToken, - } = User; - const serverInfo = { - meetingId, - userName: name, - userIntId: intId, - userExtId: extId, - authToken, - }; - logContents.serverInfo = serverInfo; + if (User.meetingId === args[0].meetingId) { + args[0].validUser = 'vaild'; + } else { + args[0].validUser = 'invaild'; + } + } else { + args[0].validUser = 'notFound'; } if (typeof log === 'string' || log instanceof String) { - Logger.log(type, `CLIENT LOG: ${log}\n`, logContents); + Logger.log(type, `CLIENT LOG: ${log}`, logContents); } else { - Logger.log(type, `CLIENT LOG: ${JSON.stringify(log)}\n`, logContents); + Logger.log(type, `CLIENT LOG: ${JSON.stringify(log)}`, logContents); } }; diff --git a/bigbluebutton-html5/imports/startup/client/auth.js b/bigbluebutton-html5/imports/startup/client/auth.js index 896e6370fc..590b752e9b 100755 --- a/bigbluebutton-html5/imports/startup/client/auth.js +++ b/bigbluebutton-html5/imports/startup/client/auth.js @@ -3,6 +3,7 @@ import SessionStorage from '/imports/ui/services/storage/session'; import { setCustomLogoUrl } from '/imports/ui/components/user-list/service'; import { log } from '/imports/ui/services/api'; import deviceInfo from '/imports/utils/deviceInfo'; +import logger from '/imports/startup/client/logger'; // disconnected and trying to open a new connection const STATUS_CONNECTING = 'connecting'; @@ -15,6 +16,9 @@ export function joinRouteHandler(nextState, replace, callback) { replace({ pathname: '/error/404' }); callback(); } + + // Old credentials stored in memory were being used when browsers was refreshed + Auth.clearCredentials(); // use enter api to get params for the client const url = `/bigbluebutton/api/enter?sessionToken=${sessionToken}`; @@ -24,6 +28,8 @@ export function joinRouteHandler(nextState, replace, callback) { .then(({ response }) => { const { returncode, meetingID, internalUserID, authToken, logoutUrl, customLogoURL, metadata, + externUserID, fullname, confname, + } = response; if (returncode === 'FAILED') { @@ -55,13 +61,32 @@ export function joinRouteHandler(nextState, replace, callback) { }) : {}; SessionStorage.setItem(METADATA_KEY, metakeys); - Auth.set(meetingID, internalUserID, authToken, logoutUrl, sessionToken); + Auth.set( + meetingID, internalUserID, authToken, logoutUrl, + sessionToken, fullname, externUserID, confname, + ); const path = deviceInfo.type().isPhone ? '/' : '/users'; + const userInfo = window.navigator; + + // Browser information is sent once on startup + // Sent here instead of Meteor.startup, as the + // user might not be validiated by then, thus user's data + // would not be sent with this information + const clientInfo = { + language: userInfo.language, + userAgent: userInfo.userAgent, + screenSize: { width: window.screen.width, height: window.screen.height }, + windowSize: { width: window.innerWidth, height: window.innerHeight }, + bbbVersion: Meteor.settings.public.app.bbbServerVersion, + location: window.location.href, + }; replace({ pathname: path }); callback(); + + logger.info(JSON.stringify(clientInfo)); }); } diff --git a/bigbluebutton-html5/imports/startup/client/logger.js b/bigbluebutton-html5/imports/startup/client/logger.js new file mode 100755 index 0000000000..7eef6f261e --- /dev/null +++ b/bigbluebutton-html5/imports/startup/client/logger.js @@ -0,0 +1,74 @@ +import Auth from '/imports/ui/services/auth'; +import { Meteor } from 'meteor/meteor'; +import { createLogger, stdSerializers } from 'browser-bunyan'; +import { ConsoleFormattedStream } from '@browser-bunyan/console-formatted-stream'; +import { ServerStream } from '@browser-bunyan/server-stream'; +import { nameFromLevel } from '@browser-bunyan/levels'; + +// The logger accepts "console","server", and "url" as targets +// Multiple targets can be set as an array in the settings under public.log.target +// Set the desired log levels to be sent under public.log.level +// The accepted levels are "debug", "info", "warn", "error" +// If sending to a url, provide the end-point on public.log.url +// Call the logger by doing a function call with the level name, I.e, logger.warn('Hi on warn') + +const LOG_CONFIG = Meteor.settings.public.log || {}; +const loggerStreams = []; // Stores the targets streams +const { fullInfo } = Auth; + +// create a custom stream that logs to an end-point +class ServerLoggerStream extends ServerStream { + write(rec) { + if (fullInfo.meetingId != null) { + rec.clientInfo = fullInfo; + } + return super.write(rec); + } +} + +// Created a custom stream to log to the meteor server +class MeteorStream { + write(rec) { + if (fullInfo.meetingId != null) { + Meteor.call('logClient', nameFromLevel[rec.level], rec.msg, fullInfo); + } else { + Meteor.call('logClient', nameFromLevel[rec.level], rec.msg); + } + } +} + +// Checks to see which targets have been chosen +if (LOG_CONFIG.target.includes('console')) { + loggerStreams.unshift({ + level: LOG_CONFIG.level, // sends logs that are this level and higher + stream: new ConsoleFormattedStream(), + }); +} + +if (LOG_CONFIG.target.includes('server')) { + loggerStreams.unshift({ + level: LOG_CONFIG.level, + stream: new MeteorStream(), + }); +} + +if (LOG_CONFIG.target.includes('url')) { + loggerStreams.unshift({ + level: LOG_CONFIG.level, + stream: new ServerLoggerStream({ + url: LOG_CONFIG.url, + method: 'PUT', + }), + }); +} + +// Creates the logger with the array of streams of the chosen targets +const logger = createLogger({ + name: 'clientLogger', + streams: loggerStreams, + serializers: stdSerializers, + src: true, +}); + + +export default logger; diff --git a/bigbluebutton-html5/imports/ui/services/auth/index.js b/bigbluebutton-html5/imports/ui/services/auth/index.js old mode 100644 new mode 100755 index 08d639ca57..d714597b58 --- a/bigbluebutton-html5/imports/ui/services/auth/index.js +++ b/bigbluebutton-html5/imports/ui/services/auth/index.js @@ -15,6 +15,9 @@ class Auth { this._authToken = Storage.getItem('authToken'); this._sessionToken = Storage.getItem('sessionToken'); this._logoutURL = Storage.getItem('logoutURL'); + this._confname = Storage.getItem('confname'); + this._externUserID = Storage.getItem('externUserID'); + this._fullname = Storage.getItem('fullname'); this._loggedIn = { value: false, tracker: new Tracker.Dependency(), @@ -66,6 +69,33 @@ class Auth { return this._logoutURL; } + set confname(confname) { + this._confname = confname; + Storage.setItem('confname', this._confname); + } + + get confname() { + return this._confname; + } + + set externUserID(externUserID) { + this._externUserID = externUserID; + Storage.setItem('externUserID', this._externUserID); + } + + get externUserID() { + return this._externUserID; + } + + set fullname(fullname) { + this._fullname = fullname; + Storage.setItem('fullname', this._fullname); + } + + get fullname() { + return this._fullname; + } + get loggedIn() { this._loggedIn.tracker.depend(); return this._loggedIn.value; @@ -83,15 +113,32 @@ class Auth { requesterToken: this.token, logoutURL: this.logoutURL, sessionToken: this.sessionToken, + fullname: this.fullname, + externUserID: this.externUserID, + confname: this.confname + }; + } + + get fullInfo() { + return { + sessionToken: this.sessionToken, + meetingId: this.meetingID, + requesterUserId: this.userID, + fullname: this.fullname, + confname: this.confname, + externUserID: this.externUserID, }; } - set(meetingId, requesterUserId, requesterToken, logoutURL, sessionToken) { + set(meetingId, requesterUserId, requesterToken, logoutURL, sessionToken, fullname, externUserID, confname) { this.meetingID = meetingId; this.userID = requesterUserId; this.token = requesterToken; this.logoutURL = logoutURL; this.sessionToken = sessionToken; + this.fullname = fullname; + this.externUserID = externUserID; + this.confname = confname; } clearCredentials(...args) { @@ -101,7 +148,9 @@ class Auth { this.loggedIn = false; this.logoutURL = null; this.sessionToken = null; - + this.fullname = null; + this.externUserID = null + this.confname = null; return Promise.resolve(...args); } diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json index f8b617f138..dbd84aa8a4 100755 --- a/bigbluebutton-html5/package-lock.json +++ b/bigbluebutton-html5/package-lock.json @@ -3,6 +3,32 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@browser-bunyan/console-formatted-stream": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@browser-bunyan/console-formatted-stream/-/console-formatted-stream-1.3.0.tgz", + "integrity": "sha1-PcBZqlwbKnofJuJwbiveuaCbvlc=", + "requires": { + "@browser-bunyan/levels": "1.3.0" + } + }, + "@browser-bunyan/console-raw-stream": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@browser-bunyan/console-raw-stream/-/console-raw-stream-1.3.0.tgz", + "integrity": "sha1-zPJLVvImUFgpfGUX++zqhOu3gYw=", + "requires": { + "@browser-bunyan/levels": "1.3.0" + } + }, + "@browser-bunyan/levels": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@browser-bunyan/levels/-/levels-1.3.0.tgz", + "integrity": "sha1-oFIwOuXRofm2Pus6lElaL0KfSDE=" + }, + "@browser-bunyan/server-stream": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@browser-bunyan/server-stream/-/server-stream-1.3.0.tgz", + "integrity": "sha1-U7MlP6T8WA6GrZoWNqA6ISo0W1Y=" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -401,6 +427,19 @@ "concat-map": "0.0.1" } }, +<<<<<<< HEAD +======= + "browser-bunyan": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-bunyan/-/browser-bunyan-1.3.0.tgz", + "integrity": "sha1-JjeNxY16mAAsyb/Pui6l1xJEmZI=", + "requires": { + "@browser-bunyan/console-formatted-stream": "1.3.0", + "@browser-bunyan/console-raw-stream": "1.3.0", + "@browser-bunyan/levels": "1.3.0" + } + }, +>>>>>>> 33222e3... Client logger configured "browser-detect": { "version": "0.2.28", "resolved": "https://registry.npmjs.org/browser-detect/-/browser-detect-0.2.28.tgz", diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json index ae15a6a739..f83def4ff1 100755 --- a/bigbluebutton-html5/package.json +++ b/bigbluebutton-html5/package.json @@ -28,7 +28,9 @@ "but Meteor 1.6.0.1 doesn't see it there for some reason", "need to investigate" ], + "@browser-bunyan/server-stream": "^1.3.0", "babel-runtime": "~6.26.0", + "browser-bunyan": "^1.3.0", "browser-detect": "^0.2.28", "classnames": "~2.2.5", "clipboard": "~1.7.1", diff --git a/bigbluebutton-html5/private/config/settings-development.json b/bigbluebutton-html5/private/config/settings-development.json index 178d9df90e..85ac58a62c 100755 --- a/bigbluebutton-html5/private/config/settings-development.json +++ b/bigbluebutton-html5/private/config/settings-development.json @@ -336,6 +336,12 @@ } ] } + + }, + "log": { + "level":"info", + "target": ["server"], + "url":"" } }, -- GitLab