<commit_before>// TODO: Remove command
const twitchClass = require('../classes/twitch.js');
const twitch = new twitchClass(config.CLIENTID);
const ms = require('ms')
const Discord = require('discord.js');
let check = async (client) => {
    setInterval(async () => {
      console.log('Started');
        let queue = await r.table('livestreams').getAll('NONE', {index : 'guildID'}).run();

        // If 0 guilds are using the twitch system return.
        if (!queue[0].inQueue) return;

        // Loop  through all the streams and check for status
        for (let i = 0; i < queue[0].inQueue.length; i++) {

            //GuildID to look for.
            const guildID = queue[0].inQueue[i].guildID;
            const channelID = queue[0].inQueue[i].channelID;

            const channels = await r.table('livestreams').get(guildID + channelID).run(); //all the channels
            console.log('1');
            if (channels === null) return;

            //Loop through all the twitch streamers
            channels.livestreams.forEach(async O => {
              console.log('2');
                try {
                    const data = await twitch.check(O.name);

                    // Find the index
                    function findInd(element) {
                        return element.name === O.name
                    }

                    let toInsert1 = data.online === true ? {
                        game: data.game,
                        views: data.views,
                        image: data.image,
                        mature: data.mature,
                        lang: data.lang,
                        name: data.name,
                        url: data.url,
                        online: true
                    } : {online: false, name: data.name};

                    if (toInsert1['game']) {
                      await r.table('livestreams')
                          .get(`${guildID}${channelID}`)
                          .update({
                              livestreams: r.row('livestreams').map((f) => {
                                  return r.branch(
                                      f("name").eq(O.name),
                                      f.merge(toInsert1),
                                      f
                                  )
                              })
                          }).run();
                          console.log('3');
                    } else {
                      let appendToArray = (table, uArray, doc) => r.table(table)
                          .get(guildID + channelID)
                          .update(object => ({ [uArray]: object(uArray)
                          .default([]).changeAt(channels.livestreams.findIndex(findInd), doc) }))
                          .run();
                          appendToArray('livestreams', 'livestreams', toInsert1)
                      console.log('4');
                    }

                    if (O.online === true && !O.msgStatus) {
                      console.log('SENT');
                        const embed = new Discord.RichEmbed()
                            .setTitle(`${O.name} is live!`)
                            .addField('Game', O.game, true)
                            .addField('Language', O.lang, true)
                            .addField('Stream Link', `[${O.name}](${O.url})`)
                            .setImage(O.image)
                            .setColor('#56b91f')
                            .setThumbnail(O.image);
                        client.channels.get(channels.channelID).send({embed});

                        // appendToArray('livestreams', 'livestreams', toInsert2)
                        await r.table('livestreams')
                            .get(`${guildID}${channelID}`)
                            .update({
                                livestreams: r.row('livestreams').map((f) => {
                                    return r.branch(
                                        f("name").eq(O.name),
                                        f.merge({msgStatus: 'inserted'}),
                                        f
                                    )
                                })
                            }).run()
                    }

                } catch (e) {
                    logger.error(e)
                }

            });
        }

    }, ms('10s'));
};

module.exports = check;
<commit_msg>Should work now<commit_after>// TODO: Remove command
const twitchClass = require('../classes/twitch.js');
const twitch = new twitchClass(config.CLIENTID);
const ms = require('ms')
const Discord = require('discord.js');
let check = async (client) => {
    setInterval(async () => {
        let queue = await r.table('livestreams').getAll('NONE', {index : 'guildID'}).run();

        // If 0 guilds are using the twitch system return.
        if (!queue[0].inQueue) return;

        // Loop  through all the streams and check for status
        for (let i = 0; i < queue[0].inQueue.length; i++) {

            //GuildID to look for.
            const guildID = queue[0].inQueue[i].guildID;
            const channelID = queue[0].inQueue[i].channelID;

            const channels = await r.table('livestreams').get(guildID + channelID).run(); //all the channels
            if (channels === null) return;

            //Loop through all the twitch streamers
            channels.livestreams.forEach(async O => {
                try {
                    const data = await twitch.check(O.name);

                    // Find the index
                    function findInd(element) {
                        return element.name === O.name
                    }

                    let toInsert1 = data.online === true ? {
                        game: data.game,
                        views: data.views,
                        image: data.image,
                        mature: data.mature,
                        lang: data.lang,
                        name: data.name,
                        url: data.url,
                        online: true
                    } : {online: false, name: data.name};

                    if (toInsert1['game']) {
                      await r.table('livestreams')
                          .get(`${guildID}${channelID}`)
                          .update({
                              livestreams: r.row('livestreams').map((f) => {
                                  return r.branch(
                                      f("name").eq(O.name),
                                      f.merge(toInsert1),
                                      f
                                  )
                              })
                          }).run();
                    } else {
                      let appendToArray = (table, uArray, doc) => r.table(table)
                          .get(guildID + channelID)
                          .update(object => ({ [uArray]: object(uArray)
                          .default([]).changeAt(channels.livestreams.findIndex(findInd), doc) }))
                          .run();
                          appendToArray('livestreams', 'livestreams', toInsert1)
                    }

                    if (O.online === true && !O.msgStatus) {
                      console.log('SENT');
                        const embed = new Discord.RichEmbed()
                            .setTitle(`${O.name} is live!`)
                            .addField('Game', O.game, true)
                            .addField('Language', O.lang, true)
                            .addField('Stream Link', `[${O.name}](${O.url})`)
                            .setImage(O.image)
                            .setColor('#56b91f')
                            .setThumbnail(O.image);
                        client.channels.get(channels.channelID).send({embed});
                        logger.info('Fired up an auto notification for', require('chalk').cyan(guildID))
                        // appendToArray('livestreams', 'livestreams', toInsert2)
                        await r.table('livestreams')
                            .get(`${guildID}${channelID}`)
                            .update({
                                livestreams: r.row('livestreams').map((f) => {
                                    return r.branch(
                                        f("name").eq(O.name),
                                        f.merge({msgStatus: 'inserted'}),
                                        f
                                    )
                                })
                            }).run()
                    }

                } catch (e) {
                    logger.error(e)
                }

            });
        }

    }, ms('7m'));
};

module.exports = check;
<|endoftext|>


<commit_before>/*************************************************************************
 * ARMOR5 CONFIDENTIAL
 * Copyright 2012 Armor5, Inc. All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains the property
 * of Armor5, Inc. and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Armor5, Inc.
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material is
 * strictly forbidden unless prior written permission is obtained from
 * Armor5, Inc..
 **************************************************************************/

/**
 * Logging module. Shows time and log level (debug, info, warn, error).
 * Time is shown in milliseconds since this module was first initialized.
 * Usage:
 * 		var log = require('../lib/logger').get('logtest');
 *		log.info( 'Message: %s', 'my message');
 */

const LEVEL_ORDER = [ 'verbose', 'debug', 'info', 'warn', 'error', 'fatal' ];
const DEFAULT_BUFFER_DURATION = 1000; // ms

var util = require('util');
var DateUtil = require('./dateutil');
var ConsoleStream = require('./console');

// Static containing the time that this module was first initialized.
// Modules are loaded only once, so this will only be set once.
var t0 = (new Date()).getTime();

// Static stack containing stream where output should be written
var aStreams = [ new ConsoleStream() ];

// Static global holds a queue of messages that may build up while we are switching streams
// Streams do their own buffering to their own output
var queue = [];

// Static buffer duration
var gBufferDuration = DEFAULT_BUFFER_DURATION;

// Static global log level
var gLogLevel = 'debug';

// Static custom callback to use if an object is passed in as first parameter of log method
// var gGetSessionIdCallback;

