UNPKG

autotel

Version:
178 lines (175 loc) 5.73 kB
let _opentelemetry_api = require("@opentelemetry/api"); //#region src/flatten-attributes.ts /** * Convert an unknown value to an OTel-compatible AttributeValue. * Returns undefined when the value cannot be represented. */ function toAttributeValue(value) { if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value; if (Array.isArray(value)) { if (value.every((v) => typeof v === "string") || value.every((v) => typeof v === "number") || value.every((v) => typeof v === "boolean")) return value; try { return JSON.stringify(value); } catch { return "<serialization-failed>"; } } if (value instanceof Date) return value.toISOString(); if (value instanceof Error) return value.message; } /** * Recursively flatten a nested object into dot-notation OTel attributes. * Includes circular reference protection via WeakSet. */ function flattenToAttributes(fields, prefix = "") { const out = {}; const seen = /* @__PURE__ */ new WeakSet(); function flatten(obj, currentPrefix) { for (const [key, value] of Object.entries(obj)) { if (value == null) continue; const nextKey = currentPrefix ? `${currentPrefix}.${key}` : key; const attr = toAttributeValue(value); if (attr !== void 0) { out[nextKey] = attr; continue; } if (typeof value === "object" && value.constructor === Object) { if (seen.has(value)) { out[nextKey] = "<circular-reference>"; continue; } seen.add(value); flatten(value, nextKey); continue; } try { out[nextKey] = JSON.stringify(value); } catch { out[nextKey] = "<serialization-failed>"; } } } flatten(fields, prefix); return out; } //#endregion //#region src/structured-error.ts const internalKey = Symbol.for("autotel.error.internal"); function createStructuredError(input) { const error = new Error(input.message, { cause: input.cause }); error.name = input.name ?? "StructuredError"; if (input.why !== void 0) error.why = input.why; if (input.fix !== void 0) error.fix = input.fix; if (input.link !== void 0) error.link = input.link; if (input.code !== void 0) error.code = input.code; if (input.status !== void 0) error.status = input.status; if (input.details !== void 0) error.details = input.details; if (input.internal !== void 0) Object.defineProperty(error, internalKey, { value: input.internal, enumerable: false, writable: false, configurable: true }); Object.defineProperty(error, "internal", { get() { return this[internalKey]; }, enumerable: false, configurable: true }); error.toString = () => { const lines = [`${error.name}: ${error.message}`]; if (error.why) lines.push(` Why: ${error.why}`); if (error.fix) lines.push(` Fix: ${error.fix}`); if (error.link) lines.push(` Link: ${error.link}`); if (error.code !== void 0) lines.push(` Code: ${error.code}`); if (error.status !== void 0) lines.push(` Status: ${error.status}`); if (error.cause) { const cause = error.cause; lines.push(` Caused by: ${cause.name}: ${cause.message}`); } return lines.join("\n"); }; return error; } function structuredErrorToJSON(error) { const result = { name: error.name, message: error.message }; if (error.status !== void 0) result.status = error.status; if (error.why || error.fix || error.link) result.data = { ...error.why && { why: error.why }, ...error.fix && { fix: error.fix }, ...error.link && { link: error.link } }; if (error.code !== void 0) result.code = error.code; if (error.details) result.details = error.details; if (error.cause instanceof Error) result.cause = { name: error.cause.name, message: error.cause.message }; return result; } function getStructuredErrorAttributes(error) { const structured = error; const attributes = { "error.type": error.name || "Error", "error.message": error.message }; if (error.stack) attributes["error.stack"] = error.stack; if (structured.why) attributes["error.why"] = structured.why; if (structured.fix) attributes["error.fix"] = structured.fix; if (structured.link) attributes["error.link"] = structured.link; if (structured.code !== void 0) attributes["error.code"] = typeof structured.code === "string" ? structured.code : String(structured.code); if (structured.status !== void 0) attributes["error.status"] = structured.status; if (structured.details) Object.assign(attributes, flattenToAttributes(structured.details, "error.details")); return attributes; } function recordStructuredError(ctx, error) { const maybeRecordException = ctx.recordException; if (typeof maybeRecordException === "function") maybeRecordException(error); ctx.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR, message: error.message }); ctx.setAttributes(getStructuredErrorAttributes(error)); } //#endregion Object.defineProperty(exports, 'createStructuredError', { enumerable: true, get: function () { return createStructuredError; } }); Object.defineProperty(exports, 'flattenToAttributes', { enumerable: true, get: function () { return flattenToAttributes; } }); Object.defineProperty(exports, 'getStructuredErrorAttributes', { enumerable: true, get: function () { return getStructuredErrorAttributes; } }); Object.defineProperty(exports, 'recordStructuredError', { enumerable: true, get: function () { return recordStructuredError; } }); Object.defineProperty(exports, 'structuredErrorToJSON', { enumerable: true, get: function () { return structuredErrorToJSON; } }); Object.defineProperty(exports, 'toAttributeValue', { enumerable: true, get: function () { return toAttributeValue; } }); //# sourceMappingURL=structured-error-CHg7DoIQ.cjs.map