How to get console.log line numbers shown in Nodejs?

后端 未结 5 602
小蘑菇
小蘑菇 2020-12-02 20:54

Got an old application, that prints out quite a lot of messages using console.log, but I just can not find in which files and lines console.log is

5条回答
  •  猫巷女王i
    2020-12-02 21:26

    All solutions to this question so far rely on splitting and matching the stack trace as a string, which will break in (the unlikely) case the format of that string is changed in the future. Inspired by this gist on GitHub and the other answers here, I want to provide my own solution:

    'use strict';
    
    const path = require('path');
    
    ['debug', 'log', 'warn', 'error'].forEach((methodName) => {
        const originalLoggingMethod = console[methodName];
        console[methodName] = (firstArgument, ...otherArguments) => {
            const originalPrepareStackTrace = Error.prepareStackTrace;
            Error.prepareStackTrace = (_, stack) => stack;
            const callee = new Error().stack[1];
            Error.prepareStackTrace = originalPrepareStackTrace;
            const relativeFileName = path.relative(process.cwd(), callee.getFileName());
            const prefix = `${relativeFileName}:${callee.getLineNumber()}:`;
            if (typeof firstArgument === 'string') {
                originalLoggingMethod(prefix + ' ' + firstArgument, ...otherArguments);
            } else {
                originalLoggingMethod(prefix, firstArgument, ...otherArguments);
            }
        };
    });
    
    // Tests:
    console.log('%s %d', 'hi', 42);
    console.log({ a: 'foo', b: 'bar'});
    

    Unlike the other solutions, this script

    • outputs no additional lines and
    • handles string substitutions correctly.

    You can color the prefix with chalk or color.js, but I didn't want to introduce dependencies for this here.

    The above script uses the V8 API to customize stack traces. The callee is a CallSite object with the following methods in case you want to customize the prefix:

    • getThis: returns the value of this
    • getTypeName: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object’s [[Class]] internal property.
    • getFunction: returns the current function
    • getFunctionName: returns the name of the current function, typically its name property. If a name property is not available an attempt is made to infer a name from the function’s context.
    • getMethodName: returns the name of the property of this or one of its prototypes that holds the current function
    • getFileName: if this function was defined in a script returns the name of the script
    • getLineNumber: if this function was defined in a script returns the current line number
    • getColumnNumber: if this function was defined in a script returns the current column number
    • getEvalOrigin: if this function was created using a call to eval returns a string representing the location where eval was called
    • isToplevel: is this a top-level invocation, that is, is this the global object?
    • isEval: does this call take place in code defined by a call to eval?
    • isNative: is this call in native V8 code?
    • isConstructor: is this a constructor call?
    • isAsync: is this an async call (i.e. await or Promise.all())?
    • isPromiseAll: is this an async call to Promise.all()?
    • getPromiseIndex: returns the index of the promise element that was followed in Promise.all() for async stack traces, or null if the CallSite is not a Promise.all() call.

    This answer is a cross-post of an answer I just gave to a similar question as more people might find this page.

提交回复
热议问题