var Logger = function (modulename) {

    var self = this;
	this.moduleName = modulename;
	this.logLevel;
    this.logData;
    this.logAction;

    /**
	 * Log an info message. The message can contain arguments (e.g 'Hello %s', 'world')
	 */
	this.info = function() {
        return self.logArgs( 'info', Array.prototype.slice.call(arguments) );
	};

	this.warn = function() {
        return self.logArgs( 'warn', Array.prototype.slice.call(arguments) );
	};

	this.debug = function() {
        return self.logArgs( 'debug', Array.prototype.slice.call(arguments) );
	};

	this.verbose = function() {
        return self.logArgs( 'verbose', Array.prototype.slice.call(arguments) );
	};

    this.error = function() {
        return self.logArgs( 'error', Array.prototype.slice.call(arguments) );
    };

    this.fatal = function() {
        return self.logArgs( 'fatal', Array.prototype.slice.call(arguments) );
    };

    this.separator = function() {
        if( self.isAboveLevel('info') ) {
            self._writeMessage( 'info', "######################################################################" );
        }
        return this;
    };

    this.data = function(key,value) {
        if( value && (typeof key === 'string' || typeof key === 'number') ) {
            if( !self.logData)
                self.logData = {};
            self.logData[key] = value;
        } else {
            self.logData = key;
        }
        return self;
    };

    this.date = function() {
        if( self.isAboveLevel('info') ) {
            var d = new Date();
            self.data( 'localtime', DateUtil.toISOLocalString(d) );
            self.data( 'utctime', d.toISOString() );
            //var msg = util.format( "=== CURRENT TIME  %s ====", DateUtil.toISOLocalString(d) );
            self.logArgs( 'info', [] );
//			var logMsg = util.format( "[%s] INFO: %s - === CURRENT TIME  %s ====", DateUtil.formatMS(d.getTime()-t0,0), (this.moduleName ? this.moduleName : ""), DateUtil.toISOLocalString(d) );
//			writeMessage( logMsg );
        }
        return self;
    };

    // Helper, level must be set, args must be an array, but can be empty
    this.logArgs = function( level, args ) {
        if( !args.length )
            args.unshift('');
        else if( args.length && ( args[0] === undefined || args[0] === null ) )
            args.shift();
        args.unshift( level );
        return self.log.apply( this, args );
    };

    /**
	 * Output a log message. This function is suitable for providing to classes that require logging callbacks.
     * It can also be used for multiline (folded) log messages.
     * Example: log.log( 'info', req, "Found %d lines", iLines );
     * @param level One of warn, debug, error or info. Defaults to info if not present.
     * @param object Optional object that has a callback gGetSessionIdCallback
	 * @param msg The message String, or an array of strings. Will be formatted
	 */
	this.log = function() {
        var args = Array.prototype.slice.call(arguments);
        if( args.length ) {
            if( args.length === 1 )
                args.unshift( 'info' );
            if( self.isAboveLevel(args[0]) )
                self._writeMessage.apply( this, args );
        }
		return self;
	};

//    this.hasSessionObjAsNthEntry = function(args,index) {
//        if( index === undefined )
//            index = 0;
//        if( gGetSessionIdCallback && args.length > 1 && (typeof args[index] === 'object') && ( typeof args[index][gGetSessionIdCallback] === 'function') )
//            return true;
//        return false;
//    };

    // Expects level, msg params
    this._writeMessage = function( level, msg ) {
        var args = Array.prototype.slice.call(arguments);
        if( args.length > 1 ) {
            var params = { module: self.moduleName };
            params.level = args.shift();
            if( self.logData ) {
                params.data = self.logData;
                delete self.logData;
            }
            if( self.logAction ) {
                params.action = self.logAction;
                delete self.logAction;
            }
            if( args.length === 1 && (args[0] instanceof Array) ) {
                params.message = [];
                for( var idx=0; idx<args[0].length; ++idx ) {
                    params.message.push( util.format.apply(this, (args[0][idx] instanceof Array) ? args[0][idx] : [args[0][idx]] ) );
                }
            } else {
                params.message = util.format.apply( this, args );
            }
            writeMessageParams( params );
        }
    };

	// Not called. Placeholder in case we ever support managed shutdown
	this.destroy = function() {
        while( aStreams.length ) {
            var stream = aStreams.shift();
            if( stream ) {
                stream.end();
                stream.destroy();
            }
        }
	};

	/**
	 * Set the log level for this object. This overrides the global log level for this object.
	 */
	this.setLogLevel = function(level) {
		self.logLevel = level;
		return this;
	}

	/**
	 * Return true if the level is equal to or greater then the reference, or if reference is null
	 */
	this.isAboveLevel = function( level ) {
		var reference = self.logLevel || gLogLevel;
		if( LEVEL_ORDER.indexOf(level) >= LEVEL_ORDER.indexOf(reference) )
			return true;
		return false;
	};

};

//function timeDiff() {
//    return (new Date()).getTime() - t0;
//}

/**
 * Get the time at which the module was initialized
 * @return {Number} Start time in milliseconds
 */
module.exports.getStartTime = function() {
    return t0;
};

/**
 * Shortcut to util.format()
 */
module.exports.format = function() {
    return util.format.apply(this,arguments);
};

/**
 * Return an instance of the logger that has the module name set.
 */
module.exports.get = function(moduleName) {
	return new Logger(moduleName);
};

/**
 * Set log level globally
 */
module.exports.setGlobalLogLevel = function(level) {
    gLogLevel = level;
};

/**
 * If an object is passed in as the first parameter of the log method, and there are subsequent
 * objects in the argument list, then test if that object has this function assigned and, if it does
 * call it to return a string that is to be included in the log message string as the a session ID.
 * @param fnName The object's function name to be called
 */
//module.exports.setSessionIdCallback = function( fnName ) {
//    gGetSessionIdCallback = fnName;
//}

/**
 * Write a raw message. We queue messages to handle the moment in time while we are switching
 * streams and the new stream is not ready yet. We do queuing while we wait for it to be ready.
 * You can completely bypass creating a logger instance in your class if you use this call directly,
 * In this situation the log level filtering will be established by the global log level (gLogLevel).
 * @param msgParams includes:
 *      level - Must be one of LEVEL_ORDER values, all lower case
 *      sid - (Optional) sessionID to display
 *      module - (Optional) Module descriptor to display (usually of form route.obj.function)
 *      time - (Optional) A date object with the current time, will be filled in if not provided
 *      timeDiff - (Optional) The difference in milliseconds between 'time' and when the application was
 *          started, based on reading Logger.getStartTime()
 *      message - A string or an array of strings. If an array the string will be printed on multiple lines
 *          where supported (e.g. SOS). The string must already formatted (e.g.. no '%s')
 */
module.exports.logMessage = writeMessageParams;
function writeMessageParams( msgParams ) {
    if( msgParams ) {
        if( !msgParams.level )
            msgParams.level = 'info';
        if( gIsAboveLevel(msgParams.level) ) {
            if( !msgParams.time )
                msgParams.time = new Date();
            if( !msgParams.timeDiff )
                msgParams.timeDiff = msgParams.time.getTime() - t0;
            queue.push( msgParams );
        }
        if( msgParams.length && msgParams.message && msgParams.message.length > msgParams.length )
            msgParams.message = msgParams.message.substr(0,msgParams.length) + "...";
    }
    flushQueue();
};

/**
 * Return true if the level is equal to or greater then the globally set log level
 */
function gIsAboveLevel( level ) {
    if( LEVEL_ORDER.indexOf(level) >= LEVEL_ORDER.indexOf(gLogLevel) )
        return true;
    return false;
};

function flushQueue() {
    if( aStreams[0].ready ) {
        var nextMsg = queue.shift();
        if( nextMsg ) {
            aStreams[0].write( nextMsg );
            flushQueue();
        }
    }
}

function writeLoggerMessage( level, msg, data ) {
    var params = { module: 'logger', level: level, message: msg };
    if( data )
        params.data = data;
    writeMessageParams( params );
}

/**
 * Set log target by pushing the logger onto the stack of loggers. Defaults to console.
 * @param name Name of log target. Currently supports the following targets: [ 'sos' ]
 * @param options contains:
 *      type - one of 'sos', 'file', or 'console'
 *      path - path to file, for type file
 *      bIncludeSessionId - whether to include sessionId
 *      dateFormat - one of 'ISO' for 'formatMS'
 */
module.exports.setLogger = function( options ) {

    var bValid = false;
    if( options && options.type === 'sos' && aStreams[0].type !== 'sos' )
        bValid = true;
    else if( options && options.type === 'file' && aStreams[0].type !== 'sos' && options.path )
        bValid = true;
    else if( options && options.type === 'console' )
        bValid = true;

    if( bValid ) {
        var Logger = require('./' + options.type );
        var stream = new Logger( options );
        writeLoggerMessage( "info", "Setting logger to " + stream );
        aStreams[0].end();
        aStreams.unshift( stream );
        stream.open( onSuccess, onError, onClose );

        function onSuccess() {
            stream.clear();
            writeLoggerMessage( "info", "Set logger to " + stream );
        };

        function onError(err) {
            writeLoggerMessage( "Tried but failed to set logger to " + stream + ": " + err );
            popLogger();
        };

        function onClose() {
            writeLoggerMessage( "Logger " + stream + " closed" );
            popLogger();
        }

    } else {
        writeLoggerMessage( "error", ("Unsupported setLogger operation when current logger is " + aStreams[0].type), { options: options } );
    }
};

module.exports.getLogger = function() {
    return aStreams[0];
};

module.exports.popLogger = popLogger;
var popLogger = function() {

    if( aStreams.length > 1 ) {
        var discardStream = aStreams.shift();
        discardStream.destroy();
        var stream = aStreams[0];
        writeLoggerMessage( "info", "Restoring previous " + stream + " logger" );
        aStreams[0].open( onSuccess, onError, onClose );

        function onSuccess() {
            writeLoggerMessage( "info", "Set logger to " + stream );
        };

        function onError(err) {
            writeLoggerMessage( "Tried but failed to set logger to " + stream + ": " + err );
            popLogger();
        };

        function onClose() {
            writeLoggerMessage( "Logger " + stream + " closed" );
            popLogger();
        }
    } else {
        writeLoggerMessage( "warn", "Aborting popLogger because no more loggers in stack" );
    }

};

<commit_msg>Added parameters to date method.<commit_after>/*************************************************************************
 * ARMOR5 CONFIDENTIAL
 * Copyright 2012 Armor5, Inc. All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains the property
 * of Armor5, Inc. and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Armor5, Inc.
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material is
 * strictly forbidden unless prior written permission is obtained from
 * Armor5, Inc..
 **************************************************************************/

/**
 * Logging module. Shows time and log level (debug, info, warn, error).
 * Time is shown in milliseconds since this module was first initialized.
 * Usage:
 * 		var log = require('../lib/logger').get('logtest');
 *		log.info( 'Message: %s', 'my message');
 */

const LEVEL_ORDER = [ 'verbose', 'debug', 'info', 'warn', 'error', 'fatal' ];
const DEFAULT_BUFFER_DURATION = 1000; // ms

var util = require('util');
var DateUtil = require('./dateutil');
var ConsoleStream = require('./console');

// Static containing the time that this module was first initialized.
// Modules are loaded only once, so this will only be set once.
var t0 = (new Date()).getTime();

// Static stack containing stream where output should be written
var aStreams = [ new ConsoleStream() ];

// Static global holds a queue of messages that may build up while we are switching streams
// Streams do their own buffering to their own output
var queue = [];

// Static buffer duration
var gBufferDuration = DEFAULT_BUFFER_DURATION;

// Static global log level
var gLogLevel = 'debug';

// Static custom callback to use if an object is passed in as first parameter of log method
// var gGetSessionIdCallback;

