autotel
Version:
Write Once, Observe Anywhere
108 lines (106 loc) • 4.71 kB
JavaScript
import { c as withTracing } from "./functional-Bit6noRu.js";
import { t as assertTraceFactory } from "./trace-factory-validation-BjVAinz6.js";
import { SpanKind } from "@opentelemetry/api";
//#region src/semantic-helpers.ts
/**
* Semantic convention helpers for OpenTelemetry
*
* Pre-configured trace helpers that follow OpenTelemetry semantic conventions
* for common operation types. Reduces boilerplate and ensures consistency.
*
* Based on: https://opentelemetry.io/docs/specs/semconv/
*/
function setConfiguredAttributes(ctx, attributes) {
if (!attributes) return;
for (const [key, value] of Object.entries(attributes)) {
if (value === void 0 || value === null) continue;
const attributeValue = typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : JSON.stringify(value);
ctx.setAttribute(key, attributeValue);
}
}
/**
* Shared tail of `traceDB`/`traceHTTP`/`traceMessaging`: wrap `fn` directly
* when given, otherwise return the curried factory-acceptor form.
*/
function wrapSemantic(helperName, name, spanKind, configure, fn) {
if (fn) {
assertTraceFactory(helperName, fn);
return withTracing({
name,
spanKind
})((ctx) => {
configure(ctx);
return fn;
});
}
return (factory) => {
assertTraceFactory(helperName, factory);
return withTracing({
name,
spanKind
})((ctx) => {
configure(ctx);
const handler = factory(ctx);
assertTraceFactory(helperName, handler, "result");
return handler;
});
};
}
function traceDB(config, fn) {
if (!config || typeof config !== "object") throw new TypeError("traceDB: config must be an object");
if (typeof config.system !== "string" || config.system.trim() === "") throw new TypeError("traceDB: config.system must be a non-empty string");
const target = config.collection ?? config.database;
const spanName = (config.querySummary ?? [config.operation, target].filter(Boolean).join(" ")) || config.system;
const configure = (ctx) => {
ctx.setAttribute("db.system.name", config.system);
ctx.setAttribute("db.system", config.system);
if (config.operation) {
ctx.setAttribute("db.operation.name", config.operation);
ctx.setAttribute("db.operation", config.operation);
}
if (config.database) {
ctx.setAttribute("db.namespace", config.database);
ctx.setAttribute("db.name", config.database);
}
if (config.collection) ctx.setAttribute("db.collection.name", config.collection);
if (config.querySummary) ctx.setAttribute("db.query.summary", config.querySummary);
setConfiguredAttributes(ctx, config.attributes);
};
return wrapSemantic("traceDB", spanName, SpanKind.CLIENT, configure, fn);
}
function traceHTTP(config, fn) {
if (!config || typeof config !== "object") throw new TypeError("traceHTTP: config must be an object");
const method = config.method?.toUpperCase() || "HTTP";
const target = config.route ?? config.urlTemplate;
const spanName = target ? `${method} ${target}` : method;
const configure = (ctx) => {
if (config.method) ctx.setAttribute("http.request.method", method);
if (config.url) ctx.setAttribute("url.full", config.url);
if (config.route) ctx.setAttribute("http.route", config.route);
if (config.urlTemplate) ctx.setAttribute("url.template", config.urlTemplate);
setConfiguredAttributes(ctx, config.attributes);
};
return wrapSemantic("traceHTTP", spanName, SpanKind.CLIENT, configure, fn);
}
function traceMessaging(config, fn) {
if (!config || typeof config !== "object") throw new TypeError("traceMessaging: config must be an object");
if (typeof config.system !== "string" || config.system.trim() === "") throw new TypeError("traceMessaging: config.system must be a non-empty string");
const operation = config.operation ?? "messaging";
const spanName = [operation, config.destination].filter(Boolean).join(" ");
const operationType = operation === "publish" ? "send" : operation;
const spanKind = operation === "publish" ? SpanKind.PRODUCER : operation === "process" ? SpanKind.CONSUMER : operation === "receive" ? SpanKind.CLIENT : SpanKind.INTERNAL;
const configure = (ctx) => {
ctx.setAttribute("messaging.system", config.system);
if (config.operation) {
ctx.setAttribute("messaging.operation.name", config.operation);
ctx.setAttribute("messaging.operation.type", operationType);
ctx.setAttribute("messaging.operation", config.operation);
}
if (config.destination) ctx.setAttribute("messaging.destination.name", config.destination);
setConfiguredAttributes(ctx, config.attributes);
};
return wrapSemantic("traceMessaging", spanName, spanKind, configure, fn);
}
//#endregion
export { traceDB, traceHTTP, traceMessaging };
//# sourceMappingURL=semantic-helpers.js.map