Server logging

In any production system, server logs are an integral part of monitoring and troubleshooting a live running system. For Node applications, this is no different. There are a couple of handy modules that we will take a quick look at to enhance our server logging so that it can be more useful in a production setting.

The first module is named rotating-file-stream, and will rotate logs on the server according to a configurable set of rules. When logging in a production environment, we need to take care that server logs do not get too large, otherwise we could run the risk of running out of disk space. With a rotating log, a new file will be created after a period of time, with a new name, and the maximum size of log files can be configured. This ensures that we can limit the amount of files that are generated, and do not run the risk of overloading the server.

The second utility is named moment-timezone, and is used to manipulate dates and times by taking into consideration the configured time zone. We can therefore represent the same date and time in multiple time zones. It also has a full range of utilities that can handle any input date format, which is incredibly useful when working with dates and times. REST endpoints generally use ISO string format for representing dates, and these are generally in UTC. JavaScript, however, uses a native Date object, which represents the number of milliseconds since an epoch. Correctly converting between these date representations can become highly confusing, frustrating, and time-consuming. Throw in multiple time zones, and it can quickly become a nightmare. The moment-timezone library, however, makes working with dates and times within a time zone very simple.

We will update our server code in three ways. Firstly, we will add a timezone configuration parameter, as we have done for the server port earlier. Secondly, we will configure a rotating file stream for our server logs. Finally, we will write a simple logging function that will use the rotating file stream and our configured time zone to log messages to the console in both UTC and local time.

First up is the configuration of our time zone, which is accomplished as follows:

enum ConfigOptions { 
    PORT = 'port', 
    TIMEZONE = 'timezone' 
} 
 
let timezone = "Australia/Perth"; 
 
if (config.has(ConfigOptions.TIMEZONE)) { 
    timezone = config.get(ConfigOptions.TIMEZONE); 
} else { 
    serverLog(`no timezone specified, using ${timezone}`) 
} 

Here, we have added a TIMEZONE enum value to our ConfigOptions, and set the internal string value to 'timezone'. We then create a local variable named timezone, and set it to the default of 'Australia/Perth'. We then check through the config.has function if our current runtime configuration has an override value for timezone, and use it if it has. This is no different to the logic that we used to set the default port property. We will discuss the serverLog function a little later.

Next up, we will install the rotating-file-stream module as follows:

npm install rotating-file-stream  

We can create a rotating log as follows:

var logDirectory = path.join(__dirname, 'log') 
 
// ensure log directory exists 
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory) 
 
// create a rotating write stream 
var accessLogStream = rfs('main.log', { 
    interval: '10s', // rotate every 10 seconds 
    path: logDirectory, 
    maxFiles: 7 
}); 

Here, we start by figuring out the directory name for log files based on the current working directory of the Express server by using the path.join function and the __dirname variable. We then ensure that the directory exists, by using a Boolean or comparison. If fx.existsSync returns true, we will not execute the fs.mkdirSync function. If it returns false, because the directory does not exist, then the fs.mkdirSync function will execute, and create the directory.

We then create a rotating file stream named accessLogStream by calling the rfs function with a few parameters. The first is the name of the log file, and the second parameter is a set of configuration parameters for this file stream. We have set the rotation interval to 10 seconds, just for testing, and set the path for log files to our newly created log directory. We are then specifying that the maximum number of files we want in this directory is 7. These parameters can easily be tuned for production use, and it also makes sense to retrieve these values from a configuration setting.

Once we have a rotating file stream, we can create a function for our server to use for logging messages, as follows:

function serverLog(message: string) { 
    let now = moment.tz(timezone); 
    let nowISOFormat = now.toISOString(); 
    let nowLocalFormat = now.format('YYYY-MM-DD HH:mm:ss.SSS'); 
    let logMessage = `UTC : ${nowISOFormat} :  
        local : ${nowLocalFormat} : ${message}`; 
    accessLogStream.write(`${logMessage}
`); 
    console.log(logMessage); 
} 

Here, we have defined a simple function named serverLog that accepts a parameter named message, which is of type string. The first thing we do in this function is to create an instance of a moment date time in the currently configured time zone, by calling the moment.tz function and passing in our time zone string, which is currently set to 'Australia/Perth'. We then create a variable named nowISOFormat by calling the toISOString function of the moment date time object. Remember that moment time zone stores all dates in UTC format, and so this string will represent the UTC date time in ISO format. We then create another variable named nowLocalFormat by calling the format function on the now variable, and pass in the date format. This call will take into account our currently configured time zone, as the underlying moment object has been created with a time zone setting.

Once we have our time strings, we log a message to the console, showing both the UTC date time, and the local date time. Note that we are writing a message to our rotating file stream by using the accessLogStream variable that we created earlier. We are also logging a message to the standard console.

To test that the rotating file stream is working correctly, let's log a message using our serverLog function every 500 milliseconds, as follows:

setInterval(() => { 
    serverLog(`timeout reached`); 
}, 500); 

With our test function in place, we can run our Express server as usual:

node dist/main  

The console output will now log messages every 500 milliseconds, and we will write to our rotating file stream at the same time. The output is now as follows:

Here, we can see that our serverLog function is logging UTC time, as well as the local time and the message to the console.

We have seen then, that we can configure our Express server quite easily using the config package, and can log messages to a rotating file stream on our server. We have also seen how the moment-timezone package helps us by providing simple utility functions to handle date and time objects in multiple time zones.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.253.221