4

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?

3
  • I used your code verbatim, and it writes to the file perfectly fine. Make sure it isn't opened elsewhere or the like. Commented Jul 29, 2019 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. Commented Jul 29, 2019 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. Commented Jul 29, 2019 at 15:00

2 Answers 2

6

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!

Sign up to request clarification or add additional context in comments.

1 Comment

works like a charm, i still get confused with async programming
-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

2 Comments

Thanks for the suggestion, I didn't know this library, I'll have a look to see its features.
@Fel sure thing, let me know if it works the way you want it :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.