Blog DevOps

Using Winston 3 for Logging in Node.js

By Jason Skowrowski 22 May 2019

Winston is one of the most popular and versatile logging libraries for Node.js. With Winston, you can differentiate and redirect your logs to different places depending on their severity or purpose, and ensure there are redundant records in case of any failures or corruption later on.

With the Winston 3.0 update, one of the biggest changes is the ability to apply custom formatting to your logs. Any pre-processing that needs to happen, such as renaming fields, rearranging text, and anything else you can think of, is now possible without having to hack Winston itself.

We’ll show you how to add Winston to one of your applications with an Express server example, and even use the morgan library to create access logs. We’ll also show how you to send those logs to SolarWinds® Loggly®. Loggly is a perfect target for Winston, since it will help ensure your application logs are securely stored on the cloud, and make them available for search, analytics, and configurable alerts.

How to Add Winston 3 to an App

Let’s see how to add Winston in an example Express app. For our purposes, we’ll create an app that generates a random HTTP request a few times a minute, and watch the results live in the Loggly dashboard.

First, we’ll build the basic app. Create a folder for the project and open up your terminal. Type in:

> npm init
> npm install –save express morgan winston

Once that installs, let’s create a minimal echo server with express and morgan. We’ll do this in four files, to keep things nice and tidy. Create the following:

index.js, logger.js, requester.js, config.json.

If you’re using git, make sure to add config.json to your .gitignore, since we’re going to store our API tokens in it for now.

Now, let’s create the app inside index.js:

All this little guy does is set up an express app, add morgan logging to it, and create a catchall route that simply sends any URL that gets requested right back to the client. You can run it right now on the command line; enter:

> node index.js

Then open a new terminal and enter:

> curl localhost:3030/hello

In the terminal where you ran index.js, you should see something like:

> ::ffff: – – [28/Jun/2018:20:57:56 +0000] “GET /hello HTTP/1.1” 200 6 “-“ “curl/7.58.0”

And where you made the curl command, you should see:

> /hello

That shows everything’s working properly in our test app; now we can get to the interesting part.

Configuring Loggly in Winston

Let’s get logging. The first step is to install official Winston module from Loggly. Normally you’d add it like this:

> npm install –save express winston-loggly-bulk

Go to your Loggly account and create a new API token. Click on the cloud icon on the top bar, then click Customer Tokens underneath that. There you should be able to click Add New, and get a new token you can use to submit logs. Once you have the token, open up config.json and enter the following, substituting your real token:

Now let’s get to the meat of the logging app. Open up logger.js and we’ll configure Winston and Loggly.

Okay, whew. We’re doing a couple of things here. We’ve required in the Loggly transport constructor, Winston, and the config file we just made. Then we add a few transports to Winston. Winston’s real strength is in the ways you can split and route your logs within their framework. For now, we won’t get too fancy; we’ve added just two transports. First is the Loggly transport, which you feed the config we just made, and second is the console transport, which will let us compare what our app is putting out locally to what Loggly is receiving in the cloud.

Finally, we add a very basic stream method to the logger. There are various ways to do this—some built in to winston-loggly-bulk, and others that you can implement yourself. For the moment, I’ve chosen to keep it minimal and simple.

Now we’ll add the logger to the index file, like so:

Morgan is now set up to stream, and we can also use the logger on its own, as you can see below app.listen. Now, let’s see what happens.

Viewing the Logs in Loggly

Open up your Loggly account again, and this time go to Live Tail (the icon that looks like a command prompt: >_). Once there, enter “Winston’ in the search box and hit Start to begin watching for any logs sent to Loggly in real time.

Now, run the index.js again with node, and make a request with curl, just like last time. You should see something like this on the terminal:

> listening on port: 3030
> {“message”:“::ffff: – – [28/Jun/2018:21:23:37 +0000] \”GET /hello HTTP/1.1\” 200 6 \”-\” \”curl/7.58.0\”\n”,“level”:“info”}

And you should see something like this on the live tail page of Loggly:

Sweet! That looks nice. We can also check the log on any Loggly dashboards we have set up, and start looking at analytics.

Generating More Logs

One single log is not that interesting. Let’s make a bunch of them. Open up the file requester.js and add the following little test harness:

Every time we call this method, it will build a URL like localhost:3030/home/landing or localhost:3030/test/shop or something like that. Feel free to add whatever you like to the paths array for more variety. Let’s add it to index.js:

Now you can watch the logs start pouring into the Loggly live tail feature as they also stream across the console. From here you can play with the search page, look at other types of event to log, or crank up the firehose by reducing the request interval (try dropping it to 200ms to see a massive wall of logs).

For a better idea of the ways you can format and redirect your data with Winston, take a glance at Winston’s official readme. This, of course, is a toy application—just enough to get your feet wet. From here, you should take a look at the many features in Loggly for ideas on how to get the most out of your logs. With Winston 3.0 and Loggly, you can get alerts on problems with your application and troubleshoot problems faster.

The Loggly and SolarWinds trademarks, service marks, and logos are the exclusive property of SolarWinds Worldwide, LLC or its affiliates. All other trademarks are the property of their respective owners.
Jason Skowrowski

Jason Skowrowski

Share Your Thoughts