DEV Community

Cover image for log-fns: a new JS logging library
Pudding
Pudding

Posted on

log-fns: a new JS logging library

log-fns

Abstract

The log-fns project is a simple lightweight logging library for JavaScript.

Quick Start

Installation

npm i log-fns

Enter fullscreen mode Exit fullscreen mode

Basic Usage

const { createLogger } = require('log-fns');

// Create a logger with the default configuration
const logger = createLogger();

// Log a string
logger.info('Hello, log-fns!');

// Log an object
logger.info({ greeting: 'Hello', name: 'Joan' });

// Defer calculation of an expensive message so it is not called if the log level isn't enabled
logger.trace(() => 'Hello, expensive trace message!');
Enter fullscreen mode Exit fullscreen mode

Output

{"timestamp":"2022-02-23T03:06:35.206Z","logLevel":"INFO","message":"Hello, log-fns!"}
{"timestamp":"2022-02-23T03:06:35.207Z","logLevel":"INFO","message":{"greeting":"Hello","name":"Joan"}}
Enter fullscreen mode Exit fullscreen mode

Why?

Well, most of the time we are just logging to the console, and if that's all you are doing, log-fns is probably for you.

Also, if you are implementing your own logging solution, this may be a good starting point, as it is highly configurable.

Features

  • Easy to understand and use
  • No object-oriented/imperative/mutable coding is required
  • Tiny (~5KB unpacked)
  • No dependencies
  • Very customizable

Configuration

Default Configuration

{
  logLevel: 'INFO',
  logLevels: ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'],
  getLogFunctionName: (logLevel) => logLevel.toLowerCase(),
  formatOutput: (o) => JSON.stringify(o),
  enrichMessage: ({ message, logLevel }) => ({
    timestamp: new Date().toISOString(),
    logLevel,
    message,
  }),
  writeOutput: ({ message }) => {
    console.log(message);
    return message;
  },
  noOp: () => ''
}
Enter fullscreen mode Exit fullscreen mode
Key Type Value
logLevel String Threshold below which no log output will occur
logLevels Array[String] List of all available log levels in order from least severe to most
getLogFunctionName Function Determines the log function name for a given log level
formatOutput Function Formats the output of the log message
enrichMessage Function Adds data such as the current timestamp to the output
writeOutput Function Writes the output to a destination such as the console
noOp Function Does nothing - called when a function's corresponding log level is not enabled

Log Level

  • A log level is a conceptual threshold below which no log output will occur, and at or above which, it will.
  • It is configured by setting the case-sensitive value of logLevel to one of the available levels in the configuration argument of createLogger() (case-sensitive).
  • Each log level is associated with a function of the same name, but in all lower-case.

Available Levels

These log levels are available in order from most verbose or least severe, to least verbose or most severe:

['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']
Enter fullscreen mode Exit fullscreen mode

The default log level is 'INFO', which means any messages associated with the 'TRACE' OR 'DEBUG' levels will not be output, and all others will.

Configuring the Log Level

const logger = createLogger({ 
  logLevel: 'DEBUG' 
});

logger.trace('Tracing...');
logger.debug('Debugging...');
logger.warn('Warning...');
Enter fullscreen mode Exit fullscreen mode

Output

{"timestamp":"2022-02-23T06:08:04.424Z","logLevel":"DEBUG","message":"Debugging..."}
{"timestamp":"2022-02-23T06:08:04.452Z","logLevel":"WARN","message":"Warning..."}
Enter fullscreen mode Exit fullscreen mode

Custom Log Levels

By default, the log function names are the same as their corresponding log levels, but in all lowercase.

If log levels are not also legal javascript function names, you'll need to customize them using the getLogFunctionName configuration attribute.

You'll also need to configure the logLevel since it is 'INFO' by default, and if no log levels by that name exist, no log output will occur.

const logger = createLogger({
  logLevel: 'NORMAL',
  logLevels: ['NORMAL', 'WARNING', 'ERROR'],
});

logger.normal('Normal log entry...');
logger.warning('Warning log entry...');
logger.error('Error log entry...');
Enter fullscreen mode Exit fullscreen mode

Output

{"timestamp":"2022-02-24T01:47:23.238Z","logLevel":"NORMAL","message":"Normal log entry..."}
{"timestamp":"2022-02-24T01:47:23.263Z","logLevel":"WARNING","message":"Warning log entry..."}
{"timestamp":"2022-02-24T01:47:23.265Z","logLevel":"ERROR","message":"Error log entry..."}
Enter fullscreen mode Exit fullscreen mode

Customizing the Log Function Names

const logger = createLogger({
  logLevel: 'REGULAR LOGGING',
  logLevels: ['VERBOSE LOGGING', 'REGULAR LOGGING', 'ERROR LOGGING'],
  getLogFunctionName: (logLevel) => ({
    'VERBOSE LOGGING': 'logVerbose',
    'REGULAR LOGGING': 'logRegular',
    'ERROR LOGGING': 'logError',
  })[logLevel],
});

logger.logVerbose('Verbose logging...');
logger.logRegular('Regular logging...');
logger.logError('Error logging...');
Enter fullscreen mode Exit fullscreen mode

Output

{"timestamp":"2022-02-24T02:04:24.046Z","logLevel":"REGULAR LOGGING","message":"Regular logging..."}
{"timestamp":"2022-02-24T02:04:24.071Z","logLevel":"ERROR LOGGING","message":"Error logging..."}
Enter fullscreen mode Exit fullscreen mode

Customizing the Log Format

By default, output is in JSON format, but this can be changed.

const formatOutput = ({ timestamp, logLevel, message }) => `${timestamp}|${logLevel}|${(typeof message === 'string') ? message : JSON.stringify(message)}`;
const logger = createLogger({ formatOutput });

logger.info('Info message...');
Enter fullscreen mode Exit fullscreen mode

Output

2022-02-24T02:28:54.858Z|INFO|Info message...
Enter fullscreen mode Exit fullscreen mode

Customizing the message enrichment

By default, messages are enriched with the timestamp and log level, but this can be changed.

const enrichMessage = ({ message, logLevel }) => ({
  unixTime: new Date().getTime(),
  appName: 'my-app',
  loggerName: 'my-logger',
  logLevel,
  message,
});
const logger = createLogger({ enrichMessage });

logger.info('Info message...');
Enter fullscreen mode Exit fullscreen mode

Output

{"unixTime":1645672340194,"appName":"my-app","loggerName":"my-logger","logLevel":"INFO","message":"Info message..."}
Enter fullscreen mode Exit fullscreen mode

Customizing the Output

By default, log entries are written to the console, but this can be changed.

For example, the configuration below writes errors to console.error, and everything else to console.log.

const writeOutput = ({ logLevel, message }) => {
  (logLevel === 'ERROR' ? console.error : console.log)(message);
  return message;
};
const logger = createLogger({ writeOutput });

logger.info('Info message...');
logger.error('Error message...');
Enter fullscreen mode Exit fullscreen mode

Output

(console.log)
{"timestamp":"2022-02-24T02:57:53.469Z","logLevel":"INFO","message":"Info message..."}
(console.error)
{"timestamp":"2022-02-24T02:57:53.497Z","logLevel":"ERROR","message":"Error message..."}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)