Source: core.js

/**
 * This file contains the base code for hooking together the Canadarm code.
 */

// These comments are added for JSDoc. It defines the
// namespaces used across the various development files.
// Do not modify this section of comments unless you have
// good reason.
/**
  @namespace Canadarm
*/
/**
  @namespace Handler
  @memberof Canadarm
*/
/**
  @namespace Appender
  @memberof Canadarm
*/
/**
  pseudo namespace to help with documentation.
  @namespace Events
  @memberof Canadarm
*/

var errorAppenders = [],
    errorHandlers = [];

/**
 * Used to setup Canadarm for consumers. The properties below are for the settings
 * object passed to the init function.
 *
 * @example
 *  Canadarm.init({
 *    onError: true,  // Set to false if you do not want window.onerror set.
 *    wrapEvents: true, // Set to false if you do not want all event handlers to be logged for errors
 *    logLevel: Canadarm.level.WARN, // Will only send logs for level of WARN and above.
 *    appenders: [
 *      Canadarm.Appender.standardLogAppender
 *    ],
 *    handlers: [
 *      Canadarm.Handler.beaconLogHandler('http://example.com/beacon.gif'),
 *      Canadarm.Handler.consoleLogHandler
 *    ]
 *  })
 *
 * @function init
 *
 * @param {object} settings - options for setting up canadarm.
 * @property settings[onError] {boolean}    - True, Canadarm will set onerror. Defaults to true.
 * @property settings[wrapEvents] {boolean} - True, Canadarm will wrap event binding. Defaults to true.
 * @property settings[appenders] {Array}    - Array of Appenders for Canadarm to use. Defaults to empty.
 * @property settings[handlers] {Array}     - Array of Handlers for Canadarm to use. Defaults to empty.
 * @property settings[logLevel] {String}    - The log level to log at. Defaults to Canadarm.level.DEBUG.
 */
function init(settings) {
  var opts = settings || {},
    i;

  if (opts.onError !== false) {
    Canadarm.setUpOnErrorHandler();
  }

  if (opts.wrapEvents !== false) {
    Canadarm.setUpEventListening();
  }

  if (opts.appenders) {
    for (i = 0; i < opts.appenders.length; i++) {
      Canadarm.addAppender(opts.appenders[i]);
    }
  }

  if (opts.handlers) {
    for (i = 0; i < opts.handlers.length; i++) {
      Canadarm.addHandler(opts.handlers[i]);
    }
  }

  if (opts.logLevel) {
    Canadarm.loggingLevel = opts.logLevel;
  }
}

/**
 * Adds the specified logAppender to existing appenders for logging.
 *
 * @example
 *  Canadarm.addAppender(Canadarm.Appender.standardLogAppender);
 *
 * @function addAppender
 *
 * @param {function} logAppender - Log appender for gather log data.
 */
function addAppender(logAppender) {
  errorAppenders.push(logAppender);
}

/**
 * Adds the specified logHandler to existing handlers for logging.
 *
 * @example
 *  Canadarm.addHandler(Canadarm.Handler.consoleLogHandler);
 *  Canadarm.addHandler(Canadarm.Handler.beaconLogHandler('http://example.com/beacon.gif'));
 *
 * @function addHandler
 *
 * @param {function} logHandler - Log handler for logs.
 */
function addHandler(logHandler) {
  errorHandlers.push(logHandler);
}

/**
 * Used to gather the errors that have occurred.  This function loops over the existing
 * logAppenders and creates the attributes that will be logged to the errors. Returns
 * an object of errors to log.
 *
 * @function gatherErrors
 * @private
 *
 * @param {string} level      - Log level of the exception. (e.g. ERROR, FATAL)
 * @param {error}  exception  - JavaScript Error object.
 * @param {string} message    - Message of the error.
 * @param {object} data       - Key/Value pairing of additional properties to log.
 * @param {array} appenders   - If passed will override existing appenders and be used.
 */
function gatherErrors(level, exception, message, data, appenders) {
  var logAttributes = {},
    localAppenders = appenders || errorAppenders,
    errorAppender, attributeName, attributes, i, key;

  // Go over every log appender and add it's attributes so we can log them.
  for (i = 0; i < localAppenders.length; i++) {
    errorAppender = localAppenders[i];
    attributes = errorAppender(level, exception, message, data);

    for (key in attributes) {
      if (!attributes.hasOwnProperty(key)) {
        continue;
      }
      logAttributes[key] = attributes[key];
    }
  }

  return logAttributes;
}

/**
 * Sends the errors passed in `logAttributes` for each logHandler.
 *
 * @method pushErrors
 * @private
 *
 * @param {object} logAttributes -- A key/value pairing of the attributes to log.
 * @param {array} handlers   -- If passed will override existing handlers and be used.
 */
function pushErrors(logAttributes, handlers) {
  var localHandlers = handlers || errorHandlers,
    errorHandler, i;

  // Go over every log handler so we can actually create logs.
  for (i = 0; i < localHandlers.length; i++) {
    errorHandler = localHandlers[i];
    errorHandler(logAttributes);
  }
}


/**
 * Used to generate our custom loggers.
 *
 * @function customLogEvent
 * @private
 *
 * @param {string} level - The level to log the events.
 *
 * @returns a function that logs what is passed.  Signature is: message, exception, data, settings.
 */
function customLogEvent(level) {

  // options should contain the appenders and handlers to override the
  // global ones defined in errorAppenders, and errorHandlers.
  // Used by Canadarm.localWatch to wrap local appender calls.
  return function (message, exception, data, settings) {

    // If we are are below the current Canadarm.loggingLevel we
    // should not do anything with the passed information.  Return
    // as if nothing happened.
    if (Canadarm.levelOrder.indexOf(level) < Canadarm.levelOrder.indexOf(Canadarm.loggingLevel)) {
      return;
    }

    var options = settings || {},
      attrs = gatherErrors(level, exception, message, data, options.appenders);
    pushErrors(attrs, options.handlers);
  };
}

// Custom logging functions for when code is captured
Canadarm.debug = customLogEvent(Canadarm.level.DEBUG);
Canadarm.info = customLogEvent(Canadarm.level.INFO);
Canadarm.warn = customLogEvent(Canadarm.level.WARN);
Canadarm.error = customLogEvent(Canadarm.level.ERROR);
Canadarm.fatal = customLogEvent(Canadarm.level.FATAL);

// Add logHandler and logAppender functions so Canadarm will work
Canadarm.addHandler = addHandler;
Canadarm.addAppender = addAppender;

// Add init so Canadarm can be setup easily.
Canadarm.init = init;

// Set default loggingLevel
Canadarm.loggingLevel = Canadarm.level.DEBUG;