So, I’m implementing some tracing logic and want to standardize how my spans are created. I want them to be named after the function they’re instantiated inside without having to explicitly pass the name of the function every time. Seems like this should be trivial but I can’t find a good way to do it. The best way I came up with is pretty terrible:
function getCurrentFunctionName() {
// Create an error object to capture the stack trace
const error = new Error('fakeError')
// Extract the stack trace and split it into individual lines
const stackTrace = error.stack?.split('n')
if(stackTrace) {
// Get the second line of the stack trace, which contains the function information
const functionLine = stackTrace[2]
const regexResult = ((/ats+([w.]+)s+/u).exec(functionLine))
if(regexResult && regexResult.length >= 2) {
// Extract the function name from the function line
return regexResult[1]
}
}
return 'unknown'
}
This seems silly, especially the part where I use regex to get such basic information. It makes even less sense when you consider that the Error constructor clearly has a way to do this exact same thing otherwise it wouldn’t be able to construct the error stack.
I know that I could do something like:
function nonStrictGetFunctionName() {
return nonStrictGetFunctionName.caller.name
}
Which would be ideal but won’t work in my codebase because using caller/arguments is forbidden in strict mode.
Is there any other way to do this?
2
Answers
Using an error’s stack isn’t a bad idea imho for testing/debugging.
An alternative could be using
Proxy
‘sapply
hander.Note that in the snippet I used a global scope to override the declared functions with proxies.
But there are many ways to override. For example you could override exact need functions manually.
Or if you need all functions in the local scope you could somehow parse the current scope’s source code and extract function names and use
eval
to dynamically override the found functions with proxies.As a direction for parsing: Getting All Variables In Scope
In case you don’t like your implenetation(which is basically okay imho), you can use npm library called stacktrace-js
Here is example code:
It will return following array: