/*
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
*/
|
|
|
|
//------------------------------------------------------------------------------
|
|
// The logger module exports the following properties/functions:
|
|
//
|
|
// LOG - constant for the level LOG
|
|
// ERROR - constant for the level ERROR
|
|
// WARN - constant for the level WARN
|
|
// INFO - constant for the level INFO
|
|
// DEBUG - constant for the level DEBUG
|
|
// logLevel() - returns current log level
|
|
// logLevel(value) - sets and returns a new log level
|
|
// useConsole() - returns whether logger is using console
|
|
// useConsole(value) - sets and returns whether logger is using console
|
|
// log(message,...) - logs a message at level LOG
|
|
// error(message,...) - logs a message at level ERROR
|
|
// warn(message,...) - logs a message at level WARN
|
|
// info(message,...) - logs a message at level INFO
|
|
// debug(message,...) - logs a message at level DEBUG
|
|
// logLevel(level,message,...) - logs a message specified level
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
var logger = exports;
|
|
|
|
var exec = require('cordova/exec');
|
|
|
|
var UseConsole = false;
|
|
var UseLogger = true;
|
|
var Queued = [];
|
|
var DeviceReady = false;
|
|
var CurrentLevel;
|
|
|
|
var originalConsole = console;
|
|
|
|
/**
|
|
* Logging levels
|
|
*/
|
|
|
|
var Levels = [
|
|
"LOG",
|
|
"ERROR",
|
|
"WARN",
|
|
"INFO",
|
|
"DEBUG"
|
|
];
|
|
|
|
/*
|
|
* add the logging levels to the logger object and
|
|
* to a separate levelsMap object for testing
|
|
*/
|
|
|
|
var LevelsMap = {};
|
|
for (var i=0; i<Levels.length; i++) {
|
|
var level = Levels[i];
|
|
LevelsMap[level] = i;
|
|
logger[level] = level;
|
|
}
|
|
|
|
CurrentLevel = LevelsMap.WARN;
|
|
|
|
/**
|
|
* Getter/Setter for the logging level
|
|
*
|
|
* Returns the current logging level.
|
|
*
|
|
* When a value is passed, sets the logging level to that value.
|
|
* The values should be one of the following constants:
|
|
* logger.LOG
|
|
* logger.ERROR
|
|
* logger.WARN
|
|
* logger.INFO
|
|
* logger.DEBUG
|
|
*
|
|
* The value used determines which messages get printed. The logging
|
|
* values above are in order, and only messages logged at the logging
|
|
* level or above will actually be displayed to the user. E.g., the
|
|
* default level is WARN, so only messages logged with LOG, ERROR, or
|
|
* WARN will be displayed; INFO and DEBUG messages will be ignored.
|
|
*/
|
|
logger.level = function (value) {
|
|
if (arguments.length) {
|
|
if (LevelsMap[value] === null) {
|
|
throw new Error("invalid logging level: " + value);
|
|
}
|
|
CurrentLevel = LevelsMap[value];
|
|
}
|
|
|
|
return Levels[CurrentLevel];
|
|
};
|
|
|
|
/**
|
|
* Getter/Setter for the useConsole functionality
|
|
*
|
|
* When useConsole is true, the logger will log via the
|
|
* browser 'console' object.
|
|
*/
|
|
logger.useConsole = function (value) {
|
|
if (arguments.length) UseConsole = !!value;
|
|
|
|
if (UseConsole) {
|
|
if (typeof console == "undefined") {
|
|
throw new Error("global console object is not defined");
|
|
}
|
|
|
|
if (typeof console.log != "function") {
|
|
throw new Error("global console object does not have a log function");
|
|
}
|
|
|
|
if (typeof console.useLogger == "function") {
|
|
if (console.useLogger()) {
|
|
throw new Error("console and logger are too intertwingly");
|
|
}
|
|
}
|
|
}
|
|
|
|
return UseConsole;
|
|
};
|
|
|
|
/**
|
|
* Getter/Setter for the useLogger functionality
|
|
*
|
|
* When useLogger is true, the logger will log via the
|
|
* native Logger plugin.
|
|
*/
|
|
logger.useLogger = function (value) {
|
|
// Enforce boolean
|
|
if (arguments.length) UseLogger = !!value;
|
|
return UseLogger;
|
|
};
|
|
|
|
/**
|
|
* Logs a message at the LOG level.
|
|
*
|
|
* Parameters passed after message are used applied to
|
|
* the message with utils.format()
|
|
*/
|
|
logger.log = function(message) { logWithArgs("LOG", arguments); };
|
|
|
|
/**
|
|
* Logs a message at the ERROR level.
|
|
*
|
|
* Parameters passed after message are used applied to
|
|
* the message with utils.format()
|
|
*/
|
|
logger.error = function(message) { logWithArgs("ERROR", arguments); };
|
|
|
|
/**
|
|
* Logs a message at the WARN level.
|
|
*
|
|
* Parameters passed after message are used applied to
|
|
* the message with utils.format()
|
|
*/
|
|
logger.warn = function(message) { logWithArgs("WARN", arguments); };
|
|
|
|
/**
|
|
* Logs a message at the INFO level.
|
|
*
|
|
* Parameters passed after message are used applied to
|
|
* the message with utils.format()
|
|
*/
|
|
logger.info = function(message) { logWithArgs("INFO", arguments); };
|
|
|
|
/**
|
|
* Logs a message at the DEBUG level.
|
|
*
|
|
* Parameters passed after message are used applied to
|
|
* the message with utils.format()
|
|
*/
|
|
logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
|
|
|
|
// log at the specified level with args
|
|
function logWithArgs(level, args) {
|
|
args = [level].concat([].slice.call(args));
|
|
logger.logLevel.apply(logger, args);
|
|
}
|
|
|
|
// return the correct formatString for an object
|
|
function formatStringForMessage(message) {
|
|
return (typeof message === "string") ? "" : "%o";
|
|
}
|
|
|
|
/**
|
|
* Logs a message at the specified level.
|
|
*
|
|
* Parameters passed after message are used applied to
|
|
* the message with utils.format()
|
|
*/
|
|
logger.logLevel = function(level /* , ... */) {
|
|
// format the message with the parameters
|
|
var formatArgs = [].slice.call(arguments, 1);
|
|
var fmtString = formatStringForMessage(formatArgs[0]);
|
|
if (fmtString.length > 0){
|
|
formatArgs.unshift(fmtString); // add formatString
|
|
}
|
|
|
|
var message = logger.format.apply(logger.format, formatArgs);
|
|
|
|
if (LevelsMap[level] === null) {
|
|
throw new Error("invalid logging level: " + level);
|
|
}
|
|
|
|
if (LevelsMap[level] > CurrentLevel) return;
|
|
|
|
// queue the message if not yet at deviceready
|
|
if (!DeviceReady && !UseConsole) {
|
|
Queued.push([level, message]);
|
|
return;
|
|
}
|
|
|
|
// Log using the native logger if that is enabled
|
|
if (UseLogger) {
|
|
exec(null, null, "Console", "logLevel", [level, message]);
|
|
}
|
|
|
|
// Log using the console if that is enabled
|
|
if (UseConsole) {
|
|
// make sure console is not using logger
|
|
if (console.useLogger()) {
|
|
throw new Error("console and logger are too intertwingly");
|
|
}
|
|
|
|
// log to the console
|
|
switch (level) {
|
|
case logger.LOG: originalConsole.log(message); break;
|
|
case logger.ERROR: originalConsole.log("ERROR: " + message); break;
|
|
case logger.WARN: originalConsole.log("WARN: " + message); break;
|
|
case logger.INFO: originalConsole.log("INFO: " + message); break;
|
|
case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Formats a string and arguments following it ala console.log()
|
|
*
|
|
* Any remaining arguments will be appended to the formatted string.
|
|
*
|
|
* for rationale, see FireBug's Console API:
|
|
* http://getfirebug.com/wiki/index.php/Console_API
|
|
*/
|
|
logger.format = function(formatString, args) {
|
|
return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
|
|
};
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* Formats a string and arguments following it ala vsprintf()
|
|
*
|
|
* format chars:
|
|
* %j - format arg as JSON
|
|
* %o - format arg as JSON
|
|
* %c - format arg as ''
|
|
* %% - replace with '%'
|
|
* any other char following % will format it's
|
|
* arg via toString().
|
|
*
|
|
* Returns an array containing the formatted string and any remaining
|
|
* arguments.
|
|
*/
|
|
function __format(formatString, args) {
|
|
if (formatString === null || formatString === undefined) return [""];
|
|
if (arguments.length == 1) return [formatString.toString()];
|
|
|
|
if (typeof formatString != "string")
|
|
formatString = formatString.toString();
|
|
|
|
var pattern = /(.*?)%(.)(.*)/;
|
|
var rest = formatString;
|
|
var result = [];
|
|
|
|
while (args.length) {
|
|
var match = pattern.exec(rest);
|
|
if (!match) break;
|
|
|
|
var arg = args.shift();
|
|
rest = match[3];
|
|
result.push(match[1]);
|
|
|
|
if (match[2] == '%') {
|
|
result.push('%');
|
|
args.unshift(arg);
|
|
continue;
|
|
}
|
|
|
|
result.push(__formatted(arg, match[2]));
|
|
}
|
|
|
|
result.push(rest);
|
|
|
|
var remainingArgs = [].slice.call(args);
|
|
remainingArgs.unshift(result.join(''));
|
|
return remainingArgs;
|
|
}
|
|
|
|
function __formatted(object, formatChar) {
|
|
|
|
try {
|
|
switch(formatChar) {
|
|
case 'j':
|
|
case 'o': return JSON.stringify(object);
|
|
case 'c': return '';
|
|
}
|
|
}
|
|
catch (e) {
|
|
return "error JSON.stringify()ing argument: " + e;
|
|
}
|
|
|
|
if ((object === null) || (object === undefined)) {
|
|
return Object.prototype.toString.call(object);
|
|
}
|
|
|
|
return object.toString();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// when deviceready fires, log queued messages
|
|
logger.__onDeviceReady = function() {
|
|
if (DeviceReady) return;
|
|
|
|
DeviceReady = true;
|
|
|
|
for (var i=0; i<Queued.length; i++) {
|
|
var messageArgs = Queued[i];
|
|
logger.logLevel(messageArgs[0], messageArgs[1]);
|
|
}
|
|
|
|
Queued = null;
|
|
};
|
|
|
|
// add a deviceready event to log queued messages
|
|
document.addEventListener("deviceready", logger.__onDeviceReady, false);
|