How To Securely Manage Secrets with HashiCorp Vault on Ubuntu 16.04
1

Introduction

An effective logging option would be vital to the prosperity of any application. An extremely versatile logging library and the most popular logging solution available for Node.js in this guide we’ll focus on a logging package called Winston applications, based on NPM download statistics. Winston’s features include support for multiple storage options and log levels, log queries, and even a profiler that is built-in. This guide shall show you how to use Winston to log a Node/Express application that we’ll create as part of this process. We’ll also look at how we can combine Winston with another HTTP that is popular request logger for Node.js called Morgan to combine HTTP request information logs along with other information.

After doing this tutorial you’ll have an server that is ubuntu a small Node/Express application. You shall likewise have Winston implemented to log mistakes and communications to a file additionally the system.

Prerequisites

Before you start this show youwill need the ( that is following**********)

With these prerequisites in position, we are able to build our application and install Winston.

Step 1 — Creating a simple Node/Express App

A typical usage for Winston is signing occasions from internet applications constructed with Node.js. So that you can completely show just how to include Winston we are going to produce a Node that is simple.js application using the Express framework. A command-line tool for getting a Node/Express web application running quickly to help us get a basic web application running we will use express-generator. We will be able to use the npm command to install express-generator because we installed the Node Package Manager as part of our prerequisites,. We will also use the -g flag, which installs the package globally so it can used as a command line tool outside of an node project/module that is existing. Install the package with all the command that is following**********)

  • sudo npm install express-generator -g

With express-generator set up, we are able to produce our application utilising the express demand, followed closely by the title associated with directory we should utilize for the task. This can produce our application with every thing we must ( get started**********)

Next, install Nodemon, that'll immediately reload the applying if we make any modifications. A Node.js application has to be restarted any right time changes are made to the source code in order for those changes to take effect. Nodemon shall immediately watch out for modifications and restart the applying for all of us. And with the -g flag:( since we want to be able to use nodemon as a command-line tool we will install it**********)

  • sudo npm install nodemon -g

To finish establishing the applying, modification toward application directory and dependencies that are install follows:

By standard, applications made up of express-generator run using slot 3000, so we must ensure that slot just isn't obstructed by the firewall. To port that is open*******************************************************************************************), operate the next demand:

We are in possession of every thing we must begin our internet application. To do this, operate the command that is following

This begins the applying operating on slot 3000. We could test that it is working by visiting http://your_server_ip:3000 in a web web browser. You ought to see something such as this:

Default express-generator homepage

It's advisable at this time to start out an additional SSH session towards host to utilize the rest of the guide, making the internet application we simply began operating inside session that is original. For the rest of this article, we'll refer to the SSH session we've been using so far and that is currently running the application as Session A. We will use the SSH that is new session operating commands and modifying files, so we'll relate to this session as Session B. Unless otherwise noted, all staying commands is run in Session B.

Step 2 - Customizing the Node.js Application

The standard application developed by express-generator does a fantastic job at getting united states started, also it also includes the Morgan HTTP signing middleware we are going to be utilizing to log information about all HTTP demands. And since Morgan supports production channels, it creates a pairing that is nice the flow help included in Winston, allowing united states to combine HTTP demand information logs with whatever else we elect to log with Winston.

By standard, the express-generator boilerplate makes use of the adjustable logger whenever referencing the morgan package. It can be confusing to call either one of them logger since we will be using morgan and winston, which are both logging packages,. Therefore let us modification that by modifying the app.js file inside base of the task and making some modifications.

To available app.js for modifying, make use of the nano demand:

Find the line that is following the top the file:

~/myApp/app.js

...
var logger = require('morgan');
...

Change it toward ( that is following**********)

~/myApp/app.js

...
var morgan = require('morgan');
...

We should also find in which the adjustable logger ended up being referenced inside file and alter it to morgan. At it, let's change the log format used by the morgan package to combined, which is the standard Apache log format and will include useful information in the logs such as remote IP address and the user-agent HTTP request header while we are.

To do this, discover the line that is following**********)

~/myApp/app.js

...
app.use(logger('dev'));
...

Change it toward ( that is following**********)

~/myApp/app.js

...
app.use(morgan('combined'));
...

These modifications can help united states better comprehend which package that is logging are referencing at any time soon after we integrate our Winston setup.

Exit and conserve the file by typing CTRL-X, then Y, then ENTER.

Now which our application is initiated we're willing to begin working with Winston.

Step 3 — Installing and Configuring Winston

We are now actually willing to install and configure Winston. Inside action we shall explore a number of the setup choices that are offered included in the winston package and produce a logger which will log information to a file additionally the system.

To install winston run the command that is following**********)

  • cd ~/myApp
  • npm install winston

It's frequently helpful to keep just about any help or energy setup files for the applications in a directory that is special therefore let us produce a config folder which will retain the winston setup:

Now let us produce the file which will include our winston setup, which we are going to phone winston.js:

  • touch ~/myApp/config/winston.js

Next, create a folder which will include your log files:

