Source: common/util/log.js

define(["lib/underscore"], function(_) {
    "use strict";
    // logs a message
    // logFn: console.log, console.warn, or console.error
    // name: name of the logger
    // messages: array or array-like object of messages
    var logMessage = function(logFn, level, name, messages) {

        // add a tag as the first message
        var prefix = "["+level+"] [Lens."+name+"]";
        var args = [prefix].concat(_.toArray(messages));

        // we apply in the context of console to avoid an "illegal invocation"
        logFn.apply(console, args);
    };

    /**
     * Creates a new logger with the given name
     * @param {String} name String to tag messages from the logger with.
     *
     * @class A logger that prints tagged messages, filtered by the current
     *        logging level.
     * @property {String} name String to tag messages from the logger with.
     *
     * @name Log
     * @private
     */
    var Log = function(name) {
        /** @alias Log.prototype */
        var self = {};

        self.name = name;

        /**
         * Prints a debug message. Takes an arbitrary number of arguments.
         */
        self.debug = function() {
            if(Log.level >= Log.DEBUG) {
                logMessage(console.log, "DEBUG", this.name, arguments);
            }
        };

        /**
         * Prints an info message. Takes an arbitrary number of arguments.
         */
        self.info = function() {
            if(Log.level >= Log.INFO) {
                logMessage(console.info, "INFO", this.name, arguments);
            }
        };

        /**
         * Prints a warning message. Takes an arbitrary number of arguments.
         */
        self.warn = function() {
            if(Log.level >= Log.WARN) {
                logMessage(console.warn, "WARN", this.name, arguments);
            }
        };

        /**
         * Prints an error message. Takes an arbitrary number of arguments.
         */
        self.error = function() {
            if(Log.level >= Log.ERROR) {
                logMessage(console.error, "ERROR", this.name, arguments);
                console.trace();
            }
        };

        Object.freeze(self);
        return self;
    };

    _.extend(Log, /** @lends Log */ {
        /**
         * Log level that displays all messages
         */
        DEBUG: 4,

        /**
         * Log level that displays all messages except debug messages
         * @constant
         */
        INFO: 3,

        /**
         * Log level that displays warnings and errors
         * @constant
         */
        WARN: 2,

        /**
         * Log level that displays only errors
         * @constant
         */
        ERROR: 1,

        /**
         * Log level that displays no messages
         * @constant
         */
        NONE: 0,

        /**
         * The current logging level. Change this to Log.INFO, Log.WARN,
         * Log.ERROR, or Log.NONE to adjust how much logging is done.
         *
         * @default Log.INFO
         */
        level: 3
    });

    var logger = Log("setLogLevel");

    /**
     * Sets the logging level. The default logging level is "info"
     * @param {String} level One of "debug", "info", "warn", or "error"
     */
    Lens.setLogLevel = function(level) {
        if(level === "debug") {
            Log.level = Log.DEBUG;
        }
        else if(level === "info") {
            Log.level = Log.INFO;
        }
        else if(level === "warn") {
            Log.level = Log.WARN;
        }
        else if(level === "error") {
            Log.level = Log.ERROR;
        }
        else {
            logger.error(level, "is not a valid logging level.");
        }
    };

    return Log;
});