nestjs-otel
Version:
NestJS OpenTelemetry Library
78 lines (77 loc) • 2.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WideEventField = WideEventField;
const opentelemetry_utils_1 = require("../opentelemetry.utils");
const wide_event_context_1 = require("./wide-event.context");
const isAttributeValue = (value) => {
if (typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean") {
return true;
}
if (!Array.isArray(value)) {
return false;
}
let elementType;
for (const el of value) {
if (el == null)
continue;
const t = typeof el;
if (t !== "string" && t !== "number" && t !== "boolean")
return false;
if (elementType && t !== elementType)
return false;
elementType = t;
}
return true;
};
const record = (key, pick, result) => {
const bag = (0, wide_event_context_1.getWideEventBag)();
if (!bag) {
return;
}
try {
const value = pick ? pick(result) : result;
if (isAttributeValue(value)) {
bag.set(key, value);
}
}
catch {
// a failing pick must never break the decorated method
}
};
/**
* Captures the decorated method's return value (resolved value for async
* methods) as an attribute on the current wide event.
*
* No-op when called outside a request handled by the WideEventInterceptor,
* when `pick` throws, or when the value is not a valid attribute value.
*
* @param key The wide event attribute key.
* @param pick Optional projection of the return value to an attribute value.
*
* @publicApi
*/
function WideEventField(key, pick) {
return (_target, propertyKey, propertyDescriptor) => {
const originalFunction = propertyDescriptor.value;
if (typeof originalFunction !== "function") {
throw new Error(`The @WideEventField decorator can be only used on functions, but ${propertyKey.toString()} is not a function.`);
}
const wrappedFunction = function WideEventFieldWrapper(...args) {
const result = originalFunction.apply(this, args);
if (result instanceof Promise) {
return result.then((resolved) => {
record(key, pick, resolved);
return resolved;
});
}
record(key, pick, result);
return result;
};
propertyDescriptor.value = new Proxy(originalFunction, {
apply: (_, thisArg, args) => wrappedFunction.apply(thisArg, args),
});
(0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalFunction, propertyDescriptor.value);
};
}