I want to display the file Name in the log statement

后端 未结 4 790
死守一世寂寞
死守一世寂寞 2020-12-29 06:06

For every logger statement with any level, I need to display the file name from where the log statement executed, below is the illustration I given below:

Example :

相关标签:
4条回答
  • 2020-12-29 06:17

    Use this code and it will give you the log with the filename and line number. Paste this code in a new file winston.js and this requires this file to use it.

    var winston = require('winston')
    var path = require('path')
    var PROJECT_ROOT = path.join(__dirname, '..')
    var appRoot = require('app-root-path');
    
    
    const options = {
      file: {
        level: 'info',
        filename: `${appRoot}/logs/app.log`,
        handleExceptions: true,
        json: true,
        maxsize: 5242880, // 5MB
        maxFiles: 5,
        colorize: false,
        timestamp: true
      },
      console: {
        level: 'debug',
        handleExceptions: true,
        json: true,
        colorize: true,
        timestamp: true
      }
    };
    
    var logger = new winston.Logger({
      transports: [
        new winston.transports.File(options.file),
        new winston.transports.Console(options.console)
      ],
      exitOnError: false // do not exit on handled exceptions
    });
    
    logger.stream = {
      write: function (message) {
        logger.info(message)
      }
    }
    
    // A custom logger interface that wraps winston, making it easy to instrument
    // code and still possible to replace winston in the future.
    
    module.exports.debug = module.exports.log = function () {
      logger.debug.apply(logger, formatLogArguments(arguments))
    }
    
    module.exports.info = function () {
      logger.info.apply(logger, formatLogArguments(arguments))
    }
    
    module.exports.warn = function () {
      logger.warn.apply(logger, formatLogArguments(arguments))
    }
    
    module.exports.error = function () {
      logger.error.apply(logger, formatLogArguments(arguments))
    }
    
    module.exports.stream = logger.stream
    
    /**
     * Attempts to add file and line number info to the given log arguments.
     */
    function formatLogArguments (args) {
      args = Array.prototype.slice.call(args)
    
      var stackInfo = getStackInfo(1)
    
      if (stackInfo) {
        // get file path relative to project root
        var calleeStr = '(' + stackInfo.relativePath + ':' + stackInfo.line + ')'
    
        if (typeof (args[0]) === 'string') {
          args[0] = calleeStr + ' ' + args[0]
        } else {
          args.unshift(calleeStr)
        }
      }
    
      return args
    }
    
    /**
     * Parses and returns info about the call stack at the given index.
     */
    function getStackInfo (stackIndex) {
      // get call stack, and analyze it
      // get all file, method, and line numbers
      var stacklist = (new Error()).stack.split('\n').slice(3)
    
      // stack trace format:
      // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
      // do not remove the regex expresses to outside of this method (due to a BUG in node.js)
      var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
      var stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi
    
      var s = stacklist[stackIndex] || stacklist[0]
      var sp = stackReg.exec(s) || stackReg2.exec(s)
    
      if (sp && sp.length === 5) {
        return {
          method: sp[1],
          relativePath: path.relative(PROJECT_ROOT, sp[2]),
          line: sp[3],
          pos: sp[4],
          file: path.basename(sp[2]),
          stack: stacklist.join('\n')
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-29 06:28

    You can use the stack trace information attached to v8's Error object to find out what file/line your code was called from. This approach works well, but it does not perform well; so if you use it during development, you will want to disable it when you go to production.

    So you could do something like this:

      var logger_info_old = logger.info;
      logger.info = function(msg) {
        var fileAndLine = traceCaller(1);
        return logger_info_old.call(this, fileAndLine + ":" + msg);
      }
    
      /**
      * examines the call stack and returns a string indicating 
      * the file and line number of the n'th previous ancestor call.
      * this works in chrome, and should work in nodejs as well.  
      *
      * @param n : int (default: n=1) - the number of calls to trace up the
      *   stack from the current call.  `n=0` gives you your current file/line.
      *  `n=1` gives the file/line that called you.
      */
      function traceCaller(n) {
        if( isNaN(n) || n<0) n=1;
        n+=1;
        var s = (new Error()).stack
          , a=s.indexOf('\n',5);
        while(n--) {
          a=s.indexOf('\n',a+1);
          if( a<0 ) { a=s.lastIndexOf('\n',s.length); break;}
        }
        b=s.indexOf('\n',a+1); if( b<0 ) b=s.length;
        a=Math.max(s.lastIndexOf(' ',b), s.lastIndexOf('/',b));
        b=s.lastIndexOf(':',b);
        s=s.substring(a+1,b);
        return s;
      }
    
    0 讨论(0)
  • 2020-12-29 06:28

    Looks like you're using Winston here - I typically pass module into my logger module and then set Winston's label property to a parsed version of module.filename. Something like:

    logger.js:

    const path = require('path');
    
    // Return the last folder name in the path and the calling
    // module's filename.
    const getLabel = function(callingModule) {
      const parts = callingModule.filename.split(path.sep);
      return path.join(parts[parts.length - 2], parts.pop());
    };
    
    module.exports = function (callingModule) {
      return new winston.Logger({
        transports: [new winston.transports.Console({
          label: getLabel(callingModule)
        })]
      });
    };
    

    Usage (assume module is controllers/users.js):

    const logger = require('./logger')(module);
    logger.info('foo');
    

    Result:

    2014-11-25T15:31:12.186Z - info: [controllers/users.js] foo
    
    0 讨论(0)
  • 2020-12-29 06:31

    Assuming each file is a separate node process, you could use something like process.argv[1].match(/[\w-]+\.js/gi)[0]

    If you are looking for something that will work in modules this might work:

    process.mainModule.filename.match(/[\w-]+\.js/gi)[0]
    
    0 讨论(0)
提交回复
热议问题