var Logger = function (modulename) {

    var self = this;
	this.moduleName = modulename;
	this.logLevel;
    this.logData;
    this.logAction;

    /**
	 * Log an info message. The message can contain arguments (e.g 'Hello %s', 'world')
	 */
	this.info = function() {
        return self.logArgs( 'info', Array.prototype.slice.call(arguments) );
	};

	this.warn = function() {
        return self.logArgs( 'warn', Array.prototype.slice.call(arguments) );
	};

	this.debug = function() {
        return self.logArgs( 'debug', Array.prototype.slice.call(arguments) );
	};

	this.verbose = function() {
        return self.logArgs( 'verbose', Array.prototype.slice.call(arguments) );
	};

    this.error = function() {
        return self.logArgs( 'error', Array.prototype.slice.call(arguments) );
    };

    this.fatal = function() {
        return self.logArgs( 'fatal', Array.prototype.slice.call(arguments) );
    };

    this.separator = function() {
        if( self.isAboveLevel('info') ) {
            self._writeMessage( 'info', "######################################################################" );
        }
        return this;
    };

    this.data = function(key,value) {
        if( value && (typeof key === 'string' || typeof key === 'number') ) {
            if( !self.logData)
                self.logData = {};
            self.logData[key] = value;
        } else {
            self.logData = key;
        }
        return self;
    };

    this.date = function(d,s) {
        if( self.isAboveLevel('info') ) {
            d = d || new Date();
            self.data( 'localtime', DateUtil.toISOLocalString(d) );
            self.data( 'utctime', d.toISOString() );
            //var msg = util.format( "=== CURRENT TIME  %s ====", DateUtil.toISOLocalString(d) );
            self.logArgs( 'info', [s] );
//			var logMsg = util.format( "[%s] INFO: %s - === CURRENT TIME  %s ====", DateUtil.formatMS(d.getTime()-t0,0), (this.moduleName ? this.moduleName : ""), DateUtil.toISOLocalString(d) );
//			writeMessage( logMsg );
        }
        return self;
    };

    // Helper, level must be set, args must be an array, but can be empty
    this.logArgs = function( level, args ) {
        if( !args.length )
            args.unshift('');
        else if( args.length && ( args[0] === undefined || args[0] === null ) )
            args.shift();
        args.unshift( level );
        return self.log.apply( this, args );
    };

    /**
	 * Output a log message. This function is suitable for providing to classes that require logging callbacks.
     * It can also be used for multiline (folded) log messages.
     * Example: log.log( 'info', req, "Found %d lines", iLines );
     * @param level One of warn, debug, error or info. Defaults to info if not present.
     * @param object Optional object that has a callback gGetSessionIdCallback
	 * @param msg The message String, or an array of strings. Will be formatted
	 */
	this.log = function() {
        var args = Array.prototype.slice.call(arguments);
        if( args.length ) {
            if( args.length === 1 )
                args.unshift( 'info' );
            if( self.isAboveLevel(args[0]) )
                self._writeMessage.apply( this, args );
        }
		return self;
	};

//    this.hasSessionObjAsNthEntry = function(args,index) {
//        if( index === undefined )
//            index = 0;
//        if( gGetSessionIdCallback && args.length > 1 && (typeof args[index] === 'object') && ( typeof args[index][gGetSessionIdCallback] === 'function') )
//            return true;
//        return false;
//    };

    // Expects level, msg params
    this._writeMessage = function( level, msg ) {
        var args = Array.prototype.slice.call(arguments);
        if( args.length > 1 ) {
            var params = { module: self.moduleName };
            params.level = args.shift();
            if( self.logData ) {
                params.data = self.logData;
                delete self.logData;
            }
            if( self.logAction ) {
                params.action = self.logAction;
                delete self.logAction;
            }
            if( args.length === 1 && (args[0] instanceof Array) ) {
                params.message = [];
                for( var idx=0; idx<args[0].length; ++idx ) {
                    params.message.push( util.format.apply(this, (args[0][idx] instanceof Array) ? args[0][idx] : [args[0][idx]] ) );
                }
            } else {
                params.message = util.format.apply( this, args );
            }
            writeMessageParams( params );
        }
    };

	// Not called. Placeholder in case we ever support managed shutdown
	this.destroy = function() {
        while( aStreams.length ) {
            var stream = aStreams.shift();
            if( stream ) {
                stream.end();
                stream.destroy();
            }
        }
	};

	/**
	 * Set the log level for this object. This overrides the global log level for this object.
	 */
	this.setLogLevel = function(level) {
		self.logLevel = level;
		return this;
	}

	/**
	 * Return true if the level is equal to or greater then the reference, or if reference is null
	 */
	this.isAboveLevel = function( level ) {
		var reference = self.logLevel || gLogLevel;
		if( LEVEL_ORDER.indexOf(level) >= LEVEL_ORDER.indexOf(reference) )
			return true;
		return false;
	};

};

//function timeDiff() {
//    return (new Date()).getTime() - t0;
//}

/**
 * Get the time at which the module was initialized
 * @return {Number} Start time in milliseconds
 */
module.exports.getStartTime = function() {
    return t0;
};

/**
 * Shortcut to util.format()
 */
module.exports.format = function() {
    return util.format.apply(this,arguments);
};

/**
 * Return an instance of the logger that has the module name set.
 */
module.exports.get = function(moduleName) {
	return new Logger(moduleName);
};

/**
 * Set log level globally
 */
module.exports.setGlobalLogLevel = function(level) {
    gLogLevel = level;
};

/**
 * If an object is passed in as the first parameter of the log method, and there are subsequent
 * objects in the argument list, then test if that object has this function assigned and, if it does
 * call it to return a string that is to be included in the log message string as the a session ID.
 * @param fnName The object's function name to be called
 */
//module.exports.setSessionIdCallback = function( fnName ) {
//    gGetSessionIdCallback = fnName;
//}

/**
 * Write a raw message. We queue messages to handle the moment in time while we are switching
 * streams and the new stream is not ready yet. We do queuing while we wait for it to be ready.
 * You can completely bypass creating a logger instance in your class if you use this call directly,
 * In this situation the log level filtering will be established by the global log level (gLogLevel).
 * @param msgParams includes:
 *      level - Must be one of LEVEL_ORDER values, all lower case
 *      sid - (Optional) sessionID to display
 *      module - (Optional) Module descriptor to display (usually of form route.obj.function)
 *      time - (Optional) A date object with the current time, will be filled in if not provided
 *      timeDiff - (Optional) The difference in milliseconds between 'time' and when the application was
 *          started, based on reading Logger.getStartTime()
 *      message - A string or an array of strings. If an array the string will be printed on multiple lines
 *          where supported (e.g. SOS). The string must already formatted (e.g.. no '%s')
 */
module.exports.logMessage = writeMessageParams;
function writeMessageParams( msgParams ) {
    if( msgParams ) {
        if( !msgParams.level )
            msgParams.level = 'info';
        if( gIsAboveLevel(msgParams.level) ) {
            if( !msgParams.time )
                msgParams.time = new Date();
            if( !msgParams.timeDiff )
                msgParams.timeDiff = msgParams.time.getTime() - t0;
            queue.push( msgParams );
        }
        if( msgParams.length && msgParams.message && msgParams.message.length > msgParams.length )
            msgParams.message = msgParams.message.substr(0,msgParams.length) + "...";
    }
    flushQueue();
};

/**
 * Return true if the level is equal to or greater then the globally set log level
 */
function gIsAboveLevel( level ) {
    if( LEVEL_ORDER.indexOf(level) >= LEVEL_ORDER.indexOf(gLogLevel) )
        return true;
    return false;
};

function flushQueue() {
    if( aStreams[0].ready ) {
        var nextMsg = queue.shift();
        if( nextMsg ) {
            aStreams[0].write( nextMsg );
            flushQueue();
        }
    }
}

function writeLoggerMessage( level, msg, data ) {
    var params = { module: 'logger', level: level, message: msg };
    if( data )
        params.data = data;
    writeMessageParams( params );
}

/**
 * Set log target by pushing the logger onto the stack of loggers. Defaults to console.
 * @param name Name of log target. Currently supports the following targets: [ 'sos' ]
 * @param options contains:
 *      type - one of 'sos', 'file', or 'console'
 *      path - path to file, for type file
 *      bIncludeSessionId - whether to include sessionId
 *      dateFormat - one of 'ISO' for 'formatMS'
 */
module.exports.setLogger = function( options ) {

    var bValid = false;
    if( options && options.type === 'sos' && aStreams[0].type !== 'sos' )
        bValid = true;
    else if( options && options.type === 'file' && aStreams[0].type !== 'sos' && options.path )
        bValid = true;
    else if( options && options.type === 'console' )
        bValid = true;

    if( bValid ) {
        var Logger = require('./' + options.type );
        var stream = new Logger( options );
        writeLoggerMessage( "info", "Setting logger to " + stream );
        aStreams[0].end();
        aStreams.unshift( stream );
        stream.open( onSuccess, onError, onClose );

        function onSuccess() {
            stream.clear();
            writeLoggerMessage( "info", "Set logger to " + stream );
        };

        function onError(err) {
            writeLoggerMessage( "Tried but failed to set logger to " + stream + ": " + err );
            popLogger();
        };

        function onClose() {
            writeLoggerMessage( "Logger " + stream + " closed" );
            popLogger();
        }

    } else {
        writeLoggerMessage( "error", ("Unsupported setLogger operation when current logger is " + aStreams[0].type), { options: options } );
    }
};

module.exports.getLogger = function() {
    return aStreams[0];
};

module.exports.popLogger = popLogger;
var popLogger = function() {

    if( aStreams.length > 1 ) {
        var discardStream = aStreams.shift();
        discardStream.destroy();
        var stream = aStreams[0];
        writeLoggerMessage( "info", "Restoring previous " + stream + " logger" );
        aStreams[0].open( onSuccess, onError, onClose );

        function onSuccess() {
            writeLoggerMessage( "info", "Set logger to " + stream );
        };

        function onError(err) {
            writeLoggerMessage( "Tried but failed to set logger to " + stream + ": " + err );
            popLogger();
        };

        function onClose() {
            writeLoggerMessage( "Logger " + stream + " closed" );
            popLogger();
        }
    } else {
        writeLoggerMessage( "warn", "Aborting popLogger because no more loggers in stack" );
    }

};