Finally, let us install app-root-path, a package that's helpful whenever specifying paths in Node.js. This package just isn't straight regarding Winston, but assists greatly whenever paths that are specifying files in Node.js code. We'll use it to specify the location of the Winston log files from the root of the project and avoid ugly path that is relative:

  • npm install app-root-path --save

Everything we must configure how exactly we desire to manage our logging is in position, so we are able to proceed to determining our setup settings. Start by starting ~/myApp/config/winston.js for modifying:

  • nano ~/myApp/config/winston.js

Next, need the app-root-path and winston packages:

~/myApp/config/winston.js

var appRoot = require('app-root-path');
var winston = require('winston');

With these factors in position, we are able to determine the setup settings for the transports. Transports are a notion introduced by Winston that relate to the storage/output mechanisms employed for the logs. Winston includes three core transports - console, file, and HTTP. We are targeting the file and console transports for this tutorial: the console transport will log information to the console, and the file transport will log information to a specified file. Each transport definition can contain its own configuration settings such as file size, log levels, and log format. Here is a summary that is quick of settings we are going to be utilizing for every transportation:

  • level - degree of communications to log.
  • filename - The file to be utilized to create log information to.
  • handleExceptions - Catch and log unhandled exceptions.
  • json - reports log information in JSON structure.
  • maxsize - Max size of log file, in bytes, before a file that is new be produced.
  • maxFiles - restrict the amount of files produced if the size associated with logfile is surpassed.
  • colorize - Colorize the production. This is often helpful whenever considering system logs.

Logging amounts suggest message concern and are also denoted by an integer. Winston makes use of npm signing amounts being prioritized from 0 to 5 (greatest to lowest):

  • 0: mistake
  • 1: warn
  • 2: info
  • 3: verbose
  • 4: debug
  • 5: ridiculous

whenever indicating a logging degree for a transport that is particular anything at that level or higher will be logged. For example, by specifying a degree of info, any such thing at degree error, warn, or info will likely to be logged. Log amounts are specified whenever calling the logger, meaning we are able to perform some after to record one: logger.error('test error message').

We can determine the setup settings the file and console transports inside winston setup the following:

~/myApp/config/winston.js

...
var choices = {
  file: {
    degree: 'info',
    filename: `${appRoot}/logs/app.log`,
    handleExceptions: real,
    json: real,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
    colorize: false,
  },
  system: {
    degree: 'debug',
    handleExceptions: real,
    json: false,
    colorize: real,
  },
};

Next, instantiate a brand new winston logger with file and system transports utilising the properties defined inside options adjustable:

~/myApp/config/winston.js

...
var logger = winston.Logger( that is new{
  transports: [
    new winston.transports.File(options.file),
    new winston.transports.Console(options.console)
  ],
  exitOnError: false, // cannot leave on managed exceptions
});

By standard, morgan outputs toward system just, therefore let us determine a flow function that'll be capable get morgan-generated production in to the winston log files. We shall make use of the info degree and so the production will likely to be found by both transports ( console and file):

~/myApp/config/winston.js

...
logger.stream = {
  compose: function(message, encoding) {
    logger.info(message);
  },
};

Finally, export the logger therefore it may be used in other areas associated with application:

~/myApp/config/winston.js

...
module.exports = logger;

The finished winston setup file should seem like this:

~/myApp/config/winston.js

var appRoot = require('app-root-path');
var winston = require('winston');

// determine the customized settings for every transportation (file, system)
var choices = {
  file: {
    degree: 'info',
    filename: `${appRoot}/logs/app.log`,
    handleExceptions: real,
    json: real,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
    colorize: false,
  },
  system: {
    degree: 'debug',
    handleExceptions: real,
    json: false,
    colorize: real,
  },
};

// instantiate a Winston that is new logger the settings defined above
var logger = winston.Logger( that is new{
  transports: [
    new winston.transports.File(options.file),
    new winston.transports.Console(options.console)
  ],
  exitOnError: false, // cannot leave on managed exceptions
});

// create a flow item with a 'write' function that'll be employed by `morgan`
logger.stream = {
  compose: function(message, encoding) {
    // make use of the 'info' log degree and so the production will likely to be found by both transports (file and system)
    logger.info(message);
  },
};

module.exports = logger;

Exit and conserve the file.

We are in possession of our logger configured, but our application continues to be uninformed from it or utilizing it. We shall now incorporate the logger with all the application.

Step 4 — Integrating Winston With This Application

To get our logger working together with the applying we must make express conscious of it. We currently saw in 2 which our express setup is found in app.js, therefore let us import our logger into this file. Start the declare modifying by operating:

Import winston close to the the surface of the file with all the other statements that are require**********)

~/myApp/app.js

...
var winston = require('./config/winston');
...

The beginning we are going to in fact utilize winston is by using morgan. We shall use the stream option, and set it to the stream interface we created as part of the winston configuration. To do so, find the line that is following**********)

~/myApp/app.js

...
app.use(morgan('combined'));
...

Change it for this:

~/myApp/app.js

