@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
JavaScript
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"),
};