<|endoftext|>


<commit_before>bt.Widget.Download = (function() {

  var createDefaults = function() {
    return {
      _id       : (Math.random() * 1E17).toString(16),
      name      : '',
      url       : undefined,
      elem      : undefined,
      buttons   : {
        download  : ['Download %s', 'Loading\u2026'],
        play      : ['Open %s',     'Reopen %s']
      },
      template  : undefined,
      // See documentation for details about working with callbacks.
      callbacks : {
        addTorrent : function() {
          var that = this;
          $(this.elem).progressbar('destroy').empty();
          this.progressBar = bt.progressManager.createBar({
            id   : that.url,
            elem : that.elem
          }, (function() {
            var callback = function() {
              that.callbacks.dispatch('progressBar');
            };
            callback.persona = that;
            return callback;
          })());
        },
        progressBar : (function() {
          var playClick = function() {
            _.sortBy(
              _.values(bt.torrent.get(this.url).file.all()),
              function(file){return 1-file.properties.get("size")}
            )[0].open();
            // XXX The following callback should be triggered by above open.
            if ('function' === typeof this.callbacks.openFile) {
              this.callbacks.dispatch('openFile');
            }
          };
          return function() {
            var that = this, templateProvided = false;
            $(this.elem).progressbar('destroy').empty();
            if (this.template) {
              var template = $('
' +
                bt.template(this.template, { settings : this }) + '
');
              var playTemplate = template.find('.play');
              if (0 < playTemplate.length) {
                templateProvided = true;
                playTemplate.appendTo(this.elem);
                var clickable = playTemplate.find('.clickable');
                if (0 === clickable.length) { clickable = playTemplate; }
                clickable.click(function() {
                  $(that.elem).html(template.find('.replay'))
                    .click(function(){playClick.call(that);});
                  playClick.call(that);
                });
              }
            }
            if (! templateProvided) {
              var button = $('<button/>').appendTo(this.elem);
              button
                .text(sprintf(this.buttons.play[0], this.name))
                .click(function() {
                  $(this).text(sprintf(that.buttons.play[1], that.name));
                  playClick.call(that);
                });
            }
          };
        })()
      }
    };
  };

  var createError = function(settings) {
    var e = _.clone(settings);
    e.prototype = new Error;
    return e;
  };

  var init = function(settings) {
    var that = this;

    // Check for error conditions.
    if(!(this instanceof bt.Widget.Download)) {
      throw new createError({
        name: 'InvocationError',
        message: 'Widget.Download constructor must create a new instance.'
      });
    }

    // Allow abreviated settings style as URL string instead of an object.
    if ('string' === typeof settings ) settings = { url: settings };

    // Deep-clone defaults and deep-extend user settings into this.settings.
    this.settings = $.extend(true, {}, createDefaults.call(this), settings);

    // Create a default target element node if none has been provided.
    if (!this.settings.elem) {
      this.settings.elem = $('
').appendTo('body')[0];
    }
    $(this.settings.elem).addClass('bt-widget bt-download-widget');

    // The second value in button-text arrays is onclick.
    _.each(this.settings.buttons, function(v, k) {
      if ('string' === typeof that.settings.buttons[k]) {
        that.settings.buttons[k]= [
          that.settings.buttons[k],
          that.settings.buttons[k] ];
      }
    });

    // Give settings.callbacks the methods add and dispatch since they have no
    // access to this. Differentiate callbacks by dlw instance settings _id.
    this.settings.callbacks.add = function(category, handler) {
      that.addCallback.call(that, that.settings._id + category, handler);
    }
    this.settings.callbacks.dispatch = function(category) {
      that.dispatchCallbacks.call(that, that.settings._id + category);
    }
    this.settings.callbacks.remove = function(category) {
      that.removeCallbacks.call(that, that.settings._id + category);
    }
    var callbacksAccess = ['add', 'dispatch', 'remove'];

    // Callbacks get default persona of the settings object. You can override
    // this by giving the callback function a persona property.
    _.each(this.settings.callbacks, function(cbFn, cbName) {
      if ('function' === typeof cbFn &&
        -1 === _.indexOf(callbacksAccess, cbName)) {
          cbFn.persona = cbFn.persona || that.settings;
          that.settings.callbacks.add(cbName, cbFn);
        }
    });

    return settings;
  }

  var Result = function(settings) {
    arguments.callee.check('bt.Widget.Download', arguments, 'Os');
    settings = init.call(this, settings);
    try {
      var that = this, tor = bt.torrent.get(settings.url);
    } catch(err) {
      var that = this, tor = undefined;
    }

    // Check to see current download state of torrent. Display a button,
    // progress-bar, or play button accordingly.
    if ('undefined' === typeof tor) {
      // A new torrent
      var templateProvided = false;
      if (settings.template) {
        var template = $('
' +
          bt.template(settings.template, this) + '
');
        var dlTemplate = template.find('.download');
        if (0 < dlTemplate.length) {
          templateProvided = true;
          dlTemplate.appendTo(settings.elem);
          var clickable = dlTemplate.find('.clickable');
          if (0 === clickable.length) { clickable = dlTemplate; }
          clickable.click(function() {
            var settings = that.settings;
            $(settings.elem).html(template.find('.loading'));
            settings.callbacks.dispatch('addingTorrent');
            bt.add.torrent(settings.url, function() {
              settings.callbacks.dispatch('addTorrent');
            });
          });
        }
      }
      if (! templateProvided) {
        var button = $('<button/>').appendTo(this.settings.elem)
          .text(sprintf(this.settings.buttons.download[0], this.settings.name))
          .click(function() {
            var settings = that.settings;
            button
              .attr('disabled', true)
              .text(sprintf(settings.buttons.download[1], settings.name));
            bt.add.torrent(settings.url, function() {
              that.settings.callbacks.dispatch('addTorrent');
            });
          });
      }
    }
    else {
      if (1000 > tor.properties.get('progress') ) {
        // Download in progress. No need to add, so go to its callback.
        that.settings.callbacks.dispatch('addTorrent');
      }
      else {
        // Download complete. No need for a progress-bar, so go to its callback.
        that.settings.callbacks.dispatch('progressBar');
      }
    }
  };
  Result.prototype = new bt.Widget('Download');
  return Result;
})();
<commit_msg>Converting "click" alias to "bind('click')" because bind events are stackable and click alias events aren't.<commit_after>bt.Widget.Download = (function() {

  var createDefaults = function() {
    return {
      _id       : (Math.random() * 1E17).toString(16),
      name      : '',
      url       : undefined,
      elem      : undefined,
      buttons   : {
        download  : ['Download %s', 'Loading\u2026'],
        play      : ['Open %s',     'Reopen %s']
      },
      template  : undefined,
      // See documentation for details about working with callbacks.
      callbacks : {
        addTorrent : function() {
          var that = this;
          $(this.elem).progressbar('destroy').empty();
          this.progressBar = bt.progressManager.createBar({
            id   : that.url,
            elem : that.elem
          }, (function() {
            var callback = function() {
              that.callbacks.dispatch('progressBar');
            };
            callback.persona = that;
            return callback;
          })());
        },
        progressBar : (function() {
          var playClick = function() {
            _.sortBy(
              _.values(bt.torrent.get(this.url).file.all()),
              function(file){return 1-file.properties.get("size")}
            )[0].open();
            // XXX The following callback should be triggered by above open.
            if ('function' === typeof this.callbacks.openFile) {
              this.callbacks.dispatch('openFile');
            }
          };
          return function() {
            var that = this, templateProvided = false;
            $(this.elem).progressbar('destroy').empty();
            if (this.template) {
              var template = $('
' +
                bt.template(this.template, { settings : this }) + '
');
              var playTemplate = template.find('.play');
              if (0 < playTemplate.length) {
                templateProvided = true;
                playTemplate.appendTo(this.elem);
                var clickable = playTemplate.find('.clickable');
                if (0 === clickable.length) { clickable = playTemplate; }
                clickable.bind('click', function() {
                  $(that.elem).html(template.find('.replay'))
                    .bind('click', function(){playClick.call(that);});
                  playClick.call(that);
                });
              }
            }
            if (! templateProvided) {
              var button = $('<button/>').appendTo(this.elem);
              button
                .text(sprintf(this.buttons.play[0], this.name))
                .bind('click', function() {
                  $(this).text(sprintf(that.buttons.play[1], that.name));
                  playClick.call(that);
                });
            }
          };
        })()
      }
    };
  };

  var createError = function(settings) {
    var e = _.clone(settings);
    e.prototype = new Error;
    return e;
  };

  var init = function(settings) {
    var that = this;

    // Check for error conditions.
    if(!(this instanceof bt.Widget.Download)) {
      throw new createError({
        name: 'InvocationError',
        message: 'Widget.Download constructor must create a new instance.'
      });
    }

    // Allow abreviated settings style as URL string instead of an object.
    if ('string' === typeof settings ) settings = { url: settings };

    // Deep-clone defaults and deep-extend user settings into this.settings.
    this.settings = $.extend(true, {}, createDefaults.call(this), settings);

    // Create a default target element node if none has been provided.
    if (!this.settings.elem) {
      this.settings.elem = $('
').appendTo('body')[0];
    }
    $(this.settings.elem).addClass('bt-widget bt-download-widget');

    // The second value in button-text arrays is onclick.
    _.each(this.settings.buttons, function(v, k) {
      if ('string' === typeof that.settings.buttons[k]) {
        that.settings.buttons[k]= [
          that.settings.buttons[k],
          that.settings.buttons[k] ];
      }
    });

    // Give settings.callbacks the methods add and dispatch since they have no
    // access to this. Differentiate callbacks by dlw instance settings _id.
    this.settings.callbacks.add = function(category, handler) {
      that.addCallback.call(that, that.settings._id + category, handler);
    }
    this.settings.callbacks.dispatch = function(category) {
      that.dispatchCallbacks.call(that, that.settings._id + category);
    }
    this.settings.callbacks.remove = function(category) {
      that.removeCallbacks.call(that, that.settings._id + category);
    }
    var callbacksAccess = ['add', 'dispatch', 'remove'];

    // Callbacks get default persona of the settings object. You can override
    // this by giving the callback function a persona property.
    _.each(this.settings.callbacks, function(cbFn, cbName) {
      if ('function' === typeof cbFn &&
        -1 === _.indexOf(callbacksAccess, cbName)) {
          cbFn.persona = cbFn.persona || that.settings;
          that.settings.callbacks.add(cbName, cbFn);
        }
    });

    return settings;
  }

  var Result = function(settings) {
    arguments.callee.check('bt.Widget.Download', arguments, 'Os');
    settings = init.call(this, settings);
    try {
      var that = this, tor = bt.torrent.get(settings.url);
    } catch(err) {
      var that = this, tor = undefined;
    }

    // Check to see current download state of torrent. Display a button,
    // progress-bar, or play button accordingly.
    if ('undefined' === typeof tor) {
      // A new torrent
      var templateProvided = false;
      if (settings.template) {
        var template = $('
' +
          bt.template(settings.template, this) + '
');
        var dlTemplate = template.find('.download');
        if (0 < dlTemplate.length) {
          templateProvided = true;
          dlTemplate.appendTo(settings.elem);
          var clickable = dlTemplate.find('.clickable');
          if (0 === clickable.length) { clickable = dlTemplate; }
          clickable.click(function() {
            var settings = that.settings;
            $(settings.elem).html(template.find('.loading'));
            settings.callbacks.dispatch('addingTorrent');
            bt.add.torrent(settings.url, function() {
              settings.callbacks.dispatch('addTorrent');
            });
          });
        }
      }
      if (! templateProvided) {
        var button = $('<button/>').appendTo(this.settings.elem)
          .text(sprintf(this.settings.buttons.download[0], this.settings.name))
          .click(function() {
            var settings = that.settings;
            button
              .attr('disabled', true)
              .text(sprintf(settings.buttons.download[1], settings.name));
            bt.add.torrent(settings.url, function() {
              that.settings.callbacks.dispatch('addTorrent');
            });
          });
      }
    }
    else {
      if (1000 > tor.properties.get('progress') ) {
        // Download in progress. No need to add, so go to its callback.
        that.settings.callbacks.dispatch('addTorrent');
      }
      else {
        // Download complete. No need for a progress-bar, so go to its callback.
        that.settings.callbacks.dispatch('progressBar');
      }
    }
  };
  Result.prototype = new bt.Widget('Download');
  return Result;
})();
<|endoftext|>


<commit_before>'use strict'

// Setup
const path = require('path')
const fork = require('child_process').fork
const logger = {
  debug: (err) => logIt(err, 'debug'),
  info: (err) => logIt(err, 'info'),
  warn: (err) => logIt(err, 'warn'),
  fatal: (err) => logIt(err, 'fatal')
}
// Globals
let commitLogToFile = fork(path.join(__dirname, 'logger_to_file.js'))
let appName = 'oacpApp'
let logLevel = 'warn'
let logBase = __dirname
let toConsole = true
let toFile = true
let toDb = false

// Get new fork if this one closes
commitLogToFile.on('close', () => {
  commitLogToFile = fork(path.join(__dirname, 'logger_to_file.js'))
})

// Exports
module.exports = logger
module.exports.setOpts = (opts) => {
  opts = opts || {}
  appName = opts.appName || appName
  logLevel = opts.logLevel || logLevel
  logBase = opts.logBase || logBase
  toConsole = opts.toConsole
  toFile = opts.toFile
  toDb = opts.toDb
}

// Helpers
function today () {
  let d = new Date()
  return (
    `0${d.getMonth() + 1}`.slice(-2) + '_' +
    `0${d.getDate()}`.slice(-2) + '_' +
    d.getFullYear()
  )
}

function levelToInt (level) {
  switch (level) {
    case 'info': return 1
    case 'warn': return 2
    case 'fatal': return 3
    default: return 0
  }
}

function logIt (err, level) {
  if (levelToInt(level) < levelToInt(logLevel)) return
  let logFilePath = path.join(logBase, `${appName}_${today()}.json`)
  let log = {}
  log.time = Date.now()
  log.level = level
  if (typeof err === 'string') log.message = err
  else {
    if (err.name) log.name = err.name
    if (err.message) log.message = err.message
    if (err.fileName) log.fileName = err.fileName
    if (err.lineNumber) log.lineNumber = err.lineNumber
    if (err.stack) log.stack = err.stack
  }
  if (!log.name && !log.message) log.message = err
  let logText = level.toUpperCase() + ':'
  if (typeof log.message === 'object') return console.log(log.message)
  if (log.name) logText += '\nName: ' + log.name
  if (log.message) logText += '\nMessage: ' + log.message
  if (log.fileName) logText += '\nFilename: ' + log.fileName
  if (log.lineNumber) logText += '\nLine Number: ' + log.lineNumber
  if (log.stack) logText += '\nStack:\n' + log.stack
  logText += '\n'
  if (toFile) {
    try {
      commitLogToFile.send({logFilePath, log})
    } catch (e) {
      commitLogToFile = fork(path.join(__dirname, 'logger_to_file.js'))
    }
  }
  if (toDb) {
    // not implemented
  }
  if (toConsole) {
    switch (level) {
      case 'info': return console.info(logText)
      case 'warn': return console.warn(logText)
      case 'fatal': return console.error(logText)
      default: return console.log(logText)
    }
  }
}
<commit_msg>Display date in logger console output<commit_after>'use strict'

// Setup
const path = require('path')
const fork = require('child_process').fork
const errProps = [
  'name',
  'message',
  'fileName',
  'lineNumber',
  'stack'
]
const logger = {
  debug: (err) => logIt(err, 'debug'),
  info: (err) => logIt(err, 'info'),
  warn: (err) => logIt(err, 'warn'),
  fatal: (err) => logIt(err, 'fatal')
}
// Globals
let commitLogToFile = fork(path.join(__dirname, 'logger_to_file.js'))
let appName = 'oacpApp'
let logLevel = 'warn'
let logBase = __dirname
let toConsole = true
let toFile = true
let toDb = false

// Get new fork if this one closes
commitLogToFile.on('close', () => {
  commitLogToFile = fork(path.join(__dirname, 'logger_to_file.js'))
})

// Exports
module.exports = logger
module.exports.setOpts = (opts) => {
  opts = opts || {}
  appName = opts.appName || appName
  logLevel = opts.logLevel || logLevel
  logBase = opts.logBase || logBase
  toConsole = opts.toConsole
  toFile = opts.toFile
  toDb = opts.toDb
}

// Helpers
function today () {
  let d = new Date()
  return (
    `0${d.getMonth() + 1}`.slice(-2) + '_' +
    `0${d.getDate()}`.slice(-2) + '_' +
    d.getFullYear()
  )
}

function levelToInt (level) {
  switch (level) {
    case 'info': return 1
    case 'warn': return 2
    case 'fatal': return 3
    default: return 0
  }
}

function logIt (err, level) {
  if (levelToInt(level) < levelToInt(logLevel)) return
  let logFilePath = path.join(logBase, `${appName}_${today()}.json`)
  let log = {}
  log.time = Date.now()
  log.level = level
  if (typeof err === 'string') log.message = err
  else errProps.forEach((p) => { if (err[p]) log[p] = err[p] })
  if (!log.name && !log.message) log.message = err
  let logText = level.toUpperCase() + ':'
  if (typeof log.message === 'object') return console.log(log.message)
  logText += `\nTimestamp: ${new Date(log.time).toLocaleString()}`
  if (log.name) logText += `\nName: ${log.name}`
  if (log.message) logText += `\nMessage: ${log.message}`
  if (log.fileName) logText += `\nFilename: ${log.fileName}`
  if (log.lineNumber) logText += `\nLine Number: ${log.lineNumber}`
  if (log.stack) logText += `\nStack:\n ${log.stack}`
  logText += '\n'
  if (toFile) {
    try {
      commitLogToFile.send({logFilePath, log})
    } catch (e) {
      commitLogToFile = fork(path.join(__dirname, 'logger_to_file.js'))
    }
  }
  if (toDb) {
    // not implemented
  }
  if (toConsole) {
    switch (level) {
      case 'info': return console.info(logText)
      case 'warn': return console.warn(logText)
      case 'fatal': return console.error(logText)
      default: return console.log(logText)
    }
  }
}
<|endoftext|>


<commit_before>var winston = require('winston'),
    path = require('path');

var DEFAULT_LOG = 'browsertime';

module.exports = {
  getLog: function(name) {
    name = name || DEFAULT_LOG;

    return winston.loggers.get(name);
  },

  addLog: function(name, options) {
    name = name || DEFAULT_LOG;
    options = options || {};

    if (winston.loggers.has(name)) {
      return winston.loggers.get(name);
    }

    var logPath = path.join(options.logDir || '', name + '.log');
    var logLevel = options.verbose ? 'verbose' : 'info';

    var winstonOpts = {
      file: {
        level: logLevel,
        json: false,
        label: name,
        filename: logPath
      },
      console: {
        level: logLevel,
        colorize: !options.noColor,
        silent: !!options.silent
      }
    };

    return winston.loggers.add(name, winstonOpts);
  }
};<commit_msg>Remove redundant [browsertime] on each log line.<commit_after>var winston = require('winston'),
    path = require('path');

var DEFAULT_LOG = 'browsertime';

module.exports = {
  getLog: function(name) {
    name = name || DEFAULT_LOG;

    return winston.loggers.get(name);
  },

  addLog: function(name, options) {
    name = name || DEFAULT_LOG;
    options = options || {};

    if (winston.loggers.has(name)) {
      return winston.loggers.get(name);
    }

    var logPath = path.join(options.logDir || '', name + '.log');
    var logLevel = options.verbose ? 'verbose' : 'info';

    var winstonOpts = {
      file: {
        level: logLevel,
        json: false,
        filename: logPath
      },
      console: {
        level: logLevel,
        colorize: !options.noColor,
        silent: !!options.silent
      }
    };

    return winston.loggers.add(name, winstonOpts);
  }
};<|endoftext|>


<commit_before>var path = require('path'),
    winston = require('winston');

var logDir = process.env.NODE_LOG_DIR || path.join(process.cwd(), 'log');
var environment = process.env.NODE_ENV || 'development';

var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.File)({
      filename: path.join(logDir, environment + '.log'),
      json: false,
    })
  ],
  levels: winston.config.syslog.levels,
});