...
app.use(morgan('combined', { stream: winston.stream }));
...

Exit and conserve the file.

We're willing to see some log information! In the event that you reload the web page inside internet browser, your should see something such as the next inside system of SSH Session A:

Output

[nodemon] restarting considering modifications... [nodemon] beginning `node bin/www` information: ::ffff:72.80.124.207 - - [07/Mar/2018:17:29:36 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" information: ::ffff:72.80.124.207 - - [07/Mar/2018:17:29:37 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"

There are a couple of log entries right here - initial the demand toward HTML web page, the 2nd the accompanied stylesheet. Since each transportation is configured to carry out info degree log information, we have to additionally see information that is similar the file transport located at ~/myApp/logs/app.log. The output in the file transport, however, should be written as a JSON object since we specified json: true in the file transport configuration. You can learn more about JSON in our introduction to JSON tutorial. To view the contents of the log file, run the command that is following**********)

  • tail ~/myApp/logs/app.log

You should see something such as the ( that is following**********)

{"level":"info","message":"::ffff:72.80.124.207 - - [07/Mar/2018:17:29:36 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"n","timestamp":"2018-03-07T17:29:36.962Z"}
{"level":"info","message":"::ffff:72.80.124.207 - - [07/Mar/2018:17:29:37 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"n","timestamp":"2018-03-07T17:29:37.067Z"}

So far our logger is just recording HTTP demands and associated information. This really is really information that is important have in our logs, but how do we record custom log messages? There will certainly be times that we want this ability for things such as recording errors or database that is profiling performance, as an example. To illustrate how exactly we can perform this, let us phone the logger from mistake handler path.

The express-generator package includes a 404 and 500 mistake handler path automatically, therefore we are going to utilize that. Start the ~/myApp/app.js file:

Find the rule block at the end associated with file that appears like this:

~/myApp/app.js

...
// mistake handler
app.use(function(err, req, res, next) {
  // set locals, just error that is providing development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the mistake web page
  res.status(err.status || 500);
  res.render('error');
});
...

This could be the error that is final route that will ultimately send an error response back to the client. This is a good place to include the winston logger since all server-side errors will be run through this route.

Because we're now coping with mistakes, we should make use of the error log degree. Once again, both transports are configured to log error degree communications so we have to understand production inside system and file logs. We could add any such thing we wish inside log therefore make sure you add some information that is useful:

  • err.status - The HTTP mistake status rule. If one just isn't currently current, standard to 500.
  • err.message - information on the mistake.
  • req.originalUrl - The Address which was required.
  • req.path - the road area of the demand URL.
  • req.method - HTTP way of the demand (GET, POST, place, etc.).
  • req.ip - Remote ip associated with demand.

Update the mistake handler approach to match the ( that is following**********)

~/myApp/app.js

...
// mistake handler
app.use(function(err, req, res, next) {
  // set locals, just error that is providing development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // include this line to incorporate winston signing
  winston.error(`$ - ${err.message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);

  // render the mistake web page
  res.status(err.status || 500);
  res.render('error');
});
...

Exit and conserve the file.

To try out this, let us you will need to access a web page within our task that does not occur, that'll put a 404 mistake. Back your on line web browser, make an effort to load the URL that is following http://your_server_ip:3000/foo. The application is already set up to respond to such an error, thanks to the boilerplate created by express-generator. Your browser should display an error message that looks like this (your error message might become more detail by detail than what exactly is shown):

Browser error message

Now simply take another consider the system in SSH Session A. there must be a log entry the mistake, and because of the colorize establishing it must be no problem finding.

Output

[nodemon] beginning `node bin/www` error: 404 - maybe not discovered - /foo - GET - ::ffff:72.80.124.207 information: ::ffff:72.80.124.207 - - [07/Mar/2018:17:40:11 +0000] "GET /foo HTTP/1.1" 404 985 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" information: ::ffff:72.80.124.207 - - [07/Mar/2018:17:40:11 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/foo" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"

As the file logger, operating the tail demand once again should show united states the log that is new:

  • tail ~/myApp/logs/app.log

You might find an email like following:

{"level":"error","message":"404 - Not Found - /foo - GET - ::ffff:72.80.124.207","timestamp":"2018-03-07T17:40:10.622Z"}

The mistake message includes most of the information we particularly instructed winston to log included in the mistake handler, like the mistake status (404 - maybe not discovered), the URL that is requestedlocalhost/foo), the demand technique (GET), the ip making the demand, additionally the timestamp of if the demand ended up being made.

Conclusion

In this guide, you built a straightforward Node.js internet application and incorporated a Winston logging solution which will work as an tool that is effective provide insight into the performance of the application. You can do a lot more to build logging that is robust for the applications, specially as your preferences be complex. We suggest that you are taking the right time for you view some of those other papers:

An iPhone assembly worker works with Apple supplier Pegatron in an image distributed by Apple.

in an audit of supply chain partners, Apple found increased labor violations in 2017
Previous article

Just how to Install and Configure Nibbleblog on Ubuntu 16.04

Next article