3

I need a basic logging system for a NodeJS application, so I'm doing some tests with log4js, which seems to be the standard for these cases. I need to print the messages both to the console and a file, so I wrote this code:

// Logger
var log4js = require('log4js');

log4js.configure({
  appenders: {
    'console': { type: 'console' },
    'file': { type: 'file', filename: 'logs/mailer.log' }
  },
  categories: {
    default: { appenders: ['file', 'console'], level: 'DEBUG' },
  }
});

var logger = log4js.getLogger("Mailer");

logger.info("Starting application");

try {
  // CODE TO READ APP CONFIG FILE
}
catch(e) {
  logger.error("Couldn't read app configuration file (config.yml)");

  // This is the trouble maker. It kills the app without flushing the logs
  process.exit(1);
}

When I run the application, the logs appear like this:

[2019-07-29T16:07:24.763] [INFO] Mailer - Starting application

The problem is that I can see the messages in the console, but the log file remains empty. If I delete it and run the application again, it's created, so I suppose that the problem is a missing option or something like that.

Any suggestion?

Fel
  • 4,428
  • 9
  • 43
  • 94
  • I used your code verbatim, and it writes to the file perfectly fine. Make sure it isn't opened elsewhere or the like. –  Jul 29 '19 at 14:26
  • I found the reason of the problem: after I print the error message, I quit the application by running `process.exit(1);`, and it seems that the logger doesn't flush the messages to the file. I'm doing a little research and I'll post the solution when I find it. – Fel Jul 29 '19 at 14:57
  • Yeah, I guess the logger writes asynchronously, so when you kill the process right after logging something, it probably doesn't get saved. You should add this to the code in your question though so we can reproduce this. –  Jul 29 '19 at 15:00

2 Answers2

5

To avoid changing the application logic and all the process.exit() calls, I've replaced the file appender by its synchronous version fileSync and now everything works as expected. So, the only thing I changed is the line where I declare the 'file' appender:

    'file': { type: 'fileSync', filename: 'logs/mailer.log' }

Cheers!

Fel
  • 4,428
  • 9
  • 43
  • 94
-1

You could use loggerWinston...I used it in my nodejs application and it works fine.
You should add it in your server.js (the file you use to start node)

const winston = require('winston');

const tsFormat = () => (new Date()).toLocaleTimeString();
global.loggerWinston = new (winston.Logger)({
  transports: [
    // colorize the output to the console
    new (winston.transports.Console)({
      timestamp: tsFormat,
      colorize: true,
      level: 'debug'
    }),
    new (winston.transports.File)({
      filename: 'results.log',
      timestamp: tsFormat,
//      level: (process.env.NODE_ENV || 'development') === 'development' ? 'debug' : 'info'
      level: 'info'
    })
  ]
});

The results.log file should be added in your project folder.

This is the reference https://www.npmjs.com/package/winston

alesssz
  • 384
  • 4
  • 18