module.exports = logger;
<commit_msg>Fix winston syslog levels that was preventing errors from showing up.<commit_after>var path = require('path'),
    winston = require('winston');

var logDir = process.env.NODE_LOG_DIR || path.join(process.cwd(), 'log');
var environment = process.env.NODE_ENV || 'development';

var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.File)({
      filename: path.join(logDir, environment + '.log'),
      json: false,
    })
  ],

  // Use syslog levels, but don't use Winston's built-in levels, since those
  // are currently broken: https://github.com/flatiron/winston/issues/249
  // levels: winston.config.syslog.levels,
  levels: {
    debug: 0,
    info: 1,
    notice: 2,
    warning: 3,
    error: 4,
    crit: 5,
    alert: 6,
    emerg: 7
  },
});

module.exports = logger;
<|endoftext|>


<commit_before>'use strict';
var bunyan = require('bunyan');
var config = require('config');
var LogglyLogger = require('./loggly_logger');

var streams = [];
var logLevel = config.has('Hoist.debug') && config.get('Hoist.debug') ? 'debug' : 'info';

if (typeof describe === 'undefined') {
  streams.push({
    name: 'console',
    level: logLevel,
    stream: process.stdout
  });
}
if (config.has('Hoist.loggly')) {
  streams.push({
    type: 'raw',
    stream: new LogglyLogger()
  });
}
var appName = 'no application name set';
if (config.has('Hoist.application.name')) {
  appName = config.get('Hoist.application.name');
}
var logger = bunyan.createLogger({
  name: appName,
  streams: streams
});
logger.alert = function () {

};
logger.keen = function () {

};
if (config.has('Hoist.raygun.enabled') && config.get('Hoist.raygun.enabled')) {
  var raygun = require('raygun');
  var raygunClient = new raygun.Client().init({
    apiKey: config.has('Hoist.raygun.apiKey')
  });
  logger.alert = function (err, applicationId) {
    raygunClient.send(err, {
      hoistApplication: appName,
      applicationId: applicationId
    });
  };
}
if (config.has('Hoist.keenio.projectId') && config.has('Hoist.keenio.writeKey')) {
  var Keen = require('keen.io');
  var keenClient = Keen.configure({
    projectId: config.get('Hoist.keenio.projectId'),
    writeKey: config.has('Hoist.keenio.writeKey')
  });
  logger.keen = function (eventName, eventDetails) {
    keenClient.addEvent(eventName, eventDetails);
  };
}

