Winston is a popular logging library for NodeJS which allows you to customise the output, as well as different logging targets.
This lesson covers configuring Winston to run with different levels depending on a Node environment variable as well as enhancing the log output to include the filename and line number the log message originates from.
Instructor: [00:00] Winston is a very useful node package for dealing with logging, and it can log two various transports including the console, file system or third parties. To start with, we just include into our standard node application here the winston package.
[00:15] Then, as an example of logging out some output, I'm going to output what the service started. We use the info level. There are various levels that you can use in winston, debug, error. Depending on how you set it up, you can filter off logging messages.
[00:30] For now, we're going to pass in the package name for this project, what the port number is. If I start the server up now, we can see the output. That's the initial default output for winston, but we can do much better than that. Let's move on to that now.
[00:46] To enhance our winston login, we're going to create a new logger file where we can add in some additional properties. Let's start by first importing winston. We're also going to include moment, because we're going to do some date/time formatting.
[00:58] The first thing we're going to do is set up a new transport. This one, we're just going to deal with the console first of all. One of the properties we can set on the console is a timestamp, and we're going to use moment to format that.
[01:18] We're also going to colorize the output for our terminal. This makes it easy to identify when there's errors. Now we've got our transport, we're going to instantiate a logger instance and pass it the transport.
[01:30] One of the options winston gives you is to decide whether you want to exit the node application when there's an error. In fact, normally, you'd probably want to manage the error yourself and not have the node jest process terminate. I'm going to set that to false.
[01:49] Then we're just going to export the logger instance. Going back into our server js file, we're going to get rid of winston, and this time, import our logger. Our info message, we're going to change to use our logger.
[02:03] Going back to my terminal, start the server. This time, we've got a formatted date/time, and we got some colorization for the info login. Let's move on. Like any good login system, winston has the ability to define different levels of logging.
[02:29] This means for different error messages, we can add more granularity when we're debugging or when we're in production. To start with, we're going to add a specific level to the console. We're going to make sure that we capture all debug messages and above. This would include info and error.
[02:50] To demonstrate a debug message running along with info, we're going to set up a small interval. We now start our server up, and we should see info level and debug level. The problem with the debug level is it's going to flood our logging system with unnecessary messages once we go into production.
[03:12] Therefore, we're going to have to sort out how we can disable debug level once we are in production. We're going to do that now. Going back into our logger file, what we're going to do is add a setting depending on our node environment.
[03:26] The node environment is an environment variable that can be set when we first launch the application. It's available to us through the process. If our node environment = production, we will set our logger level to info.
[03:40] I'm running on Windows using the PowerShell. I'm going to change my node environment now to production, and then start my server. This time, all I get is the info message.
[03:53] Our next step is we want to make winston logging a little bit more useful to us. One of the things we want to do is actually identify or easily identify where the debug message or error message or info message is occurring within our application. In other words, which file and which line.
[04:11] The first thing we need to do is include the project route so that we can determine where the file location is. We're just going to join the paths with a separator with two dots.
[04:22] The next thing is we need the stack information that the node process gives us, and from that, we can work out the file path. I haven't written this particular function, I've taken it from Google Code.
[04:35] I'm going to paste it in. As I say, this will basically get hold of the stack information, and that's where we use our project route. Next, we need to override the winston methods for calling our logger. For instance, debug, own, log, etc.
[04:51] For each one, we need to override it, and we're going to use that here. Here's an example. We're calling logger.info, and we're applying a new function to it which is going to pass it some arguments. Which is passed to it from winston.
[05:04] The next thing we need to do is create our format log arguments method. We'll pass in the arguments. We need to convert the arguments, potentially, into a array from an array-like object.
[05:16] We then get the stack information using our stack info. If we get some stack information, we can then return it. We use some ES6 formatting here just to build up between the location of the file and the line number.
[05:32] We just need to do a simple check to make sure that the first argument is a string, or if not, we will push the stack information to the beginning of the array. Finally, we return back the arguments with the line number and file location.
[06:00] If we start our server again, we can see that the information now includes the location of a file -- which is server.js in this case. Line number 12 is where this log message is running from.