Winston: I want to display the file Name in the log statement

Created on 5 Nov 2012  Â·  12Comments  Â·  Source: winstonjs/winston

For every logger.info or logger.debug, I need to display the filename in which the following line executed.

Example :

JobWorks.js

logger.info("Hello Logger");

Actual :
2012-11-05T06:07:19.158Z - warn: getInCompleteJobs in job works

Required :
2012-11-05T06:07:19.158Z - warn JobWorks : getInCompleteJobs in job works

Most helpful comment

We use a module which wraps around a logger instance. It changes the signature for requiring it.
As a quick example for info:

var logger = require('logger')(module);

logger.info('My log statement');

Inside your logger module:

var winston = require('winston');

module.exports = function (module) {

  var filename = module.id;
  return {
    info : function (msg, vars) { 
      winston.info(filename + ': ' + msg, vars); 
    }
  }
};

We made it a little more generic to handle other levels of logging, but the basic idea is still the same.

Agree though that it probably doesn't belong in winston source.

All 12 comments

guys please help me, I found a helpful link http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi

subscribe to this, plus my personal suggestion, also display the row from where the log has been executed and from what function name

In my previous reply I said about V8 Javascript Stack Trace API, it is right, now I can get the file name also.

I have writte a function in my js file which will return the file name :

function getFileName(){
var fileName="";
var rowNumber;
var columnNumber;
var currentStackPosition=1; // this is the value representing the position of your caller in the error stack.
try{
throw new Error("Custom Error");
}catch(e){
Error["prepareStackTrace"]=function(){
return arguments[1];
};
Error.prepareStackTrace(e, function(){});
fileName=e.stack[currentStackPosition].getFileName();
rowNumber=e.stack[currentStackPosition].getLineNumber();
columnNumber=e.stack[currentStackPosition].getColumnNumber();
}
return {"file":fileName,"row":rowNumber,"column":columnNumber};
}

I feel this is ok, If any better suggestions are available please provide me.

This is a really big performance hit. It involves creating an error object and reading the stack trace every time anything is logged. It doesn't belong to winston core. Feel free to create your own logger tho.

thanks for the comment, so how else we can get the file name in the logger

We use a module which wraps around a logger instance. It changes the signature for requiring it.
As a quick example for info:

var logger = require('logger')(module);

logger.info('My log statement');

Inside your logger module:

var winston = require('winston');

module.exports = function (module) {

  var filename = module.id;
  return {
    info : function (msg, vars) { 
      winston.info(filename + ': ' + msg, vars); 
    }
  }
};

We made it a little more generic to handle other levels of logging, but the basic idea is still the same.

Agree though that it probably doesn't belong in winston source.

way, my opinion is that is a good feature, to be ported in winston as a switch element for logging.
at least this feature, if the posibilty to display the row and the method from where the logging is called.

Personally, I've find this solution:
new Error().stack

I can get the original file where logger is call.

Like this:

main.js

exports.logger = new (winston.Logger)({
    levels: levelsOptions,
    transports: [
        new (winston.transports.Console)({
            timestamp: () => dateformat(Date.now(), "dd/mm/yyyy HH:MM:ss"),
            formatter: (options) => {
                const detailsFromFile = getDetailsFromFile(new Error().stack);

                // S'il y a un objet, on le formatte
                const meta = (options.meta && Object.keys(options.meta).length)
                    ? JSON.stringify(options.meta, null, 2)
                    : "";

                return options.level,
                    `${options.timestamp()}\t +
                    `${options.message}` +
                    `${meta}` +
                    `${detailsFromFile.formattedInfos}`
            }
        })
    ]
});

getDetailsFromFile.js

exports.getDetailsFromFile = (fileDetails) => {
    const fileAndRow = fileDetails
        .split("at ").pop()
        .split("(").pop()
        .replace(')', '')
        .split(':');

    const detailsFromFile = {
        file: fileAndRow[0].trim(),
        line: fileAndRow[1],
        row: fileAndRow[2],
    };

    detailsFromFile.formattedInfos = chalk.white(
        Object.keys(detailsFromFile).reduce((previous, key) => 
                `${previous}` +
                `${chalk.underline(key)}: ` +
                `${chalk.italic(detailsFromFile[key])}`;
        , `\n`)
    );

    return detailsFromFile;
};

My final log have this format:

logger.info("Mon test !");

=>
ℹ  04/05/2018 10:43:56  Mon test !
file: /Users/[user]/Document/test/index.js                    line: 7                    row: 12

PS:
I simplified my original code for better comprehension. Some processes are not present in my example.

We use a module which wraps around a logger instance. It changes the signature for requiring it.
As a quick example for info:

var logger = require('logger')(module);

logger.info('My log statement');

Inside your logger module:

var winston = require('winston');

module.exports = function (module) {

  var filename = module.id;
  return {
    info : function (msg, vars) { 
      winston.info(filename + ': ' + msg, vars); 
    }
  }
};

We made it a little more generic to handle other levels of logging, but the basic idea is still the same.

Agree though that it probably doesn't belong in winston source.

This is actually an awesome solution. thanks for this.

But when I used it today, I realized that it breaks Singleton pattern of logger as with each filename, it will be different instance of logger.
Do you think it has any disadvantages, Can it lead to any race conditions when writing to files.

Do you think it has any disadvantages, Can it lead to any race conditions when writing to files.

No, only the wrapper object is created once per file, each wrapper uses the same instance of winston.

Why are folks not using __filename ? https://nodejs.org/api/globals.html#globals_filename

Was this page helpful?
0 / 5 - 0 ratings

Related issues

amiram picture amiram  Â·  4Comments

greenhat616 picture greenhat616  Â·  3Comments

ghost picture ghost  Â·  4Comments

KingRial picture KingRial  Â·  3Comments

Tonacatecuhtli picture Tonacatecuhtli  Â·  4Comments