Structured logging from Node.js to Seq

The benefits of centralized, structured logging should be available to all technology stacks, which is why there are Seq clients for many different programming languages, including Python, Java and JavaScript (Node.js).

For Node.js developers there are several libraries that make it easier to send structured log events from Node.js applications to Seq, including bunyan-seq, pino-seq and most recently @datalust/winston-seq.

winston is a logging library for Node.js. It's like Serilog, but for JavaScript. To provide different log event destinations Serilog has sinks, and winston has transports. Using different transports winston can log to the console, text files, AWS Cloudwatch, Seq and many other destinations. @datalust/winston-seq is the winston transport for sending log events to Seq.

This post demonstrates how to configure winston and @datalust/winston-seq to send log events from a Node.js application to Seq.

1. Install the winston and @datalust/winston-seq npm modules

npm install winston @datalust/winston-seq
NOTE: The npm package name is @datalust/winston-seq. There is a different package called winston-seq that is built for an older version of winston and is not maintained by Datalust.


2. Create a winston logger within the application

This example sends log events to the console and to Seq. Set the serverUrl to the ingestion endpoint of your Seq server. Set the apiKey to an API key with the Ingest permission.

const winston = require('winston');
const { SeqTransport } = require('@datalust/winston-seq');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(  
    winston.format.errors({ stack: true }),
    winston.format.json(),
  ),
  transports: [
    new winston.transports.Console({
        format: winston.format.simple(),
    }),
    new SeqTransport({
      serverUrl: "https://your-seq-server",
      apiKey: "your-api-key",
      onError: (e => { console.error(e) }),
      handleExceptions: true,
      handleRejections: true,
    })
  ]
});


3. Call log methods on the logger to send log events

There are different methods for different log levels. In the following example, {arch} and {speed} are log event properties. Their values are provided as properties on the object that is the second argument to logger.info.

logger.info("My CPU is {arch} at {speed}GHz", { 
  arch: os.arch(), 
  speed: os.cpus()[0].speed/1000 
});

logger.warn("I'm warning you");

logger.error("Something doesn't feel right");


4. Watch the events appear in Seq

5. Create signals, dashboards, and alerts

Create signals, dashboards, and alerts that provide insight into the behavior of your Node.js application.

Finally

It is essential to understand what is happening within a running application, and to be able to diagnose issues when problems occur in production. winston and @datalust/winston-seq provide another way to bring this capability to the JavaScript development community.

For more @datalust/winston-seq configuration scenarios refer to the @datalust/winston-seq website.