UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

119 lines (118 loc) • 5.22 kB
import { context, trace, } from "@opentelemetry/api"; import { ensureTelemetry } from "../services/server/ai/observability/instrumentation.js"; const PRODUCT_NAME = /neurolink/gi; const OPERATION_ROOT = /^(?:provider\.)?(generate|stream)(?:\.|$)/; const operations = new WeakMap(); const nestedOperations = new WeakSet(); function trackOperation(span, name, parent) { const root = OPERATION_ROOT.exec(name)?.[1]; const parentOperation = parent && operations.get(parent); if (root && parentOperation) { nestedOperations.add(span); } const operation = root ?? parentOperation; if (operation) { operations.set(span, operation); } return span; } /** * @description Reads which public API call the active span belongs to, following the span's ancestry up to a `generate`, `stream`, `provider.generate` or `provider.stream` span. * @returns {GenerationOperation | undefined} The enclosing operation, or `undefined` when no such span is active. */ export function activeOperation() { const span = trace.getSpan(context.active()); return span && operations.get(span); } /** * @description Reports whether a `generate` or `stream` span started inside another operation's span tree. * @param span {Span} - Span returned by a scrubbed tracer. * @returns {boolean} `true` when the span is nested in an enclosing operation, `false` for a trace root. */ export function isNestedOperation(span) { return nestedOperations.has(span); } function scrubException(exception) { if (!(exception instanceof Error)) { return typeof exception === "string" ? exception.replace(PRODUCT_NAME, "ai") : exception; } return { name: exception.name.replace(PRODUCT_NAME, "Ai"), message: exception.message.replace(PRODUCT_NAME, "ai"), }; } function withScrubbedExceptions(span) { const record = span.recordException.bind(span); span.recordException = (exception, time) => record(scrubException(exception), time); return span; } /** * @description Resolves a tracer whose spans record exceptions as type and message only, without stack traces or product-name references that would reach trace backends as event metadata. * @param name {string} - Instrumentation scope name. * @returns {Tracer} A tracer delegating to the globally registered provider. */ export function scrubbedTracer(name) { const inner = trace.getTracer(name); return { startSpan: (spanName, options, ctx) => { ensureTelemetry(); const span = withScrubbedExceptions(inner.startSpan(spanName, options, ctx)); return trackOperation(span, spanName, trace.getSpan(ctx ?? context.active())); }, startActiveSpan(spanName, arg2, arg3, arg4) { ensureTelemetry(); const fn = [arg4, arg3, arg2].find((arg) => typeof arg === "function"); const options = typeof arg2 === "function" ? undefined : arg2; const ctx = typeof arg3 === "function" ? undefined : arg3; const parent = trace.getSpan(ctx ?? context.active()); const wrapped = ((span) => fn(trackOperation(withScrubbedExceptions(span), spanName, parent))); if (ctx) { return inner.startActiveSpan(spanName, options ?? {}, ctx, wrapped); } return options ? inner.startActiveSpan(spanName, options, wrapped) : inner.startActiveSpan(spanName, wrapped); }, }; } /** * Pre-resolved tracers cached at module load. * * Module-load timing is intentional and safe: `trace.getTracer(name)` from * `@opentelemetry/api` always returns a proxy that defers to whatever * `TracerProvider` is registered globally at the moment a span is created. * If the OTel SDK initializes *after* this module is imported (the common * case — telemetry setup typically runs once at app boot, after lazy * imports have already pulled this file), the tracer reference is still * valid; spans created via it correctly route to the SDK once registered. * * Pre-SDK calls produce a noop span — `span.end()` etc. are valid; nothing * is exported. This is OTel's documented contract: * https://opentelemetry.io/docs/specs/otel/trace/api/#tracerprovider * * If a future refactor moves to a non-proxy TracerProvider API (e.g. a * custom provider where `getTracer` returns the live instance), revisit * this file and switch to lazy accessors. */ export const tracers = { sdk: scrubbedTracer("sdk"), provider: scrubbedTracer("provider"), generation: scrubbedTracer("generation"), decision: scrubbedTracer("decision"), stream: scrubbedTracer("stream"), http: scrubbedTracer("http"), mcp: scrubbedTracer("mcp"), memory: scrubbedTracer("memory"), redis: scrubbedTracer("redis"), factory: scrubbedTracer("factory"), rag: scrubbedTracer("rag"), context: scrubbedTracer("context"), middleware: scrubbedTracer("middleware"), processor: scrubbedTracer("processor"), file: scrubbedTracer("file"), autoresearch: scrubbedTracer("autoresearch"), auth: scrubbedTracer("auth"), workflow: scrubbedTracer("workflow"), };