module.exports = logger;
<commit_msg>ensure keen logs go through<commit_after>'use strict';
var bunyan = require('bunyan');
var config = require('config');
var LogglyLogger = require('./loggly_logger');

var streams = [];
var logLevel = config.has('Hoist.debug') && config.get('Hoist.debug') ? 'debug' : 'info';

if (typeof describe === 'undefined') {
  streams.push({
    name: 'console',
    level: logLevel,
    stream: process.stdout
  });
}
if (config.has('Hoist.loggly')) {
  streams.push({
    type: 'raw',
    stream: new LogglyLogger()
  });
}
var appName = 'no application name set';
if (config.has('Hoist.application.name')) {
  appName = config.get('Hoist.application.name');
}
var logger = bunyan.createLogger({
  name: appName,
  streams: streams
});
logger.alert = function () {

};
logger.keen = function () {

};
if (config.has('Hoist.raygun.enabled') && config.get('Hoist.raygun.enabled')) {
  var raygun = require('raygun');
  var raygunClient = new raygun.Client().init({
    apiKey: config.has('Hoist.raygun.apiKey')
  });
  logger.alert = function (err, applicationId) {
    raygunClient.send(err, {
      hoistApplication: appName,
      applicationId: applicationId
    });
  };
}
if (config.has('Hoist.keenio.projectId') && config.has('Hoist.keenio.writeKey')) {
  var Keen = require('keen.io');
  var keenClient = Keen.configure({
    projectId: config.get('Hoist.keenio.projectId'),
    writeKey: config.has('Hoist.keenio.writeKey')
  });
  logger.keen = function (eventName, eventDetails) {
    keenClient.addEvent(eventName, eventDetails, function (err, res) {
      if (err) {
        logger.error(err);
      }
      logger.info({
        res: res,
        err: err
      }, 'logged to keen');
    });
  };
}

module.exports = logger;
<|endoftext|>


<commit_before>/**
 * Copyright 2014 Netsend.
 *
 * This file is part of Mastersync.
 *
 * Mastersync is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * Mastersync is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with Mastersync. If not, see <https://www.gnu.org/licenses/>.
 */

'use strict';

var fs = require('fs');
var util = require('util');

var posix; // optional, only used if syslog is enabled

// ordered priorities (see POSIX)
var EMERG     = 0;      /* system is unusable */
var ALERT     = 1;      /* action must be taken immediately */
var CRIT      = 2;      /* critical conditions */
var ERR       = 3;      /* error conditions */
var WARNING   = 4;      /* warning conditions */
var NOTICE    = 5;      /* normal but significant condition */
var INFO      = 6;      /* informational */
var DEBUG     = 7;      /* debug-level messages */
var DEBUG2    = 8;      /* more verbose debug-level messages */

var PRIOS = ['EMERG', 'ALERT', 'CRIT', 'ERR', 'WARNING', 'NOTICE', 'INFO', 'DEBUG', 'DEBUG2'];

var ERR_THRESHOLD = 3;      /* priority error or worse */

// ensure a log file is opened in append only mode
function openFile(file, cb) {
  var options = { flags: 'a' };

  switch (typeof file) {
    case 'object':
      process.nextTick(function() {
        if (typeof file.write !== 'function') {
          cb(new TypeError('file must support write'));
          return;
        }
        cb(null, file);
      });
      break;
    case 'number':
      options.fd = file;
      file = '';
      /* falls through */
    case 'string':
      var logFile = fs.createWriteStream(file, options);
      logFile.once('error', cb);
      logFile.once('open', function() {
        cb(null, logFile);
      });
      break;
    default:
      process.nextTick(function() {
        cb(new Error('file not opened'));
      });
  }
}

/**
 * Create a new logger.
 *
 * Note: specify at least one of console, syslog, file, error or silence.
 *
 * @param {Object} [opts]  options, see below
 * @param {Function} cb  first parameter will be an error or null. Second parameter
 *                       will be an boject containing the following functions:
 *     emerg:   log emerg
 *     alert:   log alert
 *     crit:    log crit
 *     err:     log err
 *     warning: log warning
 *     notice:  log notice
 *     info:    log info
 *     debug:   log debug
 *     debug2:  log debug2
 *     getFileStream:  return writable stream for the normal logging file
 *     getErrorStream: return writable stream for the error logging file
 *     close: stop logging and close file handles
 *
 * Options
 *   ident {String, default 'logger'}  name to prepend after the date
 *   console {Boolean, default: false}  whether to log to the console
 *   syslog {Boolean, default false}  whether to log to the system logger
 *   file {String|Number|Object}  log all messages to this file, either a filename,
 *                                file descriptor or writable stream.
 *   error {String|Number|Object}  extra file to log errors only, either a
 *                                 filename, file descriptor or writable stream.
 *   mask {Number, default NOTICE}  set a minimum priority for "file"
 *   silence {Boolean, default false}  whether to suppress logging or not
 */
