@oselvar/c4
Version:
Test helpers for Cloudflare Workers
75 lines • 2.28 kB
JavaScript
// src/decorators/index.ts
import { basename, extname } from "node:path";
import { trace } from "@opentelemetry/api";
import ErrorStackParser from "error-stack-parser";
function C4Component(params) {
return (component) => {
const tracer = trace.getTracer("@oselvar/c4");
const span = tracer.startSpan("component");
span.setAttribute("name", component.name);
span.setAttribute("tags", params?.tags || []);
span.end();
return component;
};
}
function C4Operation() {
return function(...args) {
if (args.length === 2 && args[1] && typeof args[1] === "object" && args[1].kind === "method") {
const method = args[0];
return c4OperationWrapper(method);
} else {
const descriptor = args[2];
if (descriptor && typeof descriptor.value === "function") {
const originalMethod = descriptor.value;
descriptor.value = c4OperationWrapper(originalMethod);
}
return descriptor;
}
};
}
function c4OperationWrapper(method) {
async function wrapper(...args) {
const calleeName = this.constructor.name;
const stack = ErrorStackParser.parse(new Error());
const callerClassNameCandidates = stack.filter((frame) => !frame.fileName?.match(/\/node_modules\//)).filter((frame) => !frame.fileName?.match(/^node:internal/)).flatMap(toClassNames);
const callerName = callerClassNameCandidates.find(
(callerName2) => callerName2 !== calleeName
);
const operationName = method.name;
const tracer = trace.getTracer("@oselvar/c4");
return tracer.startActiveSpan(
"call",
{
attributes: {
callerName,
calleeName,
operationName
}
},
async (span) => {
try {
return await method.apply(this, args);
} finally {
span.end();
}
}
);
}
return wrapper;
}
function toClassNames(frame) {
const classNames = [];
const functioNameParts = frame.functionName?.split(".") || [];
if (functioNameParts.length === 2) {
classNames.push(functioNameParts[0]);
}
if (frame.fileName) {
classNames.push(basename(frame.fileName, extname(frame.fileName)));
}
return classNames;
}
export {
C4Component,
C4Operation
};
//# sourceMappingURL=index.js.map