CyberSEO Pro plugin for WordPress

Winston Logger - Full tutorial with a sample Nodejs application

Read Time:7 Minute, 52 Second

Winston Logger is one of the most popular logging libraries for Node.js. It is designed to be a simple and universal logging library supporting multiple modes of transport. A transport is essentially a storage device for the logs.

Each logger can have multiple modes of transport configured at different levels. For example, one may want error logs stored in a database, but all logs output to the console or a local file.

Some of the features of Winston logger are:

  • Logging Levels
  • Transports
  • Formats
  • Profiling

What are logging levels in Winston logger?

Logging levels in winston follow the severity ordering specified by RFC5424: severity of all levels is assumed to be numerically ascending from most important to least important*.*

Each level is given a specific integer priority. The higher the priority, the more important the message is considered, and the lower the corresponding integer priority. For example, as specified in RFC5424 the syslog levels are prioritized from 0 to 7 (highest to lowest).

{ emerg: 0, alert: 1, crit: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7
}
Enter fullscreen mode Exit fullscreen mode

Similarly, npm logging levels are prioritized from 0 to 6 (highest to lowest):

{ error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
}
Enter fullscreen mode Exit fullscreen mode

What are Transports in Winston logger?

A transport is a storage device or output mechanism for our logs. Each Winston logger can have multiple modes of transport configured at different levels.

Winston comes with three core modes of transport: console, file, and HTTP. The transports must be created and added to the loggers.

Here’s how we initialize different transports:

  • *Console Transport:*

    logger.add(new winston.transports.Console(options));
    
  • File Transport:

    logger.add(new winston.transports.File(options));
    
  • HTTP Transport:

    logger.add(new winston.transports.Http(options));
    

Formats in Winston logger

