rdeg
rdeg

Reputation: 169

Creating and writing to a log file using morgan in express

So I am trying to create a log file if it doesn't exist, and if it does exist then I want morgan to write the logs to it. Here is the code

  // Function to write a file in a non-existing directory
  function writeFile(path, contents, cb){
    mkdirp(getDirName(path), function(err){
      if (err) return cb(err);
      fs.writeFile(path, contents, cb);
    });
  }

  // Check if log file exists, if it does not, then create it
  fs.exists(__dirname + '/log/access.log', function(exists){
    if(exists){
      app.use(logger('common', {
        stream: fs.createWriteStream(__dirname + '/log/access.log', {flags: 'a'})
      }));
      console.log('access.log exists!');
    } else {
      writeFile(__dirname + '/log/access.log', {flag: 'wx'}, function(err){
        if (err) throw err;
        console.log('access.log created!');
      });
    }
  });

The first function creates the log directory and access.log file. The problem is when I hit a route it doesn't log anything to access.log. It was working before when the app.use call was not in fs.exists so I don't know if thats the problem or not, but when It's not in fs.exists it will error out due to the file not having been created yet.

Upvotes: 0

Views: 2930

Answers (1)

ChevCast
ChevCast

Reputation: 59234

Looks like you need to use fs.existsSync. The reason being that the app.use call is executing further down the event loop due to the asynchronous call to fs.exists. My guess is that by the time the fs.exists callback is invoked, your express app is already configured and has begun listening. Try this:

var fs = require('fs');
var path = require('path');
var logPath = path.join(__dirname, 'log', 'access.log');

if (fs.existsSync(logPath)) {
  app.use(logger('common', {
    stream: fs.createWriteStream(logPath, {flags:'a'});
  }));
  console.log('access.log exists!');
} else {
  fs.mkdirSync(path.dirname(logPath));
  fs.writeFileSync(logPath, {flags:'wx'});
  console.log('access.log created!');
}

Since this appears to be code that runs during application startup, making it synchronous shouldn't be very costly. I'm sure you could make the asynchronous setup work by restructuring how your express app and all it's middleware is constructed, but it won't save you much since these operations clearly need to happen in order before app.listen anyway.

Upvotes: 1

Related Questions