Derptacos
Derptacos

Reputation: 177

Expressjs Morgan dynamically format the logs

Attempting to change the format of morgan's logging through the application run time.

The value will change pending on some remote value in a database and I would like morgan's output to change as a result. ie. If in the database the value is 1 morgan's formatting is 'dev', if the value is 3 the formatting is 'combined'

I have the been using the following line to set up morgan with formatting:

app.use(morgan(get_verbose()))
   .use ....

where get_verbose will correspond to the format options. However it is not giving the dynamic results I was wishing for - it's only setting the formatting once.

Am I going about this incorrectly or is morgan limited to only 1 format at run time?

Upvotes: 3

Views: 2297

Answers (2)

artis3n
artis3n

Reputation: 840

Another way to accomplish this with Morgan's built-in features is the skip parameter. From the documentation:

// EXAMPLE: only log error responses
morgan('combined', {
  skip: function (req, res) { return res.statusCode < 400 }
})

The skip option specifies a function with parameters req and res that returns True/False to determine if the logging option should be skipped. The function can contain any necessary code as long as it returns True or False.

Depending on what parameter you want to differentiate logging on, this may be a simpler way then a multi-line if/else block. An example server logging HTTPS traffic separately from HTTP traffic:

const express = require('express');
const http = require('http');
const https = require('https');
const logger = require('morgan');

const httpsOptions = // {} hash of options.

app.use(logger('combined', {
  stream: httpLogStream,
  skip: function(req, res) { return req.secure }
});
app.use(logger('combined', {
  stream: httpsLogStream,
  skip: function(req, res) { return !req.secure }
});

http.createServer(app).listen(80);
https.createServer(httpsOptions, app).listen(443);

A good walk through for setting up HTTPS as I did in this example can be found here.

To read about Express's req.secure method: here.

The log streams are set up as in Morgan's documentation.

Upvotes: 2

smitelli
smitelli

Reputation: 7575

One approach would be to create a middleware function that "wraps" the Morgan middleware:

var morganDev = mordan('dev');
var morganCombined = morgan('combined');

app.use(function(req, res, next) {
    var value = /* get value somehow */

    if (value === 1) {
        morganDev(req, res, next);
    } else if (value === 3) {
        morganCombined(req, res, next);
    }
});

Up front, you create one logger for each log format you would like, but don't attach either of them to the app. In their place, a custom function reads the value and chooses which logger should handle the processing for this request.

Safety update: There should be a catch-all else block to handle the case where value is neither 1 or 3. This block should call next() directly, otherwise the request handling will stall and never return a response to the client.

Upvotes: 3

Related Questions