Formats in winston can be accessed from winston.format. They are implemented in [logform](https://github.com/winstonjs/logform), a separate module from winston. This allows flexibility when writing your transports in case you wish to include a default format with your transport.

In modern versions of node template strings are very performant and are the recommended way for doing most end-user formatting.

Profiling with Winston logger

In addition to logging messages and metadata, winston also has a simple profiling mechanism implemented for any logger.

All profile messages are set to the ‘info’ level by default, and both message and metadata are optional. For individual profile messages, you can override the default log level by supplying a metadata object with a level property:

logger.profile('test', { level: 'debug' });
Enter fullscreen mode Exit fullscreen mode

Prerequisites

Getting Started with Winston Logger

Create a node project in the current directory:

mkdir winston-nodejs-example
cd winston-nodejs-example 
Enter fullscreen mode Exit fullscreen mode

Initialize an npm project:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install express and winston packages:

npm i winston express
Enter fullscreen mode Exit fullscreen mode

Create an entry file called index.js file:

touch index.js
Enter fullscreen mode Exit fullscreen mode

Create a basic hello world express app:

const express = require("express");
const PORT = process.env.PORT || "5555";
const app = express(); app.use(express.json()) app.get("/", (req, res) => { res.json({ method: req.method, message: "Hello World", ...req.body });
}); app.get('/404', (req, res) => { res.sendStatus(404);
}) app.get("/user", (req, res, next) => { try { throw new Error("Invalid user"); } catch (error) { res.status(500).send("Error!"); } }); app.listen(parseInt(PORT, 10), () => { console.log(`Listening on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Run the server with the below command and hit http://localhost:5555:

node index.js
Enter fullscreen mode Exit fullscreen mode

If done correctly, the console should show Listening on http://localhost:5555

Winston Logger – Full tutorial with a sample Nodejs application
Basic nodejs express app

Now, in the current directory, create a logger.js file in which we will be configuring the winston logger:

const {createLogger, format, transports} = require("winston"); const logger = createLogger({ level: "debug", format: format.json(), transports: [new transports.Console()],
}); module.exports = logger;
Enter fullscreen mode Exit fullscreen mode

At this point, the project structure should look like this:

/node_modules
/index.js
/logger.js
/package-lock.json
/package.json
Enter fullscreen mode Exit fullscreen mode

Import the logger and use it wherever required. The final index.js after using the logger looks something like this:

const express = require("express");
const logger = require("./logger");
const PORT = process.env.PORT || "5555";
const app = express(); app.use(express.json()) app.get("/", (req, res) => { logger.log("debug", "Hello, World!"); //debug level as first param logger.debug("The is the home '/' route."); // using debug method directly res.json({ method: req.method, message: "Hello World", ...req.body });
}); app.get('/404', (req, res) => { logger.error("404 error"); //error method logger.debug("The is the 404 route."); res.sendStatus(404);
}) app.get("/user", (req, res) => { try { throw new Error("Invalid user"); } catch (error) { logger.error("Auth Error: invalid user"); logger.debug("The is the user route."); res.status(500).send("Error!"); } }); app.listen(parseInt(PORT, 10), () => { console.log(`Listening on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Logs will be captured depending on the route we hit.

Home route

nodejs express app home route
Nodejs Express app home route

Home route logs

winston logs for home route
winston logs for home route

User error route

Nodejs express error route
Nodejs express error route

User error logs

User Error logs
User error logs

404 route

Nodejs express app 404 route
Nodejs express app 404 route

404 route logs

404 route logs
404 route logs

In a production environment, you will need a log management tool to store and manage your logs efficiently. In this tutorial, we will use SigNoz – an open source APM and observability tool for logs collected by Winston logging library.

Log management in SigNoz

SigNoz is full-stack open source Application Performance Monitoring tool that you can use for monitoring logs, metrics, and traces. Having all the important telemetry signals under a single dashboard leads to less operational overhead. Users can also access telemetry data with richer context by correlating these signals.

SigNoz uses a columnar database – ClickHouse, for storing logs efficiently. Big companies like Uber and Cloudflare have shifted from Elasticsearch to ClickHouse for storing their log data.

Sending logs to SigNoz deployed on Docker

We will dockerize our nodejs application and run the application in Docker. We will be using the console transport for winston. If SigNoz is running on the same host, it will automatically start collecting logs of all the docker containers.

Installing and running the SigNoz app

SigNoz can be installed on macOS or Linux computers in just three steps by using a simple install script.

The install script automatically installs Docker Engine on Linux. However, on macOS, you must manually install Docker Engine before running the install script.

git clone -b main https://github.com/SigNoz/signoz.git
cd signoz/deploy/
./install.sh
Enter fullscreen mode Exit fullscreen mode

Dockerising the Node app

Create a docker-compose.yaml file and paste the following code:

version: "3.9" services: app: container_name: app image: app restart: always build: context: . dockerfile: Dockerfile target: base ports: - "${PORT}:${PORT}"
Enter fullscreen mode Exit fullscreen mode

Create a Dockerfile (no file extension needed) and paste the following code:

FROM node:alpine as base WORKDIR /winston-nodejs-example # current project name COPY package.json ./ RUN rm -rf node_modules && npm i COPY . . CMD ["node", "index.js"]
Enter fullscreen mode Exit fullscreen mode

Before we can deploy our app on a Docker container, we need to set up the environment variable we will need to run the app. Create a file named .env in the root directory of your folder.

Since we defined the port as a variable in the docker-compose.yml file, we need to set the port in the .env file:

PORT=5555
Enter fullscreen mode Exit fullscreen mode

Running the app

Finally, we can deploy the Node app on a Docker container. To do so, use Docker Compose:

docker compose up --build
Enter fullscreen mode Exit fullscreen mode

Once the build is successfully run, you should be able to see the following logs on the console.

Nodejs Winston logs on console
Nodejs Winston logs on console

Observing the logs on SigNoz

Now, hit the different routes we’ve hit earlier to check the logs i.e /, /404, /user and we should be able to watch the logs in SigNoz as follows.

winston logs with SigNoz
winston logs with SigNoz
winston logs with SigNoz
winston logs with SigNoz
winston logs with SigNoz
winston logs with SigNoz

If SigNoz is installed on a different host, you can collect logs by following these instructions.

Conclusion

Logs play an essential part in a developer’s workflow and are critical to debugging applications. Winston is a simple logging library and makes the logging process more flexible and extensible. Once the logs are generated, you can collect them with SigNoz.

SigNoz uses OpenTelemetry to collect logs. With OpenTelemetry, you can also correlate your logs with other telemetry signals like metrics and traces. Having contextual information in your logs can help you debug applications faster. You can get an overview of logs management in SigNoz from the logs documentation.


Related Posts

SigNoz – a lightweight open source ELK alternative

Source: https://dev.to/signoz/winston-logger-full-tutorial-with-a-sample-nodejs-application-2fm9

All About Shopify Analytics Previous post All About Shopify Analytics
JavaScript Array slice() method Next post JavaScript Array slice() method

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.