UNPKG

autotel

Version:
388 lines (383 loc) 13.7 kB
export { createDrainPipeline } from './chunk-KFOHQK7X.js'; export { getCurrentWorkflowContext, isInWorkflow, traceStep, traceWorkflow } from './chunk-RXFZKLRQ.js'; export { attrs, autoRedactPII, dbClient, httpClient, httpServer, identify, mergeAttrs, mergeServiceResource, request, safeSetAttributes, setDevice, setError, setException, setSession, setUser, validateAttribute } from './chunk-M4US3P4K.js'; export { httpRequestHeaderAttribute, httpResponseHeaderAttribute } from './chunk-7552UTQW.js'; export { HTTPAttributes, ServiceAttributes, URLAttributes } from './chunk-4A53YIAX.js'; export { parseError } from './chunk-J7VGRIAJ.js'; export { traceConsumer, traceProducer } from './chunk-GTD3NXOS.js'; export { BusinessBaggage, createSafeBaggageSchema } from './chunk-4IFSYQVX.js'; import { resetMetrics } from './chunk-7SAWIN74.js'; export { Metric, getMetrics, resetMetrics } from './chunk-7SAWIN74.js'; import './chunk-5ZN622AO.js'; export { createCounter, createHistogram, createObservableGauge, createUpDownCounter, getMeter } from './chunk-TQ5UWA7S.js'; export { traceDB, traceHTTP, traceLLM, traceMessaging } from './chunk-DGPUZ6TE.js'; import { getEventQueue, resetEventQueue } from './chunk-4PTCDOZY.js'; export { ctx, getEventQueue, instrument, span, trace, track, withBaggage, withNewContext, withTracing } from './chunk-4PTCDOZY.js'; export { createDeterministicTraceId, enrichWithTraceContext, finalizeSpan, flattenMetadata, getActiveContext, getActiveSpan, getTraceContext, getTracer, isTracing, resolveTraceUrl, runWithSpan } from './chunk-B3ZHLLMP.js'; import { resetEvents } from './chunk-WAB4CHBU.js'; export { Event, getEvents, resetEvents } from './chunk-WAB4CHBU.js'; import './chunk-LITNXTTT.js'; import './chunk-BZHG5IZ4.js'; export { getOperationContext, runInOperationContext } from './chunk-WD4RP6IV.js'; export { CORRELATION_ID_BAGGAGE_KEY, generateCorrelationId, getCorrelationId, getOrCreateCorrelationId, runWithCorrelationId, setCorrelationId, setCorrelationIdInBaggage } from './chunk-S4OFEXLA.js'; import { createTraceContext } from './chunk-BBBWDIYQ.js'; export { defineBaggageSchema } from './chunk-BBBWDIYQ.js'; import { getLogger, getSdk, _closeEmbeddedDevtools } from './chunk-EXOXDI5A.js'; export { BaggageSpanProcessor, createStringRedactor, init } from './chunk-EXOXDI5A.js'; import './chunk-RUD7KS4R.js'; import './chunk-XDKK53OL.js'; export { FilteringSpanProcessor } from './chunk-WGWSHJ2N.js'; export { NORMALIZER_PATTERNS, NORMALIZER_PRESETS, SpanNameNormalizingProcessor } from './chunk-GYR5K654.js'; export { AttributeRedactingProcessor, REDACTOR_PATTERNS, REDACTOR_PRESETS, createAttributeRedactor, createRedactedSpan } from './chunk-SNINLBEE.js'; import './chunk-6UQRVUN3.js'; export { formatDuration } from './chunk-3QXBFGKP.js'; import './chunk-33WTKH7X.js'; export { AUTOTEL_SAMPLING_TAIL_EVALUATED, AUTOTEL_SAMPLING_TAIL_KEEP, AdaptiveSampler, AlwaysSampler, NeverSampler, RandomSampler, UserIdSampler, createLinkFromHeaders, extractLinksFromBatch, resolveSamplingPreset, samplingPresets } from './chunk-VYA6QDNA.js'; import './chunk-B33XPEKY.js'; import './chunk-J5QENANM.js'; export { getAutotelTracer, getAutotelTracerProvider, setAutotelTracerProvider } from './chunk-HA2WBOGQ.js'; import './chunk-DGUM43GV.js'; import { AsyncLocalStorage } from 'async_hooks'; import { SpanStatusCode, trace } from '@opentelemetry/api'; export { ROOT_CONTEXT, SpanKind, SpanStatusCode, context, trace as otelTrace, propagation } from '@opentelemetry/api'; // src/shutdown.ts async function flush(options) { const timeout = options?.timeout ?? 2e3; const forShutdown = options?.forShutdown ?? false; const doFlush = async () => { const eventsQueue = getEventQueue(); if (eventsQueue) { if (forShutdown) { await eventsQueue.shutdown(); } else { await eventsQueue.flush(); } } const sdk = getSdk(); if (sdk) { try { const sdkAny = sdk; if (typeof sdkAny.getTracerProvider === "function") { const tracerProvider = sdkAny.getTracerProvider(); if (tracerProvider && typeof tracerProvider.forceFlush === "function") { await tracerProvider.forceFlush(); } } } catch { } } }; let timeoutHandle; try { await Promise.race([ doFlush().finally(() => { if (timeoutHandle) { clearTimeout(timeoutHandle); } }), new Promise((_, reject) => { timeoutHandle = setTimeout( () => reject(new Error("Flush timeout")), timeout ); timeoutHandle.unref(); }) ]); } catch (error) { if (timeoutHandle) { clearTimeout(timeoutHandle); } const logger = getLogger(); logger.error( { err: error instanceof Error ? error : new Error(String(error)) }, "[autotel] Flush error" ); throw error; } } async function shutdown() { const logger = getLogger(); let shutdownError = null; try { await flush({ forShutdown: true }); } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); shutdownError = err; logger.error( { err }, "[autotel] Flush failed during shutdown, continuing cleanup" ); } try { const sdk = getSdk(); if (sdk) { await sdk.shutdown(); } } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); const isConnectionRefused = typeof error === "object" && error !== null && "code" in error && error.code === "ECONNREFUSED"; if (!isConnectionRefused) { if (!shutdownError) { shutdownError = err; } logger.error({ err }, "[autotel] SDK shutdown failed"); } } finally { await _closeEmbeddedDevtools(); const eventsQueue = getEventQueue(); if (eventsQueue && typeof eventsQueue.cleanup === "function") { eventsQueue.cleanup(); } resetEvents(); resetMetrics(); resetEventQueue(); } if (shutdownError) { throw shutdownError; } } function registerShutdownHooks() { if (typeof process === "undefined") return; const signals = ["SIGTERM", "SIGINT"]; let shuttingDown = false; for (const signal of signals) { process.on(signal, async () => { if (shuttingDown) return; shuttingDown = true; if (process.env.NODE_ENV !== "test") { getLogger().info( {}, `[autotel] Received ${signal}, flushing telemetry...` ); } try { await shutdown(); } catch (error) { getLogger().error( { err: error instanceof Error ? error : void 0 }, "[autotel] Error during shutdown" ); } finally { process.exit(0); } }); } } registerShutdownHooks(); // src/flatten-attributes.ts 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; } return void 0; } 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; } // src/structured-error.ts 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; 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) lines.push(` Caused by: ${error.cause}`); return lines.join("\n"); }; return error; } 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(ctx2, error) { ctx2.recordException(error); ctx2.setStatus({ code: SpanStatusCode.ERROR, message: error.message }); ctx2.setAttributes(getStructuredErrorAttributes(error)); } // src/request-logger.ts var requestContextStore = new AsyncLocalStorage(); function runWithRequestContext(ctx2, fn) { return requestContextStore.run(ctx2, fn); } function resolveContext(ctx2) { if (ctx2) return ctx2; const stored = requestContextStore.getStore(); if (stored) return stored; const span2 = trace.getActiveSpan(); if (!span2) { throw new Error( "[autotel] getRequestLogger() requires an active span or runWithRequestContext(). Wrap your handler with trace() or use runWithRequestContext()." ); } return createTraceContext(span2); } function getRequestLogger(ctx2, options) { const activeContext = resolveContext(ctx2); let contextState = {}; const addLogEvent = (level, message, fields) => { const attrs2 = fields ? flattenToAttributes(fields) : void 0; activeContext.addEvent(`log.${level}`, { message, ...attrs2 }); }; return { set(fields) { contextState = { ...contextState, ...fields }; activeContext.setAttributes(flattenToAttributes(fields)); }, info(message, fields) { addLogEvent("info", message, fields); if (fields) { contextState = { ...contextState, ...fields }; activeContext.setAttributes(flattenToAttributes(fields)); } }, warn(message, fields) { addLogEvent("warn", message, fields); activeContext.setAttribute("autotel.log.level", "warn"); if (fields) { contextState = { ...contextState, ...fields }; activeContext.setAttributes(flattenToAttributes(fields)); } }, error(error, fields) { const err = typeof error === "string" ? new Error(error) : error; recordStructuredError(activeContext, err); addLogEvent("error", err.message, fields); if (fields) { contextState = { ...contextState, ...fields }; activeContext.setAttributes(flattenToAttributes(fields)); } activeContext.setAttribute("autotel.log.level", "error"); }, getContext() { return { ...contextState }; }, emitNow(overrides) { const mergedContext = { ...contextState, ...overrides ?? {} }; const flattened = flattenToAttributes(mergedContext); activeContext.setAttributes(flattened); const snapshot = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), traceId: activeContext.traceId, spanId: activeContext.spanId, correlationId: activeContext.correlationId, context: mergedContext }; activeContext.addEvent("log.emit.manual", { ...flattened }); if (options?.onEmit) { Promise.resolve(options.onEmit(snapshot)).catch((error) => { console.warn("[autotel] request logger onEmit failed:", error); }); } return snapshot; } }; } export { createStructuredError, flattenToAttributes, flush, getRequestLogger, getStructuredErrorAttributes, recordStructuredError, runWithRequestContext, shutdown, toAttributeValue }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map