function logger(opts, cb) {
  if (typeof opts !== 'object') { throw new TypeError('opts must be an object'); }
  if (typeof cb !== 'function') { throw new TypeError('cb must be a function'); }

  if (opts.hasOwnProperty('ident') && typeof opts.ident !== 'string') { throw new TypeError('opts.ident must be a string'); }
  if (opts.hasOwnProperty('file')) {
    if (typeof opts.file === 'object') {
      if (typeof opts.file.write !== 'function') { throw new TypeError('opts.file writable stream must have a write function'); }
    } else if (typeof opts.file !== 'string' && typeof opts.file !== 'number') {
      throw new TypeError('opts.file must be a string or a number');
    }
  }
  if (opts.hasOwnProperty('error')) {
    if (typeof opts.error === 'object') {
      if (typeof opts.error.write !== 'function') { throw new TypeError('opts.error writable stream must have a write function'); }
    } else if (typeof opts.error !== 'string' && typeof opts.error !== 'number') {
      throw new TypeError('opts.error must be a string or a number');
    }
  }

  /* jshint laxcomma: true */

  var ident = opts.ident || 'logger';
  var file = opts.file;
  var error = opts.error;

  var cons = false;
  if (opts.hasOwnProperty('console')) {
    if (typeof opts.console !== 'boolean') { throw new TypeError('opts.console must be a boolean'); }
    cons = opts.console;
  }

  var syslog = false;
  if (opts.hasOwnProperty('syslog')) {
    if (typeof opts.syslog !== 'boolean') { throw new TypeError('opts.syslog must be a boolean'); }
    syslog = opts.syslog;
  }

  var mask = NOTICE;
  if (opts.hasOwnProperty('mask')) {
    if (typeof opts.mask !== 'number') { throw new TypeError('opts.mask must be a priority number'); }
    mask = opts.mask;
  }

  var silence = false;
  if (opts.hasOwnProperty('silence')) {
    if (typeof opts.silence !== 'boolean') { throw new TypeError('opts.silence must be a boolean'); }
    silence = opts.silence;
  }

  if (!cons && !syslog && !file && !error && !silence) { throw new Error('configure at least one logging method'); }

  var logFile, errFile;

  if (syslog) {
    // only require posix if used
    posix = require('posix');
    posix.openlog(ident, { ndelay: true, pid: true }, 'daemon');
  }

  var tasksDone = 0;

  var tasks = [function(cb2) {
    // ensure async even without any other tasks
    process.nextTick(function() {
      tasksDone++;
      cb2();
    });
  }];

  if (file) {
    tasks.push(function(cb2) {
      openFile(file, function(err, f) {
        if (err) { cb2(err); return; }
        logFile = f;

        tasksDone++;
        cb2();
      });
    });
  }

  if (error) {
    tasks.push(function(cb2) {
      openFile(error, function(err, f) {
        if (err) { cb2(err); return; }
        errFile = f;

        tasksDone++;
        cb2();
      });
    });
  }

  // format date
  var start = new Date();
  var startYear   = start.getFullYear();
  var startMonth  = start.getMonth() + 1;
  var startDay    = start.getDate();
  var startHour   = start.getHours();
  var startMinute = start.getMinutes();
  var startSecond = start.getSeconds();

  var YEAR   = 0x01;
  var MONTH  = 0x02;
  var DAY    = 0x04;
  var HOUR   = 0x08;
  var MINUTE = 0x10;
  var SECOND = 0x20;

  var disabled = 0;

  function padTwoDigits(val) {
    return ('00' + val).slice(-2);
  }

  function strFmtTime() {
    var now = new Date();

    var currYear   = now.getFullYear()
      , currMonth  = now.getMonth() + 1
      , currDay    = now.getDate()
      , currHour   = now.getHours()
      , currMinute = now.getMinutes()
      , currSecond = now.getSeconds();

    var result = '';

    if (YEAR & disabled) {
      if (currYear > startYear) {
        disabled = 0x00;
        result += currYear + '-';
      }
    } else {
      result += currYear + '-';
    }

    if (MONTH & disabled) {
      if (currMonth > startMonth) {
        disabled = YEAR;
        result += padTwoDigits(currMonth) + '-';
      }
    } else {
      result += padTwoDigits(currMonth) + '-';
    }

    if (DAY & disabled) {
      if (currDay > startDay) {
        disabled = YEAR + MONTH;
        result += padTwoDigits(currDay) + ' ';
      }
    } else {
      result += padTwoDigits(currDay) + ' ';
    }

    if (HOUR & disabled) {
      if (currHour > startHour) {
        disabled = YEAR + MONTH + DAY;
        result += padTwoDigits(currHour) + ':';
      }
    } else {
      result += padTwoDigits(currHour) + ':';
    }

    if (MINUTE & disabled) {
      if (currMinute > startMinute) {
        disabled = YEAR + MONTH + DAY + HOUR;
        result += padTwoDigits(currMinute) + ':';
      }
    } else {
      result += padTwoDigits(currMinute) + ':';
    }

    if (SECOND & disabled) {
      if (currSecond > startSecond) {
        disabled = YEAR + MONTH + DAY + HOUR + MINUTE;
        result += padTwoDigits(currSecond);
      }
    } else {
      result += padTwoDigits(currSecond);
    }

    return result;
  }

  /**
   * Log to syslog, and/or file and/or err and/or console
   *
   * @param {Number} prio  priority or severity of this message
   * @param {String} msg  message to log
   *   all remaining arguments will be concatenated to msg with a space
   */
  function log() {
    if (arguments[0] > mask || silence) { return; }

    var prio = Array.prototype.slice.call(arguments, 0, 1);
    var msgs = Array.prototype.slice.call(arguments, 1);

    var msg = msgs.join(' ');

    if (syslog) {
      posix.syslog(prio, msg);
    }

    var fmtMsg = strFmtTime() + ' ' + ident + '[' + process.pid + '] ' + prio + ': ' + util.format.apply(this, msgs) + '\n';

    if (logFile) {
      logFile.write(fmtMsg);
    }

    if (errFile && (prio <= ERR_THRESHOLD)) {
      errFile.write(fmtMsg);
    }

    if (cons) {
      if (prio <= ERR_THRESHOLD) {
        process.stderr.write(fmtMsg);
      } else {
        process.stdout.write(fmtMsg);
      }
    }
  }

  function logEmerg()   { Array.prototype.unshift.call(arguments, EMERG);   log.apply(null, arguments); }
  function logAlert()   { Array.prototype.unshift.call(arguments, ALERT);   log.apply(null, arguments); }
  function logCrit()    { Array.prototype.unshift.call(arguments, CRIT);    log.apply(null, arguments); }
  function logErr()     { Array.prototype.unshift.call(arguments, ERR);     log.apply(null, arguments); }
  function logWarning() { Array.prototype.unshift.call(arguments, WARNING); log.apply(null, arguments); }
  function logNotice()  { Array.prototype.unshift.call(arguments, NOTICE);  log.apply(null, arguments); }
  function logInfo()    { Array.prototype.unshift.call(arguments, INFO);    log.apply(null, arguments); }
  function logDebug()   { Array.prototype.unshift.call(arguments, DEBUG);   log.apply(null, arguments); }
  function logDebug2()  { Array.prototype.unshift.call(arguments, DEBUG2);  log.apply(null, arguments); }

  function close(cb2) {
    var tasks2Done = 0;

    var tasks2 = [function(cb3) {
      // ensure async even without any other tasks
      process.nextTick(function() {
        tasks2Done++;
        cb3();
      });
    }];

    logDebug2('closing all logs');

    if (syslog) { posix.closelog(); }

    if (logFile)  {
      tasks2.push(function(cb3) {
        logFile.end(function(err) {
          if (err) { cb3(err); return; }

          tasks2Done++;
          cb3(null);
        });
      });
    }
    if (errFile) {
      tasks2.push(function(cb3) {
        errFile.end(function(err) {
          if (err) { cb3(err); return; }

          tasks2Done++;
          cb3(null);
        });
      });
    }

    tasks2.forEach(function(task) {
      task(function(err) {
        if (err) { cb2(err); return; }
        if (tasks2Done === tasks2.length) {
          cb2();
        }
      });
    });
  }

  tasks.forEach(function(task) {
    task(function(err) {
      if (err) { cb(err); return; }
      if (tasksDone === tasks.length) {
        cb(null, {
          emerg:   logEmerg,
          alert:   logAlert,
          crit:    logCrit,
          err:     logErr,
          warning: logWarning,
          notice:  logNotice,
          info:    logInfo,
          debug:   logDebug,
          debug2:  logDebug2,
          getFileStream: function() { return logFile; },
          getErrorStream: function() { return errFile; },
          close: close
        });
      }
    });
  });
}

module.exports = logger;

module.exports.EMERG     =  EMERG;
module.exports.ALERT     =  ALERT;
module.exports.CRIT      =  CRIT;
module.exports.ERR       =  ERR;
module.exports.WARNING   =  WARNING;
module.exports.NOTICE    =  NOTICE;
module.exports.INFO      =  INFO;
module.exports.DEBUG     =  DEBUG;
module.exports.DEBUG2    =  DEBUG2;

module.exports.levelToPrio = function(name) {
  if (!name) { return null; }

  var idx = PRIOS.indexOf(name.toUpperCase());
  if (~idx) {
    return idx;
  }
  return null;
};

// ensure a log file is opened in append only mode
module.exports.openFile = openFile;
<commit_msg>logger: remove syslog functionality<commit_after>/**
 * Copyright 2014 Netsend.
 *
 * This file is part of Mastersync.
 *
 * Mastersync is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * Mastersync is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with Mastersync. If not, see <https://www.gnu.org/licenses/>.
 */

'use strict';

var fs = require('fs');
var util = require('util');

// ordered priorities (see POSIX)
var EMERG     = 0;      /* system is unusable */
var ALERT     = 1;      /* action must be taken immediately */
var CRIT      = 2;      /* critical conditions */
var ERR       = 3;      /* error conditions */
var WARNING   = 4;      /* warning conditions */
var NOTICE    = 5;      /* normal but significant condition */
var INFO      = 6;      /* informational */
var DEBUG     = 7;      /* debug-level messages */
var DEBUG2    = 8;      /* more verbose debug-level messages */

var PRIOS = ['EMERG', 'ALERT', 'CRIT', 'ERR', 'WARNING', 'NOTICE', 'INFO', 'DEBUG', 'DEBUG2'];

var ERR_THRESHOLD = 3;      /* priority error or worse */

// ensure a log file is opened in append only mode
function openFile(file, cb) {
  var options = { flags: 'a' };

  switch (typeof file) {
    case 'object':
      process.nextTick(function() {
        if (typeof file.write !== 'function') {
          cb(new TypeError('file must support write'));
          return;
        }
        cb(null, file);
      });
      break;
    case 'number':
      options.fd = file;
      file = '';
      /* falls through */
    case 'string':
      var logFile = fs.createWriteStream(file, options);
      logFile.once('error', cb);
      logFile.once('open', function() {
        cb(null, logFile);
      });
      break;
    default:
      process.nextTick(function() {
        cb(new Error('file not opened'));
      });
  }
}

