node.jsloggingmorgan

NodeJS12 Morgan logger skip not working with rotating file stream


I am using NodeJS with morgan for logging and rotating-file-stream to create the log files. I want to set up the app to create a rotating log file in apache combined format. The code is working, the log is created in the desired directory. However, the skip function is not working. Requests sent to /api/healthcheck are still appearing in the log. I have confirmed that the 'skip' url is correct and matches originalUrl when a request to that url is sent, and I have confirmed that the function does in fact return true when the healthcheck route is called.

const logger = require('morgan');

/* Logger */
// Logger skip url
const loggerSkipUrl = '/api/healthcheck';

// Create a rotating write stream
let accessLogStream = rfs.createStream('server.log', {
  interval: '1d', // Rotate daily
  maxFiles: 30, // Maximum number of rotated files to keep in storage
  compress: 'gzip', // Compress rotated files
  path: path.join(__dirname, 'logs'),
})

// Log requests in the Apache combined format to one log file per day
app.use(logger('combined',
  { stream: accessLogStream }, // Works but doesn't skip
  { skip: (req, res) => req.originalUrl === loggerSkipUrl }, // Does not skip
  { flags: 'a' },
));

UPDATE: I am still having this issue. It appears to be related to using the stream option. For example, logging without the stream option, it skips the healthcheck route correctly, but when using the stream option, it does not skip. Is this a configuration issue or a bug in the Morgan logger module?

function skipLog(req, res) {
  const answer = req.originalUrl.indexOf('healthcheck') > -1;
  console.log(`skipLog ${answer}`);
  return answer;
}

/* SKIP WORKS WITHOUT STREAM OPTION */

// Log API requests to console
app.use(requestLogger('dev', { skip: skipLog }));


/* SKIP DOES NOT WORK WITH STREAM OPTION */

requestLogStream = rfs.createStream('request.log', {
  interval: '1d', // Rotate daily
  maxFiles: 30, // Maximum number of rotated files to keep in storage
  path: path.join(__dirname, `logs/${hostname}`)
});

// Log API requests in the Apache combined format to one log file per day
app.use(requestLogger('combined',
  { stream: requestLogStream },
  { flags: 'a' },
  { skip: skipLog },
));

Solution

  • Looking the code of morgan you will see that skip and stream together is supported.

    The issue is how the option is provided to the factory function:

    app.use(requestLogger('combined',
      {
        stream: requestLogStream,
        flags: 'a',
        skip: skipLog
      })
    )
    

    It must be a single object