Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs Winston using async function inside 'createLogger'

I am trying to put IP address of my server at the beginning of my logs. I am using the public-ip library. Problem is, that I am not allowed to use await getIp() inside winston options.

My logger.js looks like this

const winston = require( 'winston' );
const publicIp = require( 'public-ip' );

let ip;

async function getIp() {
  if ( !ip ) {
    ip = await publicIp.v4();
  }
  return ip;
}

const logger = winston.createLogger( {
  level: process.env.NODE_ENV !== global.PRODUCTION ? 'debug' : 'info',
  defaultMeta: { service: 'user-service' },
  format: winston.format.combine(
    winston.format.timestamp( {
      format: 'YYYY-MM-DD HH:mm:ss'
    } ),
    winston.format.printf( ( info ) => `[${await getIp()}] ${info.message}` )
  ),
  transports: [
    new winston.transports.File( { filename: 'logs/error.log', level: 'error', maxsize: '20MB' } ),
    new winston.transports.File( { filename: 'logs/combined.log', maxsize: '20MB' } ),
    new winston.transports.Console( {
      format: winston.format.combine(
        winston.format.colorize()
      )
    } )
  ]
} );

module.exports = logger;
like image 238
Tomas Lukac Avatar asked Mar 26 '26 23:03

Tomas Lukac


1 Answers

Your log configuration is synchronous so you need to provide your log configuration after you have done something i.e. fetched your public-ip.

// log.config.js
const winston = require('winston');
const publicIp = require('public-ip');

module.exports = {
    // Logger initialized async-hronously
    logger: async () => {
        let ip = await publicIp.v4();

        return winston.createLogger({
            level: process.env.NODE_ENV !== global.PRODUCTION ? 'debug' : 'info',
            defaultMeta: {service: 'user-service'},
            format: winston.format.combine(
                winston.format.timestamp({
                    format: 'YYYY-MM-DD HH:mm:ss'
                }),
                winston.format.printf((info) => `[${ip}] ${info.message}`)
            ),
            transports: [
                new winston.transports.File({filename: 'logs/error.log', level: 'error', maxsize: '20MB'}),
                new winston.transports.File({filename: 'logs/combined.log', maxsize: '20MB'}),
                new winston.transports.Console({
                    format: winston.format.combine(
                        winston.format.colorize()
                    )
                })
            ]
        })
    }
};

Since you logger has ip address fetched asynchronously in the format message your application needs to get the instance after it has initialized properly, like so.

// main.js
const myLogger = require('./log.config');

async function start() {
    let logger = await myLogger.logger();

    logger.debug('Hello from my log');

    // Application can proceed with rest of the logic ...
}

// Run my app
start();

Hope this helps.

like image 63
visitsb Avatar answered Mar 28 '26 12:03

visitsb