/**
 * Create a new logger.
 *
 * Note: specify at least one of console, file, error or silence.
 *
 * @param {Object} [opts]  options, see below
 * @param {Function} cb  first parameter will be an error or null. Second parameter
 *                       will be an boject containing the following functions:
 *     emerg:   log emerg
 *     alert:   log alert
 *     crit:    log crit
 *     err:     log err
 *     warning: log warning
 *     notice:  log notice
 *     info:    log info
 *     debug:   log debug
 *     debug2:  log debug2
 *     getFileStream:  return writable stream for the normal logging file
 *     getErrorStream: return writable stream for the error logging file
 *     close: stop logging and close file handles
 *
 * Options
 *   ident {String, default 'logger'}  name to prepend after the date
 *   console {Boolean, default: false}  whether to log to the console
 *   file {String|Number|Object}  log all messages to this file, either a filename,
 *                                file descriptor or writable stream.
 *   error {String|Number|Object}  extra file to log errors only, either a
 *                                 filename, file descriptor or writable stream.
 *   mask {Number, default NOTICE}  set a minimum priority for "file"
 *   silence {Boolean, default false}  whether to suppress logging or not
 */
function logger(opts, cb) {
  if (typeof opts !== 'object') { throw new TypeError('opts must be an object'); }
  if (typeof cb !== 'function') { throw new TypeError('cb must be a function'); }

  if (opts.hasOwnProperty('ident') && typeof opts.ident !== 'string') { throw new TypeError('opts.ident must be a string'); }
  if (opts.hasOwnProperty('file')) {
    if (typeof opts.file === 'object') {
      if (typeof opts.file.write !== 'function') { throw new TypeError('opts.file writable stream must have a write function'); }
    } else if (typeof opts.file !== 'string' && typeof opts.file !== 'number') {
      throw new TypeError('opts.file must be a string or a number');
    }
  }
  if (opts.hasOwnProperty('error')) {
    if (typeof opts.error === 'object') {
      if (typeof opts.error.write !== 'function') { throw new TypeError('opts.error writable stream must have a write function'); }
    } else if (typeof opts.error !== 'string' && typeof opts.error !== 'number') {
      throw new TypeError('opts.error must be a string or a number');
    }
  }

  /* jshint laxcomma: true */

  var ident = opts.ident || 'logger';
  var file = opts.file;
  var error = opts.error;

  var cons = false;
  if (opts.hasOwnProperty('console')) {
    if (typeof opts.console !== 'boolean') { throw new TypeError('opts.console must be a boolean'); }
    cons = opts.console;
  }

  var mask = NOTICE;
  if (opts.hasOwnProperty('mask')) {
    if (typeof opts.mask !== 'number') { throw new TypeError('opts.mask must be a priority number'); }
    mask = opts.mask;
  }

  var silence = false;
  if (opts.hasOwnProperty('silence')) {
    if (typeof opts.silence !== 'boolean') { throw new TypeError('opts.silence must be a boolean'); }
    silence = opts.silence;
  }

  if (!cons && !file && !error && !silence) { throw new Error('configure at least one logging method'); }

  var logFile, errFile;

  var tasksDone = 0;

  var tasks = [function(cb2) {
    // ensure async even without any other tasks
    process.nextTick(function() {
      tasksDone++;
      cb2();
    });
  }];

  if (file) {
    tasks.push(function(cb2) {
      openFile(file, function(err, f) {
        if (err) { cb2(err); return; }
        logFile = f;

        tasksDone++;
        cb2();
      });
    });
  }

  if (error) {
    tasks.push(function(cb2) {
      openFile(error, function(err, f) {
        if (err) { cb2(err); return; }
        errFile = f;

        tasksDone++;
        cb2();
      });
    });
  }

  // format date
  var start = new Date();
  var startYear   = start.getFullYear();
  var startMonth  = start.getMonth() + 1;
  var startDay    = start.getDate();
  var startHour   = start.getHours();
  var startMinute = start.getMinutes();
  var startSecond = start.getSeconds();

  var YEAR   = 0x01;
  var MONTH  = 0x02;
  var DAY    = 0x04;
  var HOUR   = 0x08;
  var MINUTE = 0x10;
  var SECOND = 0x20;

  var disabled = 0;

  function padTwoDigits(val) {
    return ('00' + val).slice(-2);
  }

  function strFmtTime() {
    var now = new Date();

    var currYear   = now.getFullYear()
      , currMonth  = now.getMonth() + 1
      , currDay    = now.getDate()
      , currHour   = now.getHours()
      , currMinute = now.getMinutes()
      , currSecond = now.getSeconds();

    var result = '';

    if (YEAR & disabled) {
      if (currYear > startYear) {
        disabled = 0x00;
        result += currYear + '-';
      }
    } else {
      result += currYear + '-';
    }

    if (MONTH & disabled) {
      if (currMonth > startMonth) {
        disabled = YEAR;
        result += padTwoDigits(currMonth) + '-';
      }
    } else {
      result += padTwoDigits(currMonth) + '-';
    }

    if (DAY & disabled) {
      if (currDay > startDay) {
        disabled = YEAR + MONTH;
        result += padTwoDigits(currDay) + ' ';
      }
    } else {
      result += padTwoDigits(currDay) + ' ';
    }

    if (HOUR & disabled) {
      if (currHour > startHour) {
        disabled = YEAR + MONTH + DAY;
        result += padTwoDigits(currHour) + ':';
      }
    } else {
      result += padTwoDigits(currHour) + ':';
    }

    if (MINUTE & disabled) {
      if (currMinute > startMinute) {
        disabled = YEAR + MONTH + DAY + HOUR;
        result += padTwoDigits(currMinute) + ':';
      }
    } else {
      result += padTwoDigits(currMinute) + ':';
    }

    if (SECOND & disabled) {
      if (currSecond > startSecond) {
        disabled = YEAR + MONTH + DAY + HOUR + MINUTE;
        result += padTwoDigits(currSecond);
      }
    } else {
      result += padTwoDigits(currSecond);
    }

    return result;
  }

  /**
   * Log to file and/or err and/or console
   *
   * @param {Number} prio  priority or severity of this message
   * @param {String} msg  message to log
   *   all remaining arguments will be concatenated to msg with a space
   */
  function log() {
    if (arguments[0] > mask || silence) { return; }

    var prio = Array.prototype.slice.call(arguments, 0, 1);
    var msgs = Array.prototype.slice.call(arguments, 1);

    var fmtMsg = strFmtTime() + ' ' + ident + '[' + process.pid + '] ' + prio + ': ' + util.format.apply(this, msgs) + '\n';

    if (logFile) {
      logFile.write(fmtMsg);
    }

    if (errFile && (prio <= ERR_THRESHOLD)) {
      errFile.write(fmtMsg);
    }

    if (cons) {
      if (prio <= ERR_THRESHOLD) {
        process.stderr.write(fmtMsg);
      } else {
        process.stdout.write(fmtMsg);
      }
    }
  }

  function logEmerg()   { Array.prototype.unshift.call(arguments, EMERG);   log.apply(null, arguments); }
  function logAlert()   { Array.prototype.unshift.call(arguments, ALERT);   log.apply(null, arguments); }
  function logCrit()    { Array.prototype.unshift.call(arguments, CRIT);    log.apply(null, arguments); }
  function logErr()     { Array.prototype.unshift.call(arguments, ERR);     log.apply(null, arguments); }
  function logWarning() { Array.prototype.unshift.call(arguments, WARNING); log.apply(null, arguments); }
  function logNotice()  { Array.prototype.unshift.call(arguments, NOTICE);  log.apply(null, arguments); }
  function logInfo()    { Array.prototype.unshift.call(arguments, INFO);    log.apply(null, arguments); }
  function logDebug()   { Array.prototype.unshift.call(arguments, DEBUG);   log.apply(null, arguments); }
  function logDebug2()  { Array.prototype.unshift.call(arguments, DEBUG2);  log.apply(null, arguments); }

  function close(cb2) {
    var tasks2Done = 0;

    var tasks2 = [function(cb3) {
      // ensure async even without any other tasks
      process.nextTick(function() {
        tasks2Done++;
        cb3();
      });
    }];

    logDebug2('closing all logs');

    if (logFile)  {
      tasks2.push(function(cb3) {
        logFile.end(function(err) {
          if (err) { cb3(err); return; }

          tasks2Done++;
          cb3(null);
        });
      });
    }
    if (errFile) {
      tasks2.push(function(cb3) {
        errFile.end(function(err) {
          if (err) { cb3(err); return; }

          tasks2Done++;
          cb3(null);
        });
      });
    }

    tasks2.forEach(function(task) {
      task(function(err) {
        if (err) { cb2(err); return; }
        if (tasks2Done === tasks2.length) {
          cb2();
        }
      });
    });
  }

  tasks.forEach(function(task) {
    task(function(err) {
      if (err) { cb(err); return; }
      if (tasksDone === tasks.length) {
        cb(null, {
          emerg:   logEmerg,
          alert:   logAlert,
          crit:    logCrit,
          err:     logErr,
          warning: logWarning,
          notice:  logNotice,
          info:    logInfo,
          debug:   logDebug,
          debug2:  logDebug2,
          getFileStream: function() { return logFile; },
          getErrorStream: function() { return errFile; },
          close: close
        });
      }
    });
  });
}

module.exports = logger;

module.exports.EMERG     =  EMERG;
module.exports.ALERT     =  ALERT;
module.exports.CRIT      =  CRIT;
module.exports.ERR       =  ERR;
module.exports.WARNING   =  WARNING;
module.exports.NOTICE    =  NOTICE;
module.exports.INFO      =  INFO;
module.exports.DEBUG     =  DEBUG;
module.exports.DEBUG2    =  DEBUG2;

module.exports.levelToPrio = function(name) {
  if (!name) { return null; }

  var idx = PRIOS.indexOf(name.toUpperCase());
  if (~idx) {
    return idx;
  }
  return null;
};

// ensure a log file is opened in append only mode
module.exports.openFile = openFile;
<|endoftext|>