2021-06-22 12:58:00 +02:00
|
|
|
import { JL } from 'jsnlog'
|
|
|
|
import { OpenVidu } from "../../OpenVidu/OpenVidu";
|
2021-06-23 21:37:26 +02:00
|
|
|
import { ConsoleLogger } from './ConsoleLogger';
|
2021-06-22 12:58:00 +02:00
|
|
|
import { OpenViduLoggerConfiguration } from "./OpenViduLoggerConfiguration";
|
2021-03-31 17:12:37 +02:00
|
|
|
|
2020-05-04 20:01:56 +02:00
|
|
|
export class OpenViduLogger {
|
|
|
|
|
|
|
|
private static instance: OpenViduLogger;
|
2021-03-31 17:12:37 +02:00
|
|
|
|
2021-04-01 03:11:45 +02:00
|
|
|
private JSNLOG_URL: string = "/openvidu/elk/openvidu-browser-logs";
|
2021-04-29 21:08:12 +02:00
|
|
|
private MAX_JSNLOG_BATCH_LOG_MESSAGES: number = 100;
|
2021-03-31 17:12:37 +02:00
|
|
|
private MAX_MSECONDS_BATCH_MESSAGES: number = 5000;
|
2021-04-29 23:37:44 +02:00
|
|
|
private MAX_LENGTH_STRING_JSON: number = 1000;
|
2021-03-31 17:12:37 +02:00
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
private defaultConsoleLogger: ConsoleLogger = new ConsoleLogger(window.console);
|
|
|
|
|
2021-04-08 16:17:35 +02:00
|
|
|
private currentAppender: any;
|
|
|
|
|
2020-05-04 20:01:56 +02:00
|
|
|
private isProdMode = false;
|
2021-03-31 17:12:37 +02:00
|
|
|
private isJSNLogSetup = false;
|
|
|
|
|
2021-04-29 18:45:26 +02:00
|
|
|
// This two variables are used to restart JSNLog
|
|
|
|
// on different sessions and different userIds
|
|
|
|
private loggingSessionId: string | undefined;
|
2020-05-04 20:01:56 +02:00
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2021-04-29 18:45:26 +02:00
|
|
|
static configureJSNLog(openVidu: OpenVidu, token: string) {
|
2021-05-11 18:53:53 +02:00
|
|
|
try {
|
2021-06-22 12:58:00 +02:00
|
|
|
// If dev mode
|
|
|
|
if ((window['LOG_JSNLOG_RESULTS']) ||
|
|
|
|
// If instance is created and it is OpenVidu Pro
|
|
|
|
(this.instance && openVidu.webrtcStatsInterval > -1
|
|
|
|
// If logs are enabled
|
2021-06-23 21:37:26 +02:00
|
|
|
&& this.instance.isOpenViduBrowserLogsDebugActive(openVidu)
|
2021-06-22 12:58:00 +02:00
|
|
|
// Only reconfigure it if session or finalUserId has changed
|
|
|
|
&& this.instance.canConfigureJSNLog(openVidu, this.instance))) {
|
2021-06-23 21:37:26 +02:00
|
|
|
|
|
|
|
// Check if app logs can be sent
|
|
|
|
// and replace console.log function to send
|
|
|
|
// logs of the application
|
|
|
|
if (openVidu.sendBrowserLogs === OpenViduLoggerConfiguration.debugApp) {
|
|
|
|
this.instance.replaceWindowConsole();
|
|
|
|
}
|
|
|
|
|
2021-04-08 16:17:35 +02:00
|
|
|
// isJSNLogSetup will not be true until completed setup
|
|
|
|
this.instance.isJSNLogSetup = false;
|
|
|
|
this.instance.info("Configuring JSNLogs.");
|
|
|
|
|
2021-04-29 18:45:26 +02:00
|
|
|
const finalUserId = openVidu.finalUserId;
|
|
|
|
const sessionId = openVidu.session.sessionId;
|
|
|
|
|
2021-04-08 16:17:35 +02:00
|
|
|
const beforeSendCallback = (xhr) => {
|
|
|
|
// If 401 or 403 or 404 modify ready and status so JSNLog don't retry to send logs
|
|
|
|
// https://github.com/mperdeck/jsnlog.js/blob/v2.30.0/jsnlog.ts#L805-L818
|
|
|
|
const parentReadyStateFunction = xhr.onreadystatechange;
|
|
|
|
xhr.onreadystatechange = () => {
|
2021-06-23 21:37:26 +02:00
|
|
|
console.log(xhr.status);
|
|
|
|
if (this.isInvalidResponse(xhr)) {
|
2021-06-22 12:58:00 +02:00
|
|
|
Object.defineProperty(xhr, "readyState", { value: 4 });
|
|
|
|
Object.defineProperty(xhr, "status", { value: 200 });
|
2021-06-23 21:37:26 +02:00
|
|
|
// Disable JSNLog too to not send periodically errors
|
|
|
|
this.instance.disableLogger();
|
2021-04-08 16:17:35 +02:00
|
|
|
}
|
|
|
|
parentReadyStateFunction();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Headers to identify and authenticate logs
|
2021-04-29 18:45:26 +02:00
|
|
|
xhr.setRequestHeader('Authorization', "Basic " + btoa(`${finalUserId}%/%${sessionId}` + ":" + token));
|
2021-03-31 17:12:37 +02:00
|
|
|
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
|
|
|
// Additional headers for OpenVidu
|
2021-04-29 18:45:26 +02:00
|
|
|
xhr.setRequestHeader('OV-Final-User-Id', finalUserId);
|
2021-04-29 13:26:54 +02:00
|
|
|
xhr.setRequestHeader('OV-Session-Id', sessionId);
|
|
|
|
xhr.setRequestHeader('OV-Token', token);
|
2021-03-31 17:12:37 +02:00
|
|
|
}
|
|
|
|
|
2021-04-08 16:17:35 +02:00
|
|
|
// Creation of the appender.
|
2021-04-29 18:45:26 +02:00
|
|
|
this.instance.currentAppender = JL.createAjaxAppender(`appender-${finalUserId}-${sessionId}`);
|
2021-04-08 16:17:35 +02:00
|
|
|
this.instance.currentAppender.setOptions({
|
|
|
|
beforeSend: beforeSendCallback,
|
2021-04-07 17:29:51 +02:00
|
|
|
maxBatchSize: 1000,
|
2021-03-31 17:12:37 +02:00
|
|
|
batchSize: this.instance.MAX_JSNLOG_BATCH_LOG_MESSAGES,
|
|
|
|
batchTimeout: this.instance.MAX_MSECONDS_BATCH_MESSAGES
|
|
|
|
});
|
|
|
|
|
|
|
|
// Avoid circular dependencies
|
|
|
|
const logSerializer = (obj): string => {
|
|
|
|
const getCircularReplacer = () => {
|
|
|
|
const seen = new WeakSet();
|
|
|
|
return (key, value) => {
|
2021-04-29 18:45:26 +02:00
|
|
|
if (typeof value === "object" && value != null) {
|
2021-05-11 18:53:53 +02:00
|
|
|
if (seen.has(value) || value instanceof HTMLElement) {
|
2021-03-31 17:12:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
seen.add(value);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
};
|
|
|
|
};
|
2021-04-29 23:37:44 +02:00
|
|
|
|
|
|
|
// Cut long messages
|
2021-06-22 12:58:00 +02:00
|
|
|
let stringifyJson = JSON.stringify(obj, getCircularReplacer());
|
2021-04-29 23:37:44 +02:00
|
|
|
if (stringifyJson.length > this.instance.MAX_LENGTH_STRING_JSON) {
|
2021-06-22 12:58:00 +02:00
|
|
|
stringifyJson = `${stringifyJson.substring(0, this.instance.MAX_LENGTH_STRING_JSON)}...`;
|
2021-04-29 23:37:44 +02:00
|
|
|
}
|
2021-06-22 12:58:00 +02:00
|
|
|
|
|
|
|
if (window['LOG_JSNLOG_RESULTS']) {
|
|
|
|
console.log(stringifyJson);
|
|
|
|
}
|
|
|
|
|
2021-04-29 23:37:44 +02:00
|
|
|
return stringifyJson;
|
2021-03-31 17:12:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Initialize JL to send logs
|
|
|
|
JL.setOptions({
|
2021-04-08 16:17:35 +02:00
|
|
|
defaultAjaxUrl: openVidu.httpUri + this.instance.JSNLOG_URL,
|
2021-06-21 14:52:01 +02:00
|
|
|
serialize: logSerializer,
|
|
|
|
enabled: true
|
2021-03-31 17:12:37 +02:00
|
|
|
});
|
|
|
|
JL().setOptions({
|
2021-04-08 16:17:35 +02:00
|
|
|
appenders: [this.instance.currentAppender]
|
2021-03-31 17:12:37 +02:00
|
|
|
});
|
2021-04-08 16:17:35 +02:00
|
|
|
|
2021-03-31 17:12:37 +02:00
|
|
|
this.instance.isJSNLogSetup = true;
|
2021-04-08 16:17:35 +02:00
|
|
|
this.instance.loggingSessionId = sessionId;
|
2021-03-31 17:12:37 +02:00
|
|
|
this.instance.info("JSNLog configured.");
|
|
|
|
}
|
2021-05-11 18:53:53 +02:00
|
|
|
} catch (e) {
|
2021-06-23 21:37:26 +02:00
|
|
|
// Print error
|
2021-05-11 18:53:53 +02:00
|
|
|
console.error("Error configuring JSNLog: ");
|
|
|
|
console.error(e);
|
2021-06-23 21:37:26 +02:00
|
|
|
// Restore defaults values just in case any exception happen-
|
|
|
|
this.instance.disableLogger();
|
2021-03-31 17:12:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2020-05-04 20:01:56 +02:00
|
|
|
static getInstance(): OpenViduLogger {
|
2021-06-22 12:58:00 +02:00
|
|
|
if (!OpenViduLogger.instance) {
|
2020-05-04 20:01:56 +02:00
|
|
|
OpenViduLogger.instance = new OpenViduLogger();
|
|
|
|
}
|
|
|
|
return OpenViduLogger.instance;
|
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
private static isInvalidResponse(xhr: XMLHttpRequest) {
|
|
|
|
return xhr.status == 401 || xhr.status == 403 || xhr.status == 404 || xhr.status == 0;
|
2021-04-29 23:37:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private canConfigureJSNLog(openVidu: OpenVidu, logger: OpenViduLogger): boolean {
|
2021-05-11 19:23:42 +02:00
|
|
|
return openVidu.session.sessionId != logger.loggingSessionId
|
2021-04-29 23:37:44 +02:00
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
private isOpenViduBrowserLogsDebugActive(openVidu: OpenVidu) {
|
|
|
|
return openVidu.sendBrowserLogs === OpenViduLoggerConfiguration.debug ||
|
|
|
|
openVidu.sendBrowserLogs === OpenViduLoggerConfiguration.debugApp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return console functions with jsnlog integration
|
|
|
|
private getConsoleWithJSNLog() {
|
|
|
|
return function(openViduLogger: OpenViduLogger){
|
|
|
|
return {
|
|
|
|
log: function(...args){
|
|
|
|
openViduLogger.defaultConsoleLogger.log.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
|
|
JL().info(arguments);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
info: function (...args) {
|
|
|
|
openViduLogger.defaultConsoleLogger.info.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
|
|
JL().info(arguments);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
debug: function(...args) {
|
|
|
|
openViduLogger.defaultConsoleLogger.debug.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
|
|
},
|
|
|
|
warn: function (...args) {
|
|
|
|
openViduLogger.defaultConsoleLogger.warn.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
|
|
JL().warn(arguments);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
error: function (...args) {
|
|
|
|
openViduLogger.defaultConsoleLogger.error.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
|
|
JL().error(arguments);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
private replaceWindowConsole() {
|
|
|
|
window.console = this.defaultConsoleLogger.logger;
|
|
|
|
window.console.log = this.getConsoleWithJSNLog().log;
|
|
|
|
window.console.info = this.getConsoleWithJSNLog().info;
|
|
|
|
window.console.debug = this.getConsoleWithJSNLog().debug;
|
|
|
|
window.console.warn = this.getConsoleWithJSNLog().warn;
|
|
|
|
window.console.error = this.getConsoleWithJSNLog().error;
|
|
|
|
}
|
|
|
|
|
|
|
|
private disableLogger() {
|
|
|
|
JL.setOptions({enabled: false});
|
|
|
|
this.isJSNLogSetup = false;
|
|
|
|
this.loggingSessionId = undefined;
|
|
|
|
this.currentAppender = undefined;
|
|
|
|
window.console = this.defaultConsoleLogger.logger;
|
|
|
|
window.console.log = this.defaultConsoleLogger.log;
|
|
|
|
window.console.info = this.defaultConsoleLogger.info;
|
|
|
|
window.console.debug = this.defaultConsoleLogger.debug;
|
|
|
|
window.console.warn = this.defaultConsoleLogger.warn;
|
|
|
|
window.console.error = this.defaultConsoleLogger.error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2021-06-22 12:58:00 +02:00
|
|
|
log(...args: any[]) {
|
2020-05-04 20:01:56 +02:00
|
|
|
if (!this.isProdMode) {
|
2021-06-23 21:37:26 +02:00
|
|
|
this.defaultConsoleLogger.log.apply(this.defaultConsoleLogger.logger, arguments);
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
2021-06-23 21:37:26 +02:00
|
|
|
if (this.isJSNLogSetup) {
|
2021-03-31 17:12:37 +02:00
|
|
|
JL().info(arguments);
|
|
|
|
}
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2020-05-04 20:01:56 +02:00
|
|
|
debug(...args: any[]) {
|
|
|
|
if (!this.isProdMode) {
|
2021-06-23 21:37:26 +02:00
|
|
|
this.defaultConsoleLogger.debug.apply(this.defaultConsoleLogger.logger, arguments);
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2020-05-04 20:01:56 +02:00
|
|
|
info(...args: any[]) {
|
|
|
|
if (!this.isProdMode) {
|
2021-06-23 21:37:26 +02:00
|
|
|
this.defaultConsoleLogger.info.apply(this.defaultConsoleLogger.logger, arguments);
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
2021-06-23 21:37:26 +02:00
|
|
|
if (this.isJSNLogSetup) {
|
2021-03-31 17:12:37 +02:00
|
|
|
JL().info(arguments);
|
|
|
|
}
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2020-05-04 20:01:56 +02:00
|
|
|
warn(...args: any[]) {
|
|
|
|
if (!this.isProdMode) {
|
2021-06-23 21:37:26 +02:00
|
|
|
this.defaultConsoleLogger.warn.apply(this.defaultConsoleLogger.logger, arguments);
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
2021-06-23 21:37:26 +02:00
|
|
|
if (this.isJSNLogSetup) {
|
2021-03-31 17:12:37 +02:00
|
|
|
JL().warn(arguments);
|
|
|
|
}
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2020-05-04 20:01:56 +02:00
|
|
|
error(...args: any[]) {
|
2021-06-23 21:37:26 +02:00
|
|
|
this.defaultConsoleLogger.error.apply(this.defaultConsoleLogger.logger, arguments);
|
|
|
|
if (this.isJSNLogSetup) {
|
2021-03-31 17:12:37 +02:00
|
|
|
JL().error(arguments);
|
|
|
|
}
|
2020-05-04 20:01:56 +02:00
|
|
|
}
|
|
|
|
|
2021-06-23 21:37:26 +02:00
|
|
|
/**
|
|
|
|
* @hidden
|
|
|
|
*/
|
2021-04-07 17:29:51 +02:00
|
|
|
flush() {
|
2021-06-23 21:37:26 +02:00
|
|
|
if (this.isJSNLogSetup && this.currentAppender != null) {
|
2021-04-08 16:17:35 +02:00
|
|
|
this.currentAppender.sendBatch();
|
2021-04-07 17:29:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-22 12:58:00 +02:00
|
|
|
enableProdMode() {
|
2020-05-04 20:01:56 +02:00
|
|
|
this.isProdMode = true;
|
|
|
|
}
|
2021-03-31 17:12:37 +02:00
|
|
|
|
2021-04-08 16:17:35 +02:00
|
|
|
}
|