/**
* Stores the log message starting header string.
* E.g. "<header> - <the log message>".
* @attribute _LOG_KEY
* @type String
* @private
* @scoped true
* @for Skylink
* @since 0.5.4
*/
var _LOG_KEY = 'SkylinkJS';
/**
* Stores the list of available SDK log levels.
* @attribute _LOG_LEVELS
* @type Array
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _LOG_LEVELS = ['error', 'warn', 'info', 'log', 'debug'];
/**
* Stores the current SDK log level.
* Default is ERROR (<code>0</code>).
* @attribute _logLevel
* @type String
* @default 0
* @private
* @scoped true
* @for Skylink
* @since 0.5.4
*/
var _logLevel = 0;
/**
* Stores the flag if debugging mode is enabled.
* This manipulates the SkylinkLogs interface.
* @attribute _enableDebugMode
* @type Boolean
* @default false
* @private
* @scoped true
* @for Skylink
* @since 0.5.4
*/
var _enableDebugMode = false;
/**
* Stores the flag if logs should be stored in SkylinkLogs interface.
* @attribute _enableDebugStack
* @type Boolean
* @default false
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _enableDebugStack = false;
/**
* Stores the flag if logs should trace if available.
* This uses the <code>console.trace</code> API.
* @attribute _enableDebugTrace
* @type Boolean
* @default false
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _enableDebugTrace = false;
/**
* Stores the flag if logs should print timestamp.
* @attribute _printTimestamp
* @type Boolean
* @default false
* @private
* @scoped true
* @for Skylink
* @since 0.6.26
*/
var _printTimestamp = false;
/**
* Stores the logs used for SkylinkLogs object.
* @attribute _storedLogs
* @type Array
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _storedLogs = [];
/**
* Stores the user's info for reporting error to API
* @attribute _userInfo
* @type JSON
* @private
* @scoped true
* @for Skylink
* @since 0.6.35
*/
var _reportErrorConfig = {
app_key: null,
statsServer: null
};
/**
* Function that gets the stored logs.
* @method _getStoredLogsFn
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _getStoredLogsFn = function (logLevel) {
if (typeof logLevel === 'undefined') {
return _storedLogs;
}
var returnLogs = [];
for (var i = 0; i < _storedLogs.length; i++) {
if (_storedLogs[i][1] === _LOG_LEVELS[logLevel]) {
returnLogs.push(_storedLogs[i]);
}
}
return returnLogs;
};
/**
* Function that clears the stored logs.
* @method _clearAllStoredLogsFn
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _clearAllStoredLogsFn = function () {
_storedLogs = [];
};
/**
* Function that prints in the Web Console interface the stored logs.
* @method _printAllStoredLogsFn
* @private
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _printAllStoredLogsFn = function () {
for (var i = 0; i < _storedLogs.length; i++) {
var timestamp = _storedLogs[i][0];
var log = (console[_storedLogs[i][1]] !== 'undefined') ?
_storedLogs[i][1] : 'log';
var message = _storedLogs[i][2];
var debugObject = _storedLogs[i][3];
if (typeof debugObject !== 'undefined') {
console[log](message, debugObject, timestamp);
} else {
console[log](message, timestamp);
}
}
};
/**
* <blockquote class="info">
* To utilise and enable the <code>SkylinkLogs</code> API functionalities, the
* <a href="#method_setDebugMode"><code>setDebugMode()</code> method</a>
* <code>options.storeLogs</code> parameter has to be enabled.
* </blockquote>
* The object interface to manage the SDK <a href="https://developer.mozilla.org/en/docs/Web/API/console">
* Javascript Web Console</a> logs.
* @property SkylinkLogs
* @type JSON
* @global true
* @for Skylink
* @since 0.5.5
*/
var SkylinkLogs = {
/**
* Function that gets the current stored SDK <code>console</code> logs.
* @property SkylinkLogs.getLogs
* @param {Number} [logLevel] The specific log level of logs to return.
* - When not provided or that the level does not exists, it will return all logs of all levels.
* [Rel: Skylink.LOG_LEVEL]
* @return {Array} The array of stored logs.<ul>
* <li><code><#index></code><var><b>{</b>Array<b>}</b></var><p>The stored log item.</p><ul>
* <li><code>0</code><var><b>{</b>Date<b>}</b></var><p>The DateTime of when the log was stored.</p></li>
* <li><code>1</code><var><b>{</b>String<b>}</b></var><p>The log level. [Rel: Skylink.LOG_LEVEL]</p></li>
* <li><code>2</code><var><b>{</b>String<b>}</b></var><p>The log message.</p></li>
* <li><code>3</code><var><b>{</b>Any<b>}</b></var><span class="label">Optional</span><p>The log message object.
* </p></li></ul></li></ul>
* @example
* // Example 1: Get logs of specific level
* var debugLogs = SkylinkLogs.getLogs(skylinkDemo.LOG_LEVEL.DEBUG);
*
* // Example 2: Get all the logs
* var allLogs = SkylinkLogs.getLogs();
* @type Function
* @global true
* @triggerForPropHackNone true
* @for Skylink
* @since 0.5.5
*/
getLogs: _getStoredLogsFn,
/**
* Function that clears all the current stored SDK <code>console</code> logs.
* @property SkylinkLogs.clearAllLogs
* @type Function
* @example
* // Example 1: Clear all the logs
* SkylinkLogs.clearAllLogs();
* @global true
* @triggerForPropHackNone true
* @for Skylink
* @since 0.5.5
*/
clearAllLogs: _clearAllStoredLogsFn,
/**
* Function that prints all the current stored SDK <code>console</code> logs into the
* <a href="https://developer.mozilla.org/en/docs/Web/API/console">Javascript Web Console</a>.
* @property SkylinkLogs.printAllLogs
* @type Function
* @example
* // Example 1: Print all the logs
* SkylinkLogs.printAllLogs();
* @global true
* @triggerForPropHackNone true
* @for Skylink
* @since 0.5.5
*/
printAllLogs: _printAllStoredLogsFn
};
/**
* Function that will send the log to an API endpoint for persistence
* @method _reportToAPI
* @private
* @required
* @scoped true
* @for Skylink
* @since 0.6.35
*/
var _reportToAPI = function(message, object) {
var endpoint = '/rest/stats/sessionerror';
if(_reportErrorConfig.statsServer){
var statsServer = _reportErrorConfig.statsServer;
var requestBody = {
data: {
message: message,
object: object,
}
};
requestBody.app_key = _reportErrorConfig.app_key;
requestBody.timestamp = (new Date()).toISOString();
try {
var xhr = new XMLHttpRequest();
xhr.onerror = function () { };
xhr.open('POST', statsServer + endpoint, true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.send(JSON.stringify(requestBody));
} catch (error) {}
}
};
/**
* Function that handles the logs received and prints in the Web Console interface according to the log level set.
* @method _logFn
* @private
* @required
* @scoped true
* @for Skylink
* @since 0.5.5
*/
var _logFn = function(logLevel, message, debugObject) {
var outputLog = '';
var datetime = (new Date());
if (typeof message === 'object') {
outputLog += (message[0]) ? ' [' + message[0] + '] -' : ' -';
outputLog += (message[1]) ? ' <<' + message[1] + '>>' : '';
if (message[2]) {
outputLog += ' ';
if (typeof message[2] === 'object') {
for (var i = 0; i < message[2].length; i++) {
outputLog += '(' + message[2][i] + ')';
}
} else {
outputLog += '(' + message[2] + ')';
}
}
outputLog += ' ' + message[3];
} else {
outputLog += ' - ' + message;
}
if (_enableDebugMode && _enableDebugStack) {
// store the logs
var logItem = [datetime, _LOG_LEVELS[logLevel], outputLog];
if (typeof debugObject !== 'undefined') {
logItem.push(debugObject);
}
_storedLogs.push(logItem);
}
outputLog = _LOG_KEY + (_printTimestamp ? ' :: ' + datetime.toISOString() : '') + outputLog;
if (_logLevel >= logLevel) {
// Fallback to log if failure
logLevel = (typeof console[_LOG_LEVELS[logLevel]] === 'undefined') ? 3 : logLevel;
if (_enableDebugMode && _enableDebugTrace) {
var logConsole = (typeof console.trace === 'undefined') ? logLevel[3] : 'trace';
if (typeof debugObject !== 'undefined') {
console[_LOG_LEVELS[logLevel]](outputLog, debugObject);
// output if supported
if (typeof console.trace !== 'undefined') {
console.trace('');
}
} else {
console[_LOG_LEVELS[logLevel]](outputLog);
// output if supported
if (typeof console.trace !== 'undefined') {
console.trace('');
}
}
} else {
if (typeof debugObject !== 'undefined') {
console[_LOG_LEVELS[logLevel]](outputLog, debugObject);
} else {
console[_LOG_LEVELS[logLevel]](outputLog);
}
}
}
};
/**
* Stores the logging functions.
* @attribute log
* @param {Function} debug The function that handles the DEBUG level logs.
* @param {Function} log The function that handles the LOG level logs.
* @param {Function} info The function that handles the INFO level logs.
* @param {Function} warn The function that handles the WARN level logs.
* @param {Function} error The function that handles the ERROR level logs.
* @type JSON
* @private
* @scoped true
* @for Skylink
* @since 0.5.4
*/
var log = {
debug: function (message, object) {
_logFn(4, message, object);
},
log: function (message, object) {
_logFn(3, message, object);
},
info: function (message, object) {
_logFn(2, message, object);
},
warn: function (message, object) {
_logFn(1, message, object);
},
error: function (message, object) {
_reportToAPI(message, object);
_logFn(0, message, object);
}
};
/**
* Function that configures the level of <code>console</code> API logs to be printed in the
* <a href="https://developer.mozilla.org/en/docs/Web/API/console">Javascript Web Console</a>.
* @method setLogLevel
* @param {Number} [logLevel] The specific log level of logs to return.
* - When not provided or that the level does not exists, it will not overwrite the current log level.
* <small>By default, the initial log level is <code>ERROR</code>.</small>
* [Rel: Skylink.LOG_LEVEL]
* @example
* // Example 1: Print all of the console.debug, console.log, console.info, console.warn and console.error logs.
* skylinkDemo.setLogLevel(skylinkDemo.LOG_LEVEL.DEBUG);
*
* // Example 2: Print only the console.log, console.info, console.warn and console.error logs.
* skylinkDemo.setLogLevel(skylinkDemo.LOG_LEVEL.LOG);
*
* // Example 3: Print only the console.info, console.warn and console.error logs.
* skylinkDemo.setLogLevel(skylinkDemo.LOG_LEVEL.INFO);
*
* // Example 4: Print only the console.warn and console.error logs.
* skylinkDemo.setLogLevel(skylinkDemo.LOG_LEVEL.WARN);
*
* // Example 5: Print only the console.error logs. This is done by default.
* skylinkDemo.setLogLevel(skylinkDemo.LOG_LEVEL.ERROR);
* @for Skylink
* @since 0.5.5
*/
Skylink.prototype.setLogLevel = function(logLevel) {
for (var level in this.LOG_LEVEL) {
if (this.LOG_LEVEL[level] === logLevel) {
_logLevel = logLevel;
log.log([null, 'Log', level, 'Log level exists. Level is set']);
return;
}
}
log.error([null, 'Log', level, 'Log level does not exist. Level is not set']);
};
/**
* Function that configures the debugging mode of the SDK.
* @method setDebugMode
* @param {Boolean|JSON} [options=false] The debugging options.
* - When provided as a boolean, this sets both <code>options.trace</code>
* and <code>options.storeLogs</code> to its boolean value.
* @param {Boolean} [options.trace=false] The flag if SDK <code>console</code> logs
* should output as <code>console.trace()</code> logs for tracing the <code>Function</code> call stack.
* <small>Note that the <code>console.trace()</code> output logs is determined by the log level set
* <a href="#method_setLogLevel"><code>setLogLevel()</code> method</a>.</small>
* <small>If <code>console.trace()</code> API is not supported, <code>setDebugMode()</code>
* will fallback to use <code>console.log()</code> API.</small>
* @param {Boolean} [options.storeLogs=false] The flag if SDK should store the <code>console</code> logs.
* <small>This is required to be enabled for <a href="#prop_SkylinkLogs"><code>SkylinkLogs</code> API</a>.</small>
* @param {Boolean} [options.printTimestamp=false] The flag if SDK should print the timestamp of the <code>console</code> logs.
* @example
* // Example 1: Enable both options.storeLogs and options.trace
* skylinkDemo.setDebugMode(true);
*
* // Example 2: Enable only options.storeLogs
* skylinkDemo.setDebugMode({ storeLogs: true });
*
* // Example 3: Disable debugging mode
* skylinkDemo.setDebugMode();
* @for Skylink
* @since 0.5.2
*/
Skylink.prototype.setDebugMode = function(isDebugMode) {
// setDebugMode({})
if (isDebugMode && typeof isDebugMode === 'object') {
_enableDebugMode = true;
_enableDebugTrace = isDebugMode.trace === true;
_enableDebugStack = isDebugMode.storeLogs === true;
_printTimestamp = isDebugMode.printTimestamp === true;
// setDebugMode(true)
} else if (isDebugMode === true) {
_enableDebugMode = true;
_enableDebugTrace = true;
_enableDebugStack = true;
_printTimestamp = false;
// setDebugMode()
} else {
_enableDebugMode = false;
_enableDebugTrace = false;
_enableDebugStack = false;
_printTimestamp = false;
}
};
/**
* Function that populates the userInfo object with appKey and client ID used for logging an error and reporting to API server
* @method _setClientInfoForLogging
* @param {String} appKey
* @param {String} clientId
* @for Skylink
* @since 0.5.5
*/
Skylink.prototype._setClientInfoForLogging = function() {
var initOptions = this._initOptions;
_reportErrorConfig.app_key = initOptions.appKey;
_reportErrorConfig.statsServer = initOptions.statsServer;
};