Get name and line of calling function in node.js

Javascriptnode.js

Javascript Problem Overview


How can one get the name and line of a function that called the current one? I would like to have a rudimentary debugging function like this (with npmlog defining log.debug):

function debug() {
  var callee, line;
  /* MAGIC */
  log.debug(callee + ":" + line, arguments)
}

When called from another function it would be something like this:

function hello() {
   debug("world!")
}
// outputs something like:
// "hello:2 'world!'"

For clarity, what I want is essentially analogous to this in Python:

import inspect
def caller():
    return inspect.stack()[2][3]
// line no from getframeinfo().lineno

Is there a Node equivalent to accomplish this?

Javascript Solutions


Solution 1 - Javascript

Using info from here: https://stackoverflow.com/questions/11386492/accessing-line-number-in-v8-javascript-chrome-node-js

you can add some prototypes to provide access to this info from V8:

Object.defineProperty(global, '__stack', {
get: function() {
        var orig = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_, stack) {
            return stack;
        };
        var err = new Error;
        Error.captureStackTrace(err, arguments.callee);
        var stack = err.stack;
        Error.prepareStackTrace = orig;
        return stack;
    }
});

Object.defineProperty(global, '__line', {
get: function() {
        return __stack[1].getLineNumber();
    }
});

Object.defineProperty(global, '__function', {
get: function() {
        return __stack[1].getFunctionName();
    }
});

function foo() {
    console.log(__line);
    console.log(__function);
}

foo()

Returns '28' and 'foo', respectively.

Solution 2 - Javascript

The following code uses only core elements. It parses the stack from an error instance.

"use strict";
function debugLine(message) {
    let e = new Error();
    let frame = e.stack.split("\n")[2]; // change to 3 for grandparent func
    let lineNumber = frame.split(":").reverse()[1];
    let functionName = frame.split(" ")[5];
    return functionName + ":" + lineNumber + " " + message;
}
function myCallingFunction() {
    console.log(debugLine("error_message"));
}
myCallingFunction();

It outputs something like myCallingFunction:10 error_message

I've extracted the elements of the error as variables (lineNumber, functionName) so you can format the return value any way you want.

As a side note: the use strict; statement is optional and can be used only if your entire code is using the strict standard. If your code is not compatible with that (although it should be), then feel free to remove it.

Solution 3 - Javascript

I also had similar requirement. I used stack property of Error class provided by nodejs.
I am still learning node so, there may be the chances of error.

Below is the explanation for the same. Also created npm module for the same, if you like, you can check at:

  1. npm module 'logat'
  2. git repo

suppose we 'logger' object with method 'log'

var logger = {
 log: log
}
function log(msg){
  let logLineDetails = ((new Error().stack).split("at ")[3]).trim();
  console.log('DEBUG', new Date().toUTCString(), logLineDetails, msg);
}

Example:

//suppose file name: /home/vikash/example/age.js
function getAge(age) {
    logger.log('Inside getAge function');    //suppose line no: 9
}

Output of above Example:

    DEBUG on Sat, 24 Sept 2016 12:12:10 GMT at getAge(/home/vikash/example/age.js:9:12)
    Inside getAge function

Solution 4 - Javascript

I found and installed the node-stack-trace module (installed with npm install stack-trace), and then defined echo as:

function echo() {
  var args, file, frame, line, method;
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  
  frame = stackTrace.get()[1];
  file = path.basename(frame.getFileName());
  line = frame.getLineNumber();
  method = frame.getFunctionName();
  
  args.unshift("" + file + ":" + line + " in " + method + "()");
  return log.info.apply(log, args); // changed 'debug' to canonical npmlog 'info'
};

Solution 5 - Javascript

Here is a one liner for quick debugging purposes:

console.log("DEBUG", (new Error().stack.split("at ")[1]).trim());

This will log something like this with Node.js:

DEBUG SomeObject.function (/path/to/the/code.js:152:37)

--

You can also add custom args at the end, e.g.

console.log("DEBUG", (new Error().stack.split("at ")[1]).trim(), ">>>", myVar);

Note that if you put this into a helper function, adjust the stack index from e.g. [1] to [2].

Solution 6 - Javascript

Here is a way to get the filename when an error occurs. you have to wrap the function in the onErrorReturnFileName. Here I am wrapping func() from otherNode file.

const {func} = require('./otherNode')

function onErrorReturnFileName(funcToRead) {
	let defaultPrepareStackTrace = Error.prepareStackTrace
	try {
		let getStack = function (err, stack) { return stack; };
		Error.prepareStackTrace = getStack
		return {result: funcToRead(), name: null}
	}catch (ex) {
        return {name: ex.stack.shift().getFileName(), result: null}
	}
	Error.preppareStackTrace = defaultPrepareStackTrace
}
console.log(onErrorReturnFileName(func))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrian M. HuntView Question on Stackoverflow
Solution 1 - JavascriptJoeView Answer on Stackoverflow
Solution 2 - JavascriptCosmin StaicuView Answer on Stackoverflow
Solution 3 - JavascriptVikashView Answer on Stackoverflow
Solution 4 - JavascriptBrian M. HuntView Answer on Stackoverflow
Solution 5 - JavascriptAlexander KlimetschekView Answer on Stackoverflow
Solution 6 - JavascriptJackstineView Answer on Stackoverflow