Coming from Python I wanted to write something like this:
@trace('name', opts)
def business_logic(foo, bar):
return 0To use opentelemetry in specific function and having goodies like putting relevant stuff in the context.
I am using Node.js 20
Careful with decorator or higher order functions
function example() {}
console.log(example.name); // "example"
const example2 = function() {}
console.log(example2.name); // "example2"
const example3 = () => 0
console.log(example3.name); // "example3"
const exampleFunc = function exampleFunction() {};
console.log(exampleFunc.name); // "exampleFunction"
function traceFn(fn) {
return function (...args) {
// Wrapper logic...
return fn(...args);
};
}
const tracedExample = traceFn(example);
console.log(tracedExample.name); // undefinedPreserving Function Names and Stack Traces
`trace-fn.js
function example() {}
console.log(example.name); // "example"
function traceFn(fn) {
const wrapped = function (...args) {
// Wrapper logic...
return fn(...args);
};
Object.defineProperty(wrapped, 'name', {value: `traced${fn.name}`, configurable: true});
return wrapped;
}
const tracedExample = traceFn(example);
console.log(tracedExample.name); // "tracedExample"Error Handling and Stack Traces
etude-trace-fn.js
function traceFn(fn) {
const wrapped = function (...args) {
try {
// Simulate wrapper logic...
return fn(...args);
} catch (error) {
// Create a new error object for clean stack trace handling.
const tracedError = new Error(error.message);
// Omit this wrapped function from the stack trace to make it cleaner.
Error.captureStackTrace(tracedError, wrapped);
// Rethrow the new error with the modified stack trace.
throw tracedError;
}
};
Object.defineProperty(wrapped, 'name', {value: `traced${fn.name}`, configurable: true});
return wrapped;
}
// Adjust the example function to throw an error.
function example() {
throw new Error('Something went wrong!');
}
const tracedExample = traceFn(example);
// Execute the wrapped function to trigger the error.
try {
tracedExample();
} catch (e) {
console.log(e.stack);
}Outputs:
Error: Something went wrong!
at Object.<anonymous> (/tmp/etude-trace-fn.js:30:3)
at Module._compile (node:internal/modules/cjs/loader:1376:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
at Module.load (node:internal/modules/cjs/loader:1207:32)
at Module._load (node:internal/modules/cjs/loader:1023:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
at node:internal/main/run_main_module:28:49
- Inside
traceFn, thetry-catchblock is used to catch any errors thrown by thefn(...args)call. - If an error occurs, a new
Errorobject is created (tracedError), inheriting the message from the caught error for clarity. Error.captureStackTrace(tracedError, wrapped);is then called to modifytracedError's stack trace. It removes thewrappedfunction (and anything above it in the call stack) from the trace. This means when the error is thrown fromwrapped, the stack trace will start from wherewrappedwas called, rather than including the internals ofwrappeditself.- The modified error is then rethrown, and when caught and logged outside of
tracedExample(), it will show a cleaner stack trace that excludes thewrappedfunction, making it easier to identify the source of the erro