woodlot JSON Logging Utility

repository·master·Indexed 42 days ago

https://github.com/adpushup/woodlot

An all-in-one JSON logging utility for Node.js applications (v3.3.3) featuring ExpressJS HTTP logging middleware and a custom logger for manual application logging. It supports multiple output formats (JSON, common, combined), file streams, and an events API to track logging operations. Includes built-in support for user analytics (platform and country) and ANSI colorization for stdout output.

Tokens
4K
Snippets
11
Records
14
Agent score
53%

What's inside woodlot

  1. Use woodlot as ExpressJS middleware

    master

    The middlewareLogger can be integrated into your ExpressJS middleware chain to log all incoming HTTP requests. It supports various configurations for file streams, route whitelisting, user analytics, and output formats like json, common, or combined (Apache formats).

    Important Note: To log request body or cookies in json format, you must enable bodyParser and cookieParser middlewares in Express before adding the woodlot middleware.

    var express = require('express');
    var app = express();
    var woodlot = require('woodlot').middlewareLogger;
    
    app.use(
    	woodlot({
    		streams: ['./logs/app.log'],
    		stdout: false,
    		routes: {
    			whitelist: ['/api', '/dashboard'],
    			strictChecking: false
    		},
    		userAnalytics: {
    			platform: true,
    			country: true
    		},
    		format: {
    			type: 'json',
    			options: {
    				cookies: true,
    				headers: true,
    				spacing: 4,
    				separator: '\n'
    			}
    		}
    	})
    );
  2. Use customLogger events for logging hooks

    master

    Whenever a log is generated via the customLogger methods (info, debug, warn, err), the library fires a customLoggerEvent. This allows you to hook into the logging lifecycle to perform side effects or custom processing based on the log level and the log content.

    Events are triggered via the fireCustomLoggerEvent(level, log) internal mechanism.

  3. Configure middlewareLogger options

    master

    When using middlewareLogger, you can pass an options object to customize behavior:

    • streams {array}: File stream endpoints where logs are saved. Supports multiple streams.
    • stdout {boolean}: Whether to log to process.stdout. Defaults to true.
    • routes {object}:
      • whitelist {array}: Array of routes to enable logging for.
      • strictChecking {boolean}: If false (default), logging is enabled for any route containing a whitelisted string (e.g., /api matches /api/user). If true, it only matches the exact route.
    • userAnalytics {object}:
      • platform {boolean}: Include browser, browserVersion, os, and osVersion. Defaults to false.
      • country {boolean}: Include name and isoCode. Defaults to false.
    • format {object}:
      • type {string}: Output format. Options: 'json' (default), 'common', or 'combined'.
      • options {object} (for json type only):
        • cookies {boolean}: Log request cookies. Requires cookieParser middleware. Defaults to false.
        • headers {boolean}: Log request headers. Defaults to true.
        • compact {boolean}: Log JSON as a single-line string. If true, spacing is ignored. Defaults to false.
        • spacing {string|number}: Indentation for JSON (e.g., \t, 4, 8). Defaults to \t.
        • separator {string}: Separator between log entries (e.g., \n). Defaults to \n.
  4. Listen to woodlot events

    master

    Woodlot provides an events API via require('woodlot').events to track logging operations. The returned log entry in the callback matches the format defined in your configuration.

    middlewareLogger events

    • reqLog: Fired whenever a log entry is generated.
    • :statusCode: Fired whenever a specific HTTP status code is returned (e.g., '200', '403').
    • reqErr: Fired whenever a request returns a status code >= 400.

    customLogger events

    • info: Fired on info level logs.
    • debug: Fired on debug level logs.
    • warn: Fired on warn level logs.
    • err: Fired on err level logs.
    var woodlotEvents = require('woodlot').events;
    
    // Example: Listen for all request logs
    woodlotEvents.on('reqLog', function (log) {
    	console.log('New log generated');
    });
    
    // Example: Listen for specific status codes
    woodlotEvents.on('403', function (log) {
    	console.log('Request forbidden!');
    });
    
    // Example: Listen for errors
    woodlotEvents.on('reqErr', function (log) {
    	console.log('Errored!');
    });
  5. Use customLogger for manual logging

    master

    The customLogger allows you to perform manual logging with specific levels. You instantiate it with a configuration object similar to the middleware, then call level-specific methods.

    Supported Log Levels:

    • woodlot.info(message)
    • woodlot.debug(message)
    • woodlot.warn(message)
    • woodlot.err(message)

    Custom Formats:

    • json: Logs an object containing timeStamp, message, and level.
    • text: Logs a string in the format LEVEL [timeStamp]: "message".
    var express = require('express');
    var app = express();
    var woodlotCustomLogger = require('woodlot').customLogger;
    
    var woodlot = new woodlotCustomLogger({
    	streams: ['./logs/custom.log'],
    	stdout: false,
    	format: {
    		type: 'json',
    		options: {
    			spacing: 4,
    				separator: '\n'
    		}
    	}
    });
    
    app.get('/', function (req, res) {
    	var id = 4533;
    	woodlot.info('User id ' + id + ' accessed');
    	return res.status(200).send({ userId: id });
    });
  6. Initialize woodlot as ExpressJS middleware using middlewareLogger()

    master

    The middlewareLogger function is the primary entry point for using woodlot as an ExpressJS middleware. It accepts a config object to define how logs are handled, which routes are included, and how data is formatted.

    Configuration Options

    KeyTypeDefaultDescription
    streamsArray[]An array of log streams. If no streams are provided and logToConsole is false, the middleware will effectively do nothing and pass control to the next middleware.
    stdoutBooleantrueIf present in config, determines if logs are sent to the console. Controlled via config.logToConsole internally.
    routes.whitelistArray[]An array of route patterns. If provided, only requests matching these routes will be logged.
    format.options.headersBooleantrueDetermines if request headers are included in the log output.

    Behavior

    • Route Whitelisting: If config.routes.whitelist is provided, the middleware only processes requests that match the whitelist. Otherwise, it processes all requests.
    • No-op Mode: If config.streams is empty and config.stdout is not set to true, the middleware will log a configuration warning and call next() without performing any logging.
    const { middlewareLogger } = require('woodlot');
    
    const loggerMiddleware = middlewareLogger({
      streams: [/* your log streams here */],
      stdout: true,
      routes: {
        whitelist: ['/api/v1', '/health']
      },
      format: {
        options: {
          headers: true
        }
      }
    });
    
    // Use in Express
    app.use(loggerMiddleware);
  7. Listen to Woodlot middleware logger events

    master

    Woodlot emits events during the middleware logging lifecycle that you can listen to via the woodlotEvents EventEmitter. These events allow you to react to specific log entries or HTTP status codes.

    Available events emitted by fireMiddlewareEvents:

    • EVENTS.LOG: Emitted for every log entry.
    • res.statusCode: Emitted for every response, using the HTTP status code as the event name (e.g., 200, 404).
    • EVENTS.ERR: Emitted whenever a client or server error occurs (status code >= 400).

    Note: You must access the woodlotEvents instance from the module to attach listeners.

    const { woodlotEvents } = require('woodlot/lib/events');
    
    // Listen for all logs
    woodlotEvents.on('log', (log) => {
      console.log('New log:', log);
    });
    
    // Listen for specific HTTP status codes
    woodlotEvents.on('404', (log) => {
      console.warn('Not Found error:', log);
    });
    
    // Listen for all errors (status >= 400)
    woodlotEvents.on('error', (log) => {
      console.error('An error occurred:', log);
    });
  8. Configure and use the customLogger

    master

    The customLogger is a module used for manual logging with different levels. When initialized, it accepts a config object that determines how logs are formatted, where they are sent (streams), and whether they are printed to the console.

    Configuration Options

    • streams: An array of file streams where logs should be written. If this is missing or empty, logs will not be written to files.
    • stdout: A boolean. If present in the config, it sets the logToConsole behavior. If true, logs are printed to process.stdout. If false, they are not.
    • level: The logging level (e.g., 'info', 'debug', 'warn', 'err'). Defaults to 'info' if not specified during a log call.
    • format: Determines if logs are generated as 'text' or 'json'. (Note: The specific key for format is managed via internal utils.getLogFormat(config) calls).

    Available Logging Methods

    The logger instance provides the following methods to log messages at specific levels:

    • info(message)
    • debug(message)
    • warn(message)
    • err(message)
    const customLogger = require('woodlot/lib/customLogger');
    
    const logger = new customLogger({
        streams: [/* your file streams here */],
        stdout: true
    });
    
    logger.info('This is an info message');
    logger.err('This is an error message');
  9. Listen to Woodlot custom logger events

    master

    If you are using a custom logger, you can trigger and listen to arbitrary events using fireCustomLoggerEvent. This allows you to emit specific log levels or custom event names that can be intercepted by listeners on the woodlotEvents instance.

    const { woodlotEvents, fireCustomLoggerEvent } = require('woodlot/lib/events');
    
    // Register a listener for a custom level
    woodlotEvents.on('info', (log) => {
      console.log('Info level log:', log);
    });
    
    // Trigger the event
    fireCustomLoggerEvent('info', { message: 'Custom info log' });
  10. Generate user analytics with generateUserAnalytics()

    master

    The generateUserAnalytics function creates an object containing user metadata such as platform information (browser, OS) and geographic location (country) based on the provided configuration and request parameters.

    Configuration Options

    The config object determines which types of analytics are processed:

    • platform: (Boolean) If true, parses the userAgent to extract browser and OS details.
    • country: (Boolean) If true, uses the ip to look up the user's country via a MaxMind GeoLite2 database.

    Parameters

    The params object must contain the following keys depending on the configuration:

    • userAgent: (String) The user agent string. Must not be '-' to trigger platform parsing.
    • ip: (String) The user's IP address. Must be a valid IP string.

    Return Value

    A JSON object containing the requested analytics. For example:

    {
      "browser": "Chrome",
      "browserVersion": "91.0.4472.124",
      "os": "Windows",
      "osVersion": "10",
      "country": "United States"
    }
    const generateUserAnalytics = require('./lib/userAnalytics');
    
    const config = { platform: true, country: true };
    const params = { 
      userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...', 
      ip: '127.0.0.1' 
    };
    
    const analytics = generateUserAnalytics(config, params);
  11. Format stdout output with colorization

    master

    The stdoutFormatting module provides utilities to apply ANSI color codes and text styling to log strings. It includes specific helpers for colorizing HTTP status codes, log levels, and entire log lines based on common formats like Apache (Common/Combined), Text, and JSON.

    Available Color Helpers

    • foregroundGreen(text)
    • foregroundBlue(text)
    • foregroundYellow(text)
    • foregroundRed(text)
    • underlineText(text)

    Log-Specific Colorization

    • colorizeStatusCode(statusCode): Colors status codes based on range (2xx: Green, 3xx: Blue, 4xx: Yellow, others: Red).
    • colorizeLogLevel(level): Colors log levels (debug: Blue, warn: Yellow, err: Red, info/default: Green).
    • colorizeStdoutFormat(log, format, compact): Applies colorization to a full log string based on the specified format.

    Supported Formats for colorizeStdoutFormat

    • combined or common: Uses Apache regex to colorize the status code.
    • text: Uses text regex to colorize the log level.
    • customleveljson: Colorizes the level field in a JSON string. If compact is true, it uses a more condensed regex pattern.
    • json: Colorizes the statusCode field in a JSON string. If compact is true, it uses a more condensed regex pattern.
    const formatter = require('./lib/stdoutFormatting');
    
    // Example: Colorizing a status code
    const coloredStatus = formatter.colorizeStatusCode(200);
    
    // Example: Colorizing a full log line in JSON format
    const log = '{"statusCode": 404, "message": "Not Found"}';
    const coloredLog = formatter.colorizeStdoutFormat(log, 'json', false);