simple-node-logger = function (options) {
'use strict';
if (!options) options = {};
var manager = this,
domain = options.domain,
appenders = options.appenders || [],
loggers = options.loggers || [],
dfltLevel = options.level || Logger.DEFAULT_LEVEL,
loggerConfigFile = options.loggerConfigFile,
refresh = options.refresh,
fs = options.fs || require('fs' ),
createInterval = options.createInterval || setInterval,
minRefresh = options.minRefresh || 10 * 1000,
refreshId;
/**
* create a logger with optional category and level
*
* @param category
* @param level
*/
this.createLogger = function(category, level) {
var logger;
var opts = Object.prototype.toString.call(category) === '[object String]' ? options : dash.merge({}, options, category);
opts.category = dash.isString(category) ? category : opts.category;
opts.level = level ? level : opts.level || dfltLevel;
opts.appenders = appenders;
logger = new Logger( opts );
loggers.push( logger );
return logger;
};
/**
* create the console appender and add it to the appenders list
*
* @param opts - appender settings
* @returns ConsoleAppender -
*/
this.createConsoleAppender = function(opts) {
if (!opts) opts = {};
return manager.addAppender( new ConsoleAppender( opts ) );
};
/**
* create a file appender and add it to the appenders list
*
* @param opts
* @returns a FileAppender object
*/
this.createFileAppender = function(opts) {
if (!opts) {
throw new Error('file appender must be created with log file path set in options');
}
return manager.addAppender( new FileAppender( opts ) );
};
/**
* create a rolling file appender and add it to the appender list
*
* @param opts
* @returns the appender
*/
this.createRollingFileAppender = function( opts ) {
return manager.addAppender( new RollingFileAppender( opts ) );
};
/**
* add the appender to list
*
* @param appender
* @returns the new appender
*/
this.addAppender = function(appender) {
appenders.push( appender );
return appender;
};
this.getAppenders = function() {
return appenders;
};
this.getLoggers = function() {
return loggers;
};
/**
* start the refresh thread; minimum cycle time = 10 seconds...
*/
this.startRefreshThread = function() {
// TODO replace with watcher thread
if (fs.existsSync( loggerConfigFile ) && dash.isNumber( refresh )) {
var t = Math.max( minRefresh, refresh );
refreshId = createInterval( manager.readConfig, t);
}
};
/**
* set the level of all loggers to the specified level
*
* @param level - one of the know levels
*/
this.setAllLoggerLevels = function(level) {
loggers.forEach(function(logger) {
logger.setLevel( level );
});
};
/**
* read and parse the config file; change settings if required
*/
this.readConfig = function(completeCallback) {
// TODO refactor into configuration delegate to read stats and then process file only if stats change
const callback = (err, buf) => {
if (err) {
console.log( err );
} else {
const conf = JSON.parse( buf.toString() );
if (conf.appenders && conf.appenders.length > 0) {
// find each appender and set the level
conf.appenders.forEach(function(app) {
const level = app.level;
const appender = dash.find( appenders, (item) => {
if (item.getTypeName() === app.typeName && app.level) {
return item;
} ...n/a
AbstractAppender = function (options) {
'use strict';
const appender = this,
typeName = options.typeName,
timestampFormat = options.timestampFormat || 'HH:mm:ss.SSS';
this.separator = options.separator || ' ';
/**
* format the entry and return the field list
*
* @param entry the log entry
* @returns field array
*/
this.formatEntry = function(entry) {
var fields = [];
if (entry.domain) {
fields.push( entry.domain );
}
fields.push( appender.formatTimestamp( entry.ts ) );
fields.push( appender.formatLevel( entry.level ) );
if (entry.category) {
fields.push( entry.category );
}
fields.push( appender.formatMessage( entry.msg ) );
return fields;
};
this.formatMessage = function(msg) {
var list;
if (!msg) {
return '';
}
if (util.isArray( msg )) {
list = msg.map(function(item) {
if (util.isDate( item )) {
return appender.formatDate( item );
} else {
return appender.formatObject( item );
}
});
return list.join('');
} else {
return msg;
}
};
this.formatDate = function(value) {
return value.toJSON();
};
this.formatObject = function(value) {
if (!value) {
return '';
}
if (dash.isObject( value )) {
try {
return JSON.stringify( value );
} catch (ignore) {
return 'json error: ' + value.toString();
}
} else {
var s = value.toString();
if (s === '[object Object]') {
return util.inspect( value );
} else {
return s;
}
}
};
/**
* format the level string by forcing to upper case and padding to 5 chars
*
* @param level
* @returns {string}
*/
this.formatLevel = function(level) {
var str = level.toUpperCase();
if (str.length < 5) str += ' ';
return str;
};
/**
* format the timestamp to HH:mm:ss.SSS
*
* @param ts the unix milliseconds
* @returns formatted string
*/
this.formatTimestamp = function(ts) {
return moment( ts ).format( timestampFormat );
};
/**
* return the type name of this appender (ConsoleAppender)
*/
this.getTypeName = function() {
return typeName;
};
// constructor tests
if (!typeName) throw new Error('appender must be constructed with a type name');
}n/a
Logger = function (options) {
'use strict';
const logger = this,
pid = options.pid || process.pid;
let domain = options.domain,
category = options.category,
level = options.level || Logger.DEFAULT_LEVEL,
levels = options.levels || Logger.STANDARD_LEVELS,
currentLevel = levels.indexOf( level ),
appenders = options.appenders || [];
// helper method
const isLevelAt = function(lvl) {
const idx = levels.indexOf( lvl );
return idx >= currentLevel;
};
/**
* log the statement message
*
* @param level the level of this message
* @param msg
*/
this.log = function(level, msg) {
var entry = logger.createEntry( level, msg );
process.nextTick(function() {
// write the message to the appenders...
appenders.forEach(function(appender) {
appender.write( entry );
});
});
return entry;
};
/**
* create the entry object used to log messages
*
* @param level - info, debug, etc.
* @param messageList - a list of message objects
* @returns then entry object
*/
this.createEntry = function(level, messageList) {
const entry = {};
entry.ts = Date.now();
entry.pid = pid;
if (domain) entry.domain = domain;
if (category) entry.category = category;
entry.level = level;
entry.msg = messageList;
return entry;
};
/**
* set the level
*
* @param lvl one of the recognized logger levels
*/
this.setLevel = function(lvl) {
currentLevel = levels.indexOf(lvl);
level = lvl;
appenders.forEach(app => {
app.setLevel( lvl );
});
};
/**
* return the current level string
*/
this.getLevel = function() {
return level;
};
/**
* set the list of appenders
* @param app
*/
this.setAppenders = function(appenderList) {
appenders = appenderList;
};
/**
* add an appender to the list
*
* @param appender - implements write method
*/
this.addAppender = function(appender) {
appenders.push( appender );
};
/**
* remove the appender using the type name
*/
this.removeAppender = function(typeName) {
throw new Error('not implemented yet');
};
this.getAppenders = function() {
return appenders;
};
this.isDebug = function() {
return isLevelAt( 'debug' );
};
this.isInfo = function() {
return isLevelAt( 'info' );
};
// now initialize the methods for the standard levels
const init = function() {
levels.forEach(function(lvl) {
logger[ lvl ] = function() {
if (levels.indexOf( lvl ) >= currentLevel) {
var args = Array.prototype.slice.call( arguments );
logger.log( lvl, args );
}
};
});
};
this.__protected = function() {
return {
pid:pid,
domain:domain,
category:category
};
};
init();
}n/a
SimpleLogger = function (options) {
'use strict';
if (!options) options = {};
var manager = this,
domain = options.domain,
appenders = options.appenders || [],
loggers = options.loggers || [],
dfltLevel = options.level || Logger.DEFAULT_LEVEL,
loggerConfigFile = options.loggerConfigFile,
refresh = options.refresh,
fs = options.fs || require('fs' ),
createInterval = options.createInterval || setInterval,
minRefresh = options.minRefresh || 10 * 1000,
refreshId;
/**
* create a logger with optional category and level
*
* @param category
* @param level
*/
this.createLogger = function(category, level) {
var logger;
var opts = Object.prototype.toString.call(category) === '[object String]' ? options : dash.merge({}, options, category);
opts.category = dash.isString(category) ? category : opts.category;
opts.level = level ? level : opts.level || dfltLevel;
opts.appenders = appenders;
logger = new Logger( opts );
loggers.push( logger );
return logger;
};
/**
* create the console appender and add it to the appenders list
*
* @param opts - appender settings
* @returns ConsoleAppender -
*/
this.createConsoleAppender = function(opts) {
if (!opts) opts = {};
return manager.addAppender( new ConsoleAppender( opts ) );
};
/**
* create a file appender and add it to the appenders list
*
* @param opts
* @returns a FileAppender object
*/
this.createFileAppender = function(opts) {
if (!opts) {
throw new Error('file appender must be created with log file path set in options');
}
return manager.addAppender( new FileAppender( opts ) );
};
/**
* create a rolling file appender and add it to the appender list
*
* @param opts
* @returns the appender
*/
this.createRollingFileAppender = function( opts ) {
return manager.addAppender( new RollingFileAppender( opts ) );
};
/**
* add the appender to list
*
* @param appender
* @returns the new appender
*/
this.addAppender = function(appender) {
appenders.push( appender );
return appender;
};
this.getAppenders = function() {
return appenders;
};
this.getLoggers = function() {
return loggers;
};
/**
* start the refresh thread; minimum cycle time = 10 seconds...
*/
this.startRefreshThread = function() {
// TODO replace with watcher thread
if (fs.existsSync( loggerConfigFile ) && dash.isNumber( refresh )) {
var t = Math.max( minRefresh, refresh );
refreshId = createInterval( manager.readConfig, t);
}
};
/**
* set the level of all loggers to the specified level
*
* @param level - one of the know levels
*/
this.setAllLoggerLevels = function(level) {
loggers.forEach(function(logger) {
logger.setLevel( level );
});
};
/**
* read and parse the config file; change settings if required
*/
this.readConfig = function(completeCallback) {
// TODO refactor into configuration delegate to read stats and then process file only if stats change
const callback = (err, buf) => {
if (err) {
console.log( err );
} else {
const conf = JSON.parse( buf.toString() );
if (conf.appenders && conf.appenders.length > 0) {
// find each appender and set the level
conf.appenders.forEach(function(app) {
const level = app.level;
const appender = dash.find( appenders, (item) => {
if (item.getTypeName() === app.typeName && app.level) {
return item;
} ...n/a
createLogManager = function (options) {
'use strict';
if (!options) {
options = {};
}
var opts;
// read a dynamic config file if available
if (typeof options.readLoggerConfig === 'function') {
opts = options.readLoggerConfig();
opts.readLoggerConfig = options.readLoggerConfig;
} else {
opts = options;
}
var manager = new SimpleLogger( opts );
if (opts.logDirectory && opts.fileNamePattern) {
manager.createRollingFileAppender( opts );
}
// create at least one appender
if (manager.getAppenders().length === 0) {
manager.createConsoleAppender( opts );
}
return manager;
}...
};
const log = require('simple-node-logger').createRollingFileLogger( opts );
or
// create a log manager
const manager = require('simple-node-logger').createLogManager();
manager.createConsoleAppender();
const log = manager.createLogger('MyClass');
// create other logs and appenders...
...createRollingFileLogger = function (options) {
'use strict';
if (!options) {
throw new Error('createRollingFileLogger requires configuration options for this constructor');
}
var opts;
// read a dynamic config file if available
if (typeof options.readLoggerConfig === 'function') {
opts = options.readLoggerConfig();
opts.readLoggerConfig = options.readLoggerConfig;
} else {
opts = options;
}
var manager = new SimpleLogger( opts );
manager.createRollingFileAppender( opts );
if (opts.refresh && opts.loggerConfigFile) {
process.nextTick( manager.startRefreshThread );
}
return manager.createLogger( opts );
}...
// create a rolling file logger based on date/time
const opts = {
logDirectory:'/mylogfiles',
fileNamePattern:'roll-<DATE>.log',
dateFormat:'YYYY.MM.DD'
};
const log = require('simple-node-logger').createRollingFileLogger( opts );
or
// create a log manager
const manager = require('simple-node-logger').createLogManager();
manager.createConsoleAppender();
...createSimpleFileLogger = function (options) {
'use strict';
var opts;
if (!options) {
throw new Error('must create file logger with a logFilePath');
}
// if options is a string then it must be the
if (typeof options === 'string') {
opts = {
logFilePath: options
};
} else {
opts = dash.clone( options );
}
var manager = new SimpleLogger( opts );
manager.createFileAppender( opts );
return manager.createLogger();
}...
timestampFormat:'YYYY-MM-DD HH:mm:ss.SSS'
},
log = SimpleNodeLogger.createSimpleLogger( opts );
or
// create a file only file logger
const log = require('simple-node-logger').createSimpleFileLogger('project
.log');
or
// create a rolling file logger based on date/time
const opts = {
logDirectory:'/mylogfiles',
fileNamePattern:'roll-<DATE>.log',
...createSimpleLogger = function (options) {
'use strict';
var opts;
if (!options) {
options = {};
}
// if options is a string then it must be the
if (typeof options === 'string') {
opts = {
logFilePath: options
};
} else {
opts = dash.clone( options );
}
const manager = new SimpleLogger(opts);
// pass options in to change date formats, etc
manager.createConsoleAppender( opts );
if (opts.logFilePath) {
manager.createFileAppender( opts );
}
return manager.createLogger();
}...
npm install simple-node-logger --save
## How to use
// create a stdout console logger
const log = require('simple-node-logger').createSimpleLogger();
or
// create a stdout and file logger
const log = require('simple-node-logger').createSimpleLogger('project.log');
or
...mocks.MockLogger = function (opts) {
'use strict';
const mock = this,
appender = new MockAppender();
if (!opts) opts = {};
if (!opts.pid) opts.pid = 'test12345';
if (!opts.appenders) opts.appenders = [ appender ];
if (!opts.level) opts.level = 'trace';
dash.extend( this, new Logger(opts) );
this.getLogEntries = function() {
return appender.entries;
};
}n/a
AbstractAppender = function (options) {
'use strict';
const appender = this,
typeName = options.typeName,
timestampFormat = options.timestampFormat || 'HH:mm:ss.SSS';
this.separator = options.separator || ' ';
/**
* format the entry and return the field list
*
* @param entry the log entry
* @returns field array
*/
this.formatEntry = function(entry) {
var fields = [];
if (entry.domain) {
fields.push( entry.domain );
}
fields.push( appender.formatTimestamp( entry.ts ) );
fields.push( appender.formatLevel( entry.level ) );
if (entry.category) {
fields.push( entry.category );
}
fields.push( appender.formatMessage( entry.msg ) );
return fields;
};
this.formatMessage = function(msg) {
var list;
if (!msg) {
return '';
}
if (util.isArray( msg )) {
list = msg.map(function(item) {
if (util.isDate( item )) {
return appender.formatDate( item );
} else {
return appender.formatObject( item );
}
});
return list.join('');
} else {
return msg;
}
};
this.formatDate = function(value) {
return value.toJSON();
};
this.formatObject = function(value) {
if (!value) {
return '';
}
if (dash.isObject( value )) {
try {
return JSON.stringify( value );
} catch (ignore) {
return 'json error: ' + value.toString();
}
} else {
var s = value.toString();
if (s === '[object Object]') {
return util.inspect( value );
} else {
return s;
}
}
};
/**
* format the level string by forcing to upper case and padding to 5 chars
*
* @param level
* @returns {string}
*/
this.formatLevel = function(level) {
var str = level.toUpperCase();
if (str.length < 5) str += ' ';
return str;
};
/**
* format the timestamp to HH:mm:ss.SSS
*
* @param ts the unix milliseconds
* @returns formatted string
*/
this.formatTimestamp = function(ts) {
return moment( ts ).format( timestampFormat );
};
/**
* return the type name of this appender (ConsoleAppender)
*/
this.getTypeName = function() {
return typeName;
};
// constructor tests
if (!typeName) throw new Error('appender must be constructed with a type name');
}n/a
extend = function (child, options) {
'use strict';
const parent = new AbstractAppender( options );
dash.extend( child, parent );
return parent;
}...
'use strict';
var appender = this;
var opts = {
typeName:'JSONAppender'
};
AbstractAppender.extend( this, opts );
// format and write all entry/statements
this.write = function(entry) {
var fields = appender.formatEntry( entry );
process.stdout.write( JSON.stringify( entry ) + '\n' );
};
...SimpleLogger = function (options) {
'use strict';
if (!options) options = {};
var manager = this,
domain = options.domain,
appenders = options.appenders || [],
loggers = options.loggers || [],
dfltLevel = options.level || Logger.DEFAULT_LEVEL,
loggerConfigFile = options.loggerConfigFile,
refresh = options.refresh,
fs = options.fs || require('fs' ),
createInterval = options.createInterval || setInterval,
minRefresh = options.minRefresh || 10 * 1000,
refreshId;
/**
* create a logger with optional category and level
*
* @param category
* @param level
*/
this.createLogger = function(category, level) {
var logger;
var opts = Object.prototype.toString.call(category) === '[object String]' ? options : dash.merge({}, options, category);
opts.category = dash.isString(category) ? category : opts.category;
opts.level = level ? level : opts.level || dfltLevel;
opts.appenders = appenders;
logger = new Logger( opts );
loggers.push( logger );
return logger;
};
/**
* create the console appender and add it to the appenders list
*
* @param opts - appender settings
* @returns ConsoleAppender -
*/
this.createConsoleAppender = function(opts) {
if (!opts) opts = {};
return manager.addAppender( new ConsoleAppender( opts ) );
};
/**
* create a file appender and add it to the appenders list
*
* @param opts
* @returns a FileAppender object
*/
this.createFileAppender = function(opts) {
if (!opts) {
throw new Error('file appender must be created with log file path set in options');
}
return manager.addAppender( new FileAppender( opts ) );
};
/**
* create a rolling file appender and add it to the appender list
*
* @param opts
* @returns the appender
*/
this.createRollingFileAppender = function( opts ) {
return manager.addAppender( new RollingFileAppender( opts ) );
};
/**
* add the appender to list
*
* @param appender
* @returns the new appender
*/
this.addAppender = function(appender) {
appenders.push( appender );
return appender;
};
this.getAppenders = function() {
return appenders;
};
this.getLoggers = function() {
return loggers;
};
/**
* start the refresh thread; minimum cycle time = 10 seconds...
*/
this.startRefreshThread = function() {
// TODO replace with watcher thread
if (fs.existsSync( loggerConfigFile ) && dash.isNumber( refresh )) {
var t = Math.max( minRefresh, refresh );
refreshId = createInterval( manager.readConfig, t);
}
};
/**
* set the level of all loggers to the specified level
*
* @param level - one of the know levels
*/
this.setAllLoggerLevels = function(level) {
loggers.forEach(function(logger) {
logger.setLevel( level );
});
};
/**
* read and parse the config file; change settings if required
*/
this.readConfig = function(completeCallback) {
// TODO refactor into configuration delegate to read stats and then process file only if stats change
const callback = (err, buf) => {
if (err) {
console.log( err );
} else {
const conf = JSON.parse( buf.toString() );
if (conf.appenders && conf.appenders.length > 0) {
// find each appender and set the level
conf.appenders.forEach(function(app) {
const level = app.level;
const appender = dash.find( appenders, (item) => {
if (item.getTypeName() === app.typeName && app.level) {
return item;
} ...n/a
AbstractAppender = function (options) {
'use strict';
const appender = this,
typeName = options.typeName,
timestampFormat = options.timestampFormat || 'HH:mm:ss.SSS';
this.separator = options.separator || ' ';
/**
* format the entry and return the field list
*
* @param entry the log entry
* @returns field array
*/
this.formatEntry = function(entry) {
var fields = [];
if (entry.domain) {
fields.push( entry.domain );
}
fields.push( appender.formatTimestamp( entry.ts ) );
fields.push( appender.formatLevel( entry.level ) );
if (entry.category) {
fields.push( entry.category );
}
fields.push( appender.formatMessage( entry.msg ) );
return fields;
};
this.formatMessage = function(msg) {
var list;
if (!msg) {
return '';
}
if (util.isArray( msg )) {
list = msg.map(function(item) {
if (util.isDate( item )) {
return appender.formatDate( item );
} else {
return appender.formatObject( item );
}
});
return list.join('');
} else {
return msg;
}
};
this.formatDate = function(value) {
return value.toJSON();
};
this.formatObject = function(value) {
if (!value) {
return '';
}
if (dash.isObject( value )) {
try {
return JSON.stringify( value );
} catch (ignore) {
return 'json error: ' + value.toString();
}
} else {
var s = value.toString();
if (s === '[object Object]') {
return util.inspect( value );
} else {
return s;
}
}
};
/**
* format the level string by forcing to upper case and padding to 5 chars
*
* @param level
* @returns {string}
*/
this.formatLevel = function(level) {
var str = level.toUpperCase();
if (str.length < 5) str += ' ';
return str;
};
/**
* format the timestamp to HH:mm:ss.SSS
*
* @param ts the unix milliseconds
* @returns formatted string
*/
this.formatTimestamp = function(ts) {
return moment( ts ).format( timestampFormat );
};
/**
* return the type name of this appender (ConsoleAppender)
*/
this.getTypeName = function() {
return typeName;
};
// constructor tests
if (!typeName) throw new Error('appender must be constructed with a type name');
}n/a
Logger = function (options) {
'use strict';
const logger = this,
pid = options.pid || process.pid;
let domain = options.domain,
category = options.category,
level = options.level || Logger.DEFAULT_LEVEL,
levels = options.levels || Logger.STANDARD_LEVELS,
currentLevel = levels.indexOf( level ),
appenders = options.appenders || [];
// helper method
const isLevelAt = function(lvl) {
const idx = levels.indexOf( lvl );
return idx >= currentLevel;
};
/**
* log the statement message
*
* @param level the level of this message
* @param msg
*/
this.log = function(level, msg) {
var entry = logger.createEntry( level, msg );
process.nextTick(function() {
// write the message to the appenders...
appenders.forEach(function(appender) {
appender.write( entry );
});
});
return entry;
};
/**
* create the entry object used to log messages
*
* @param level - info, debug, etc.
* @param messageList - a list of message objects
* @returns then entry object
*/
this.createEntry = function(level, messageList) {
const entry = {};
entry.ts = Date.now();
entry.pid = pid;
if (domain) entry.domain = domain;
if (category) entry.category = category;
entry.level = level;
entry.msg = messageList;
return entry;
};
/**
* set the level
*
* @param lvl one of the recognized logger levels
*/
this.setLevel = function(lvl) {
currentLevel = levels.indexOf(lvl);
level = lvl;
appenders.forEach(app => {
app.setLevel( lvl );
});
};
/**
* return the current level string
*/
this.getLevel = function() {
return level;
};
/**
* set the list of appenders
* @param app
*/
this.setAppenders = function(appenderList) {
appenders = appenderList;
};
/**
* add an appender to the list
*
* @param appender - implements write method
*/
this.addAppender = function(appender) {
appenders.push( appender );
};
/**
* remove the appender using the type name
*/
this.removeAppender = function(typeName) {
throw new Error('not implemented yet');
};
this.getAppenders = function() {
return appenders;
};
this.isDebug = function() {
return isLevelAt( 'debug' );
};
this.isInfo = function() {
return isLevelAt( 'info' );
};
// now initialize the methods for the standard levels
const init = function() {
levels.forEach(function(lvl) {
logger[ lvl ] = function() {
if (levels.indexOf( lvl ) >= currentLevel) {
var args = Array.prototype.slice.call( arguments );
logger.log( lvl, args );
}
};
});
};
this.__protected = function() {
return {
pid:pid,
domain:domain,
category:category
};
};
init();
}n/a
createLogManager = function (options) {
'use strict';
if (!options) {
options = {};
}
var opts;
// read a dynamic config file if available
if (typeof options.readLoggerConfig === 'function') {
opts = options.readLoggerConfig();
opts.readLoggerConfig = options.readLoggerConfig;
} else {
opts = options;
}
var manager = new SimpleLogger( opts );
if (opts.logDirectory && opts.fileNamePattern) {
manager.createRollingFileAppender( opts );
}
// create at least one appender
if (manager.getAppenders().length === 0) {
manager.createConsoleAppender( opts );
}
return manager;
}...
};
const log = require('simple-node-logger').createRollingFileLogger( opts );
or
// create a log manager
const manager = require('simple-node-logger').createLogManager();
manager.createConsoleAppender();
const log = manager.createLogger('MyClass');
// create other logs and appenders...
...createRollingFileLogger = function (options) {
'use strict';
if (!options) {
throw new Error('createRollingFileLogger requires configuration options for this constructor');
}
var opts;
// read a dynamic config file if available
if (typeof options.readLoggerConfig === 'function') {
opts = options.readLoggerConfig();
opts.readLoggerConfig = options.readLoggerConfig;
} else {
opts = options;
}
var manager = new SimpleLogger( opts );
manager.createRollingFileAppender( opts );
if (opts.refresh && opts.loggerConfigFile) {
process.nextTick( manager.startRefreshThread );
}
return manager.createLogger( opts );
}...
// create a rolling file logger based on date/time
const opts = {
logDirectory:'/mylogfiles',
fileNamePattern:'roll-<DATE>.log',
dateFormat:'YYYY.MM.DD'
};
const log = require('simple-node-logger').createRollingFileLogger( opts );
or
// create a log manager
const manager = require('simple-node-logger').createLogManager();
manager.createConsoleAppender();
...createSimpleFileLogger = function (options) {
'use strict';
var opts;
if (!options) {
throw new Error('must create file logger with a logFilePath');
}
// if options is a string then it must be the
if (typeof options === 'string') {
opts = {
logFilePath: options
};
} else {
opts = dash.clone( options );
}
var manager = new SimpleLogger( opts );
manager.createFileAppender( opts );
return manager.createLogger();
}...
timestampFormat:'YYYY-MM-DD HH:mm:ss.SSS'
},
log = SimpleNodeLogger.createSimpleLogger( opts );
or
// create a file only file logger
const log = require('simple-node-logger').createSimpleFileLogger('project
.log');
or
// create a rolling file logger based on date/time
const opts = {
logDirectory:'/mylogfiles',
fileNamePattern:'roll-<DATE>.log',
...createSimpleLogger = function (options) {
'use strict';
var opts;
if (!options) {
options = {};
}
// if options is a string then it must be the
if (typeof options === 'string') {
opts = {
logFilePath: options
};
} else {
opts = dash.clone( options );
}
const manager = new SimpleLogger(opts);
// pass options in to change date formats, etc
manager.createConsoleAppender( opts );
if (opts.logFilePath) {
manager.createFileAppender( opts );
}
return manager.createLogger();
}...
npm install simple-node-logger --save
## How to use
// create a stdout console logger
const log = require('simple-node-logger').createSimpleLogger();
or
// create a stdout and file logger
const log = require('simple-node-logger').createSimpleLogger('project.log');
or
...ConsoleAppender = function (options) {
'use strict';
if (!options) options = {};
let appender = this,
typeName = options.typeName,
level = options.level || Logger.STANDARD_LEVELS[0],
levels = options.levels || Logger.STANDARD_LEVELS,
currentLevel = levels.indexOf( level ),
writer = options.writer || console.log;
if (!typeName) {
typeName = options.typeName = 'ConsoleAppender';
}
AbstractAppender.extend( this, options );
/**
* default formatter for this appender;
* @param entry
*/
this.formatter = function(entry) {
var fields = appender.formatEntry( entry );
return fields.join( appender.separator );
};
/**
* call formatter then write the entry to the console output
* @param entry - the log entry
*/
this.write = function(entry) {
if (levels.indexOf( entry.level ) >= currentLevel) {
writer( appender.formatter( entry ));
}
};
this.setLevel = function(level) {
const idx = levels.indexOf( level );
if (idx >= 0) {
currentLevel = idx;
}
};
}n/a
FileAppender = function (options) {
'use strict';
const appender = this,
fs = options.fs || require( 'fs' ),
newline = /^win/.test(process.platform) ? '\r\n' : '\n';
let typeName = options.typeName,
autoOpen = dash.isBoolean( options.autoOpen ) ? options.autoOpen : true,
logFilePath = options.logFilePath,
level = options.level || Logger.DEFAULT_LEVEL,
levels = options.levels || Logger.STANDARD_LEVELS,
currentLevel = levels.indexOf( level ),
writer = options.writer;
if (!typeName) {
// required for abstract class
typeName = options.typeName = 'FileAppender';
}
AbstractAppender.extend( this, options );
/**
* default formatter for this appender;
* @param entry
*/
this.formatter = function(entry) {
var fields = appender.formatEntry( entry );
// add new line (for linux and windows)
fields.push( newline );
return fields.join( appender.separator );
};
/**
* call formatter then write the entry to the console output
* @param entry - the log entry
*/
this.write = function(entry) {
if (levels.indexOf( entry.level ) >= currentLevel) {
writer.write( appender.formatter( entry ) );
}
};
this.setLevel = function(level) {
var idx = levels.indexOf( level );
if (idx >= 0) {
currentLevel = idx;
}
};
// writer is opened on construction
const openWriter = function() {
if (!writer) {
var file = path.normalize( logFilePath ),
opts = {
flags:'a',
encoding:'utf8'
};
writer = fs.createWriteStream( file, opts );
}
};
this.closeWriter = function() {
if (writer) {
writer.end('\n');
}
};
// constructor tests
(function() {
if (!logFilePath) {
throw new Error('appender must be constructed with a log file path');
}
}());
if (autoOpen) {
openWriter();
}
}n/a
RollingFileAppender = function (options) {
'use strict';
const appender = this,
fs = options.fs || require( 'fs' ),
newline = /^win/.test(process.platform) ? '\r\n' : '\n';
let typeName = options.typeName,
autoOpen = dash.isBoolean( options.autoOpen ) ? options.autoOpen : true,
logDirectory = options.logDirectory,
fileNamePattern = options.fileNamePattern,
dateFormat = options.dateFormat || 'YYYY.MM.DD',
level = options.level || Logger.DEFAULT_LEVEL,
levels = options.levels || Logger.STANDARD_LEVELS,
currentLevel = levels.indexOf( level ),
currentFile = options.currentFile,
rollTimer,
createInterval = options.createInterval || setInterval,
writers = [];
if (!typeName) {
typeName = options.typeName = 'RollingFileAppender';
}
AbstractAppender.extend( this, options );
const getWriter = function() {
return writers[0];
};
const openWriter = function(filename) {
let writer,
file,
opts;
if (!filename) {
filename = appender.createFileName();
}
file = path.join( logDirectory, filename );
opts = {
flags:'a',
encoding:'utf8'
};
writer = fs.createWriteStream( file, opts );
// make this the current writer...
writers.unshift( writer );
currentFile = file;
// now close the current logger and remove from the writers list
while (writers.length > 1) {
// close the old writer
writer = writers.pop();
writer.removeAllListeners();
writer.end('\n');
}
};
// check once per minute to see if we need to roll
const startRollTimer = function() {
rollTimer = createInterval(function() {
if (appender.checkForRoll()) {
openWriter();
}
}, 60 * 1000);
};
/**
* default formatter for this appender;
* @param entry
*/
this.formatter = function(entry) {
var fields = appender.formatEntry( entry );
fields.push( newline );
return fields.join( appender.separator );
};
/**
* call formatter then write the entry to the console output
* @param entry - the log entry
*/
this.write = function(entry) {
if (levels.indexOf( entry.level ) >= currentLevel) {
var writer = getWriter();
if (writer) {
writer.write( appender.formatter( entry ) );
} else {
console.log( 'no writer...' );
}
}
};
this.checkForRoll = function(now) {
// check to see if the
const fn = appender.createFileName( now ),
current = path.basename( currentFile );
return fn !== current;
};
this.createFileName = function(now) {
let dt;
if (now || now instanceof moment) {
dt = now.format( dateFormat );
} else {
dt = moment().format( dateFormat );
}
return fileNamePattern.replace( /<DATE>/i, dt );
};
this.setLevel = function(level) {
const idx = levels.indexOf( level );
if (idx >= 0) {
currentLevel = idx;
}
};
this.__protected = function() {
return {
openWriter:openWriter,
currentFile:currentFile,
rollTimer:rollTimer,
writers:writers
};
};
// constructor tests
(function() {
if (!logDirectory) {
throw new Error('appender must be constructed with a log directory');
}
if (!fileNamePattern) {
throw new Error('appender must be constructed with a file name pattern');
}
}());
// now validate the date pattern and file format
// date may only contain YMDHAa-.
if (autoOpen) {
openWriter();
startRollTimer();
}
}n/a
MockAppender = function () {
'use strict';
const Logger = require('../../lib/Logger' );
let level = Logger.DEFAULT_LEVEL,
levels = Logger.STANDARD_LEVELS,
currentLevel = levels.indexOf( level );
let appender = this;
this.entries = [];
this.setLevel = function(level) {
var idx = levels.indexOf( level );
if (idx >= 0) {
currentLevel = idx;
}
};
this.write = function(entry) {
appender.entries.push( entry );
};
}n/a
MockLogger = function (opts) {
'use strict';
const mock = this,
appender = new MockAppender();
if (!opts) opts = {};
if (!opts.pid) opts.pid = 'test12345';
if (!opts.appenders) opts.appenders = [ appender ];
if (!opts.level) opts.level = 'trace';
dash.extend( this, new Logger(opts) );
this.getLogEntries = function() {
return appender.entries;
};
}n/a
MockLogger = function (opts) {
'use strict';
const mock = this,
appender = new MockAppender();
if (!opts) opts = {};
if (!opts.pid) opts.pid = 'test12345';
if (!opts.appenders) opts.appenders = [ appender ];
if (!opts.level) opts.level = 'trace';
dash.extend( this, new Logger(opts) );
this.getLogEntries = function() {
return appender.entries;
};
}n/a
createLogger = function (category, level) {
'use strict';
const opts = {};
if (category) opts.category = category;
if (level) opts.level = level;
return new MockLogger( opts );
}...
or
// create a log manager
const manager = require('simple-node-logger').createLogManager();
manager.createConsoleAppender();
const log = manager.createLogger('MyClass');
// create other logs and appenders...
The first use simply logs to the console. The second logs to the console and to the project.log file. The third create a console
logger with a custom timestamp format. The fourth logs to the file only. The fifth creates a rolling file log system in the target
log folder. The fifth creates a log manager to enable you to add various appenders with multiple levels and create logs for each
module or class.
*See the examples folder for in depth samples...*
...