nestjs-otel
Version:
NestJS OpenTelemetry Library
66 lines (65 loc) • 2.8 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Span = Span;
const api_1 = require("@opentelemetry/api");
const opentelemetry_utils_1 = require("../../opentelemetry.utils");
const recordException = (span, error) => {
span.recordException(error);
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
};
function Span(nameOrOptions, maybeOptions) {
return (target, propertyKey, propertyDescriptor) => {
let name;
let options;
if (typeof nameOrOptions === 'string') {
name = nameOrOptions;
options = maybeOptions ?? {};
}
else {
name = `${target.constructor.name}.${String(propertyKey)}`;
options = nameOrOptions ?? {};
}
const originalFunction = propertyDescriptor.value;
if (typeof originalFunction !== 'function') {
throw new Error(`The @Span decorator can be only used on functions, but ${propertyKey.toString()} is not a function.`);
}
const wrappedFunction = function PropertyDescriptor(...args) {
const tracer = api_1.trace.getTracer('default');
const spanOptions = typeof options === 'function' ? options(...args) : options;
return tracer.startActiveSpan(name, spanOptions, span => {
if (originalFunction.constructor.name === 'AsyncFunction') {
return originalFunction
.apply(this, args)
.catch((error) => {
recordException(span, error);
// Throw error to propagate it further
throw error;
})
.finally(() => {
span.end();
});
}
try {
return originalFunction.apply(this, args);
}
catch (error) {
recordException(span, error);
// Throw error to propagate it further
throw error;
}
finally {
span.end();
}
});
};
// Wrap the original function in a proxy to ensure that the function name is preserved.
// This should also preserve parameters for OpenAPI and other libraries
// that rely on the function name as metadata key.
propertyDescriptor.value = new Proxy(originalFunction, {
apply: (_, thisArg, args) => {
return wrappedFunction.apply(thisArg, args);
},
});
(0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalFunction, propertyDescriptor.value);
};
}
;