Split-level logging to multiple destinations
npm i split-logconst Log = require('split-log')
let log = new Log({ file: true })
log.notice('Hear ye!')
// Writes '[NOTICE] Hear ye!' to console and fileChoose from syslog-style log levels (0: Emergency, 1: Alert, 2: Critical, 3: Error, 4: Warn, 5: Notice, 6: Info, 7: Debug)
// Log events at 'info' level and lower
log.level = 'info'
log.debug('Malformed request at object "Reactor"')
log.emergency('Nuclear meltdown imminent!')
// Output:
// [EMERGENCY] Nuclear meltdown imminent!Define custom levels
log.addLevel('sneeze')
// Log events at 'sneeze' level and lower
log.level = 'sneeze'
log.sneeze('Achoo!')
// Output:
// [SNEEZE] Achoo!Change output based on the current priority level rather than relying on global information
log.level = 'info'
log.error({
  info:  'Everything is going to be OK',
  warn:  'There might be a small problem',
  error: 'The world will end in five minutes',
  alert: 'This is all your fault'
})
// Output:
// [ERROR] Everything is going to be OKSplit the log further with event listeners!
Example: Using Nodemailer
// Set up email support
const nodemailer = require('nodemailer')
nodemailer.createTransport('smtps://user%40gmail.com:pass@smtp.gmail.com')
function sendBadNews(entry) {
  // If the log entry is 'error' or lower...
  if (entry.levelIndex <= 3) {
    // ... email the log entry to the sysadmin
    let msg = entry.msg
    let mailOptions = {
      from: '"Bad News Bot" <badnewsbot@badco.co>',
      to: 'sysadmin@badco.co',
      subject: 'Bad News, Buddy',
      text: 'There was an issue with the important software: ' + msg
    }
    transporter.sendMail(mailOptions)  
  }
}
// Listen for output events
log.on('entry', sendBadNews)
server.on('explosion', () => {
  // Log entry triggers the 'entry'
  log.alert('The server exploded again.')
})Handles logging configuration and output
Log is an EventEmitter
Creates a new Log with properties set by options
optionsObject (optional)levelString (optional) - Specifies priority level based on syslog conventions or custom levels. Default isnotice.stdoutBoolean (optional) - Whether to write log entries to stdout (console). Default istrue.fileBoolean (optional) - Whether to write log entries to file. Default isfalse.filenameString (optional) - Name of file to which log entries are written. Default islog_<YYYYMMDD_HHMMSS>.txtwhere<YYYYMMDD_HHMMSS>is a string-formatted timestamp representing when the log instance was created.dirString (optional) - Specifies directory to store log files. Default is./logs/(NOTE: Ifdirdoes not exist, it will be created only when a log file is written).showLabelBoolean (optional) - Whether to prependlevellabel to each log entry (ex.[INFO] Some information). Default istrueprefix- String (optional) - String to prepend to each log entry (written beforelabel). Supports strftime formatting for generating timestamps. Default is timestamp in 'YYYY-MM-DD HH:MM:SS -' format.
Objects created with new Log emit the following event:
Emitted when a log entry is created. This event will be emitted even if both log.stdout and log.file are false.
Returns:
entryObjecttimestampDate - When the entry was emittedlevelString - Priority level that fired the eventlevelIndexInteger - Numeric representation of priority level that fired the event (lower numbers mean higher priority)prefixString - Prefix or timestamp applied to log entrymsgString - Log message withoutprefix(will include label ifshowLabelistrue)
Example: Sending log entries to a logging server with Needle
const Log    = require('split-log')
const needle = require('needle')
let log = new Log({
  level: 'warn', // only care about warnings and lower
  file: false,   // disable logging to file
  stdout: false, // disable logging to terminal
})
log.on('entry', entry => {
  // POST entry object to logging server
  needle.post('https://logging-endpoint.com/', entry, (err, resp) => {
    if (err) throw err
  })
})
log.warn('Upload me, Captain.')
// No output on local machine
// Sends data to logging endpointObjects created with new Log have the following properties:
A String representing the current log level (must be an item returned in log.getLevels() array).
An Integer representing the index of level in relation to the Array returned by log.getLevels(), used for prioritizing log messages. Lower numbers mean higher priority.
A Boolean indicating whether log entries will be written to stdout (console).
A Boolean indicating whether log entries will be written to file (filepath specified by log.getFilepath()).
A String representing the name of the file to which log entries are written.
A String representing the directory to which log files are written.
A Boolean indicating whether bracketed labels will be prepended to log entries noting their priority level.
A String to prepend to log entries (before labels). Supports strftime formatting for generating timestamps.
Objects created with new Log have the following instance methods:
All priority levels returned by log.getLevels() (including custom levels) can be used as instance methods. Calling a priority level as a method writes message to logging destinations when log.level is set to a priority with a levelIndex at or above the method's level.
Example: Sending strings to the log
log.level = 'notice' // log.levelIndex('notice') === 5
log.debug('Hark! A bug!') // log.levelIndex('debug') === 7
// No output
log.error('Hark! An error!') //log.levelIndex('error') === 3
// Output: [ERROR] Hark! An error!
log.addLevel('sneeze')
log.level = 'sneeze' // log.levelIndex('sneeze') === 8
log.debug('Hark! A bug!') // log.levelIndex('debug') === 7
// Output: [DEBUG] Hark! A bug!Priority methods also accept an Object of key-value pairs, where the keys represent priority levels and values represent messages to pass. Logging this way allows different information to be passed depending the priority level set in log.level.
Example: Changing output based on priority level
log.level = 'notice'
log.error({
  notice: 'Tell your supervisor there was a problem.',
  error: 'There was a problem, boss.'
})
// Output: [ERROR] Tell your supervisor there was a problem.
log.level = 'error'
log.error({
  notice: 'Tell your supervisor there was a problem.',
  error: 'There was a problem, boss.'
})
// Output: [ERROR] There was a problem, boss.Use a key named default to pass a default message if the current priority level isn't specified in the object.
Example 2: Logging error details only during debugging
log.level = 'notice'
process.on('uncaughtException', e => {
  log.error({
    debug: e,
    default: 'Oops! There was a problem!'
  })
})
// Output: [ERROR] Oops! There was a problem!NOTE: Stringify objects that shouldn't be interpreted as priority levels. Unexpected object literals may produce unpredictable behavior.
For writing messages exclusive to the level set at log.level, see log.write(Object).
Returns an Array of available log levels, including default syslog levels and custom levels set by log.addLevel.
Returns a String representing the absolute path to the current log file.
Adds level, where level is of type String, to the list of levels returned by log.getLevels() that can be used as an instance method.
Returns Array of available priority levels.
Notes:
newLevelStrings are case-insensitive and will be converted to lowercase- Custom priority levels are assigned a 
levelIndexin order of their creation, starting at8when passed as anentryobject by the 'entry' event - Default priority levels cannot be overwritten by 
log.addLevelbut custom priority levels can be overwritten 
Removed level, where level is of type String, from the list of available priority levels returned by log.getLevels(). Levels with a levelIndex greater than level's former index are decremented by 1.
Returns String representing the removed level
Notes:
removeLevelcannot remove any of the default priority levels.- If the level being removed is currently in use as the log's priority, the log's priority will be set to 'debug'
 
Object is a set of key-value pairs, where keys are priority levels and values are messages to output if log.level matches the key. Unlike level methods such as log.warn(message), log.write(object) will only output the message associated with the priority. If no output is set for the configured priority, no output will be produced, regardless of whether the levelIndex of log.level is greater than the priorities set in log.write().
Example:
log.level = 'warn'
log.write({
  debug:     'Hark! A bug!',
  info:      'FYI...',
  notice:    'Hear ye!',
  warn:      'I tried to tell you.',
  error:     'Uh oh.',
  critical:  'Mayday!',
  alert:     'Um. Excuse me.',
  emergency: 'Going down!'
})
// Output: [WARN] I tried to tell you.Note: Assigning logging methods (such as log.error) directly to priority keys in log.write executes all methods contained in the object regardless of log.level. To change output based on the current priority level, use log.[priority](Object).
When message is of type String, message will be output without a label to logging destinations regardless of log.level. The entry prefix will still be prepended to message if configured.
NOTE: Using log.write(message) will not emit the 'entry' event.
Joshua Chumbley
Licensed under MIT

