🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@sentry/server-utils

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sentry/server-utils - npm Package Compare versions

Comparing version
10.63.0
to
10.64.0
+101
build/cjs/integrations/tracing-channel/anthropic.js
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const diagnosticsChannel = require('node:diagnostics_channel');
const core = require('@sentry/core');
const debugBuild = require('../../debug-build.js');
const channels = require('../../orchestrion/channels.js');
const tracingChannel = require('../../tracing-channel.js');
const INTEGRATION_NAME = "Anthropic_AI";
const ORIGIN = "auto.ai.orchestrion.anthropic";
const INSTRUMENTED_CHANNELS = [
{ channel: channels.CHANNELS.ANTHROPIC_CHAT, operation: "chat", methodPath: "messages.create", stream: "async-iterable" },
{ channel: channels.CHANNELS.ANTHROPIC_MODELS, operation: "models", methodPath: "models.retrieve", stream: "none" },
{
channel: channels.CHANNELS.ANTHROPIC_MESSAGES_STREAM,
operation: "chat",
methodPath: "messages.stream",
stream: "message-stream"
}
];
let subscribed = false;
const _anthropicChannelIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel || subscribed) {
return;
}
subscribed = true;
core.waitForTracingChannelBinding(() => {
for (const { channel, operation, methodPath, stream } of INSTRUMENTED_CHANNELS) {
debugBuild.DEBUG_BUILD && core.debug.log(`[orchestrion:anthropic] subscribing to channel "${channel}"`);
tracingChannel.bindTracingChannelToSpan(
diagnosticsChannel.tracingChannel(channel),
(data) => createGenAiSpan(data, operation, methodPath, options),
{
beforeSpanEnd: (span, data) => {
core.addAnthropicResponseAttributes(
span,
data.result,
core.resolveAIRecordingOptions(options).recordOutputs
);
},
deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, stream, options)
}
);
}
});
}
};
});
function createGenAiSpan(data, operation, methodPath, options) {
const args = data.arguments ?? [];
if (core._INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {
return void 0;
}
const requestOptions = args[1];
if (requestOptions?.headers?.["X-Stainless-Helper-Method"] === "stream") {
return void 0;
}
const params = typeof args[0] === "object" && args[0] !== null ? args[0] : void 0;
const { recordInputs } = core.resolveAIRecordingOptions(options);
const enableTruncation = core.shouldEnableTruncation(options.enableTruncation);
const attributes = core.extractAnthropicRequestAttributes(args, methodPath, operation);
const model = attributes[core.GEN_AI_REQUEST_MODEL_ATTRIBUTE] || "unknown";
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const span = core.startInactiveSpan({
name: `${operation} ${model}`,
op: `gen_ai.${operation}`,
attributes
});
if (recordInputs && params) {
core.addAnthropicRequestAttributes(span, params, enableTruncation);
}
return span;
}
function isAsyncIterable(value) {
return !!value && typeof value[Symbol.asyncIterator] === "function";
}
function isMessageStream(value) {
return !!value && typeof value.on === "function";
}
function wrapStreamResult(span, data, stream, options) {
const { recordOutputs } = core.resolveAIRecordingOptions(options);
const result = data.result;
if (stream === "async-iterable" && isAsyncIterable(result)) {
const iterate = result[Symbol.asyncIterator].bind(result);
const instrumented = core.instrumentAsyncIterableStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs);
result[Symbol.asyncIterator] = () => instrumented;
return true;
}
if (stream === "message-stream" && isMessageStream(result)) {
core.instrumentMessageStream(result, span, recordOutputs);
return true;
}
return false;
}
const anthropicChannelIntegration = core.defineIntegration(_anthropicChannelIntegration);
exports.anthropicChannelIntegration = anthropicChannelIntegration;
//# sourceMappingURL=anthropic.js.map
{"version":3,"file":"anthropic.js","sources":["../../../../src/integrations/tracing-channel/anthropic.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { AnthropicAiOptions, AnthropicAiResponse, IntegrationFn, Span, SpanAttributeValue } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n addAnthropicRequestAttributes,\n addAnthropicResponseAttributes,\n debug,\n defineIntegration,\n extractAnthropicRequestAttributes,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n instrumentAsyncIterableStream,\n instrumentMessageStream,\n resolveAIRecordingOptions,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// Same name as the OTel integration by design: when enabled, the OTel 'Anthropic_AI'\n// integration is dropped from the default set (see the Node opt-in loader).\nconst INTEGRATION_NAME = 'Anthropic_AI' as const;\n\n// Distinct from the proxy's `auto.ai.anthropic` so spans from the orchestrion path\n// are attributable separately from the OTel/proxy one.\nconst ORIGIN = 'auto.ai.orchestrion.anthropic';\n\n// `stream` determines how the span is ended\nconst INSTRUMENTED_CHANNELS = [\n { channel: CHANNELS.ANTHROPIC_CHAT, operation: 'chat', methodPath: 'messages.create', stream: 'async-iterable' },\n { channel: CHANNELS.ANTHROPIC_MODELS, operation: 'models', methodPath: 'models.retrieve', stream: 'none' },\n {\n channel: CHANNELS.ANTHROPIC_MESSAGES_STREAM,\n operation: 'chat',\n methodPath: 'messages.stream',\n stream: 'message-stream',\n },\n] as const;\n\ntype StreamMode = (typeof INSTRUMENTED_CHANNELS)[number]['stream'];\n\ninterface AnthropicChannelContext {\n arguments: unknown[];\n result?: unknown;\n}\n\nlet subscribed = false;\n\nconst _anthropicChannelIntegration = ((options: AnthropicAiOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // tracingChannel is unavailable before Node 18.19 and prevent double-subscribe\n if (!diagnosticsChannel.tracingChannel || subscribed) {\n return;\n }\n subscribed = true;\n\n // `bindTracingChannelToSpan` needs the async-context binding that `initOpenTelemetry()` registers\n // after `setupOnce` runs, so wait for it before subscribing.\n waitForTracingChannelBinding(() => {\n for (const { channel, operation, methodPath, stream } of INSTRUMENTED_CHANNELS) {\n DEBUG_BUILD && debug.log(`[orchestrion:anthropic] subscribing to channel \"${channel}\"`);\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<AnthropicChannelContext>(channel),\n data => createGenAiSpan(data, operation, methodPath, options),\n {\n beforeSpanEnd: (span, data) => {\n addAnthropicResponseAttributes(\n span,\n data.result as AnthropicAiResponse,\n resolveAIRecordingOptions(options).recordOutputs,\n );\n },\n deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, stream, options),\n },\n );\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Build the span for an instrumented call.\n * Returning `undefined` opts the payload out so no span is opened.\n */\nfunction createGenAiSpan(\n data: AnthropicChannelContext,\n operation: string,\n methodPath: string,\n options: AnthropicAiOptions,\n): Span | undefined {\n const args = data.arguments ?? [];\n\n // When LangChain (or another provider) is driving the SDK, it records the spans itself and marks this\n // provider as skipped — mirror the OTel integration and don't double-instrument.\n if (_INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {\n return undefined;\n }\n\n // `messages.stream()` internally calls the instrumented `messages.create({ stream: true })` tagged with\n // an `X-Stainless-Helper-Method: 'stream'` header. The messages-stream channel already covers it, so skip\n // the nested create to avoid a duplicate span.\n const requestOptions = args[1] as { headers?: Record<string, unknown> } | undefined;\n if (requestOptions?.headers?.['X-Stainless-Helper-Method'] === 'stream') {\n return undefined;\n }\n\n const params = typeof args[0] === 'object' && args[0] !== null ? (args[0] as Record<string, unknown>) : undefined;\n\n const { recordInputs } = resolveAIRecordingOptions(options);\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n\n const attributes = extractAnthropicRequestAttributes(args, methodPath, operation);\n const model = (attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;\n\n const span = startInactiveSpan({\n name: `${operation} ${model}`,\n op: `gen_ai.${operation}`,\n attributes: attributes as Record<string, SpanAttributeValue>,\n });\n\n if (recordInputs && params) {\n addAnthropicRequestAttributes(span, params, enableTruncation);\n }\n\n return span;\n}\n\ntype AsyncIterableStream = { [Symbol.asyncIterator]: () => AsyncIterator<unknown> };\ntype MessageStreamEmitter = { on: (...args: unknown[]) => void };\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterableStream {\n return !!value && typeof (value as AsyncIterableStream)[Symbol.asyncIterator] === 'function';\n}\n\nfunction isMessageStream(value: unknown): value is MessageStreamEmitter {\n return !!value && typeof (value as MessageStreamEmitter).on === 'function';\n}\n\n/**\n * Hand span-ending ownership to a streamed result: returns `true` to skip the normal `beforeSpanEnd`,\n * `false` for non-streaming results (which end via `beforeSpanEnd`).\n *\n * - `async-iterable`: patch the `Stream`'s async iterator in place so `instrumentAsyncIterableStream` ends\n * the span when iteration finishes.\n * - `message-stream`: `instrumentMessageStream` attaches `'message'`/`'error'` listeners that end the span.\n */\nfunction wrapStreamResult(\n span: Span,\n data: AnthropicChannelContext,\n stream: StreamMode,\n options: AnthropicAiOptions,\n): boolean {\n const { recordOutputs } = resolveAIRecordingOptions(options);\n const result = data.result;\n\n if (stream === 'async-iterable' && isAsyncIterable(result)) {\n const iterate = result[Symbol.asyncIterator].bind(result);\n const instrumented = instrumentAsyncIterableStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs);\n result[Symbol.asyncIterator] = () => instrumented;\n return true;\n }\n\n if (stream === 'message-stream' && isMessageStream(result)) {\n instrumentMessageStream(result, span, recordOutputs);\n return true;\n }\n\n return false;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven Anthropic integration. Subscribes to the `orchestrion:@anthropic-ai/sdk:*`\n * diagnostics_channels injected into the SDK's chat (`messages`/`completions`/beta `messages`), `models`, and\n * `messages.stream()` methods, so it requires the orchestrion runtime hook or bundler plugin.\n */\nexport const anthropicChannelIntegration = defineIntegration(_anthropicChannelIntegration);\n"],"names":["CHANNELS","waitForTracingChannelBinding","DEBUG_BUILD","debug","bindTracingChannelToSpan","addAnthropicResponseAttributes","resolveAIRecordingOptions","_INTERNAL_shouldSkipAiProviderWrapping","shouldEnableTruncation","extractAnthropicRequestAttributes","GEN_AI_REQUEST_MODEL_ATTRIBUTE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startInactiveSpan","addAnthropicRequestAttributes","instrumentAsyncIterableStream","instrumentMessageStream","defineIntegration"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const LIFECYCLE_EXT_POINTS = [
"onPreAuth",
"onCredentials",
"onPostAuth",
"onPreHandler",
"onPostHandler",
"onPreResponse",
"onRequest"
];
const handlerPatched = /* @__PURE__ */ Symbol("hapi-handler-patched");
const HapiLayerType = {
ROUTER: "router",
PLUGIN: "plugin",
EXT: "server.ext"
};
const HapiLifecycleMethodNames = new Set(LIFECYCLE_EXT_POINTS);
var AttributeNames = /* @__PURE__ */ ((AttributeNames2) => {
AttributeNames2["HAPI_TYPE"] = "hapi.type";
AttributeNames2["PLUGIN_NAME"] = "hapi.plugin.name";
AttributeNames2["EXT_TYPE"] = "server.ext.type";
return AttributeNames2;
})(AttributeNames || {});
exports.AttributeNames = AttributeNames;
exports.HapiLayerType = HapiLayerType;
exports.HapiLifecycleMethodNames = HapiLifecycleMethodNames;
exports.handlerPatched = handlerPatched;
//# sourceMappingURL=hapi-types.js.map
{"version":3,"file":"hapi-types.js","sources":["../../../../src/integrations/tracing-channel/hapi-types.ts"],"sourcesContent":["/*\n * Structural type definitions and constants ported from the vendored\n * `@opentelemetry/instrumentation-hapi` types, with all `@hapi/*` and\n * `@opentelemetry/*` dependencies removed. Only the shapes actually accessed by\n * the orchestrion hapi subscriber are kept.\n */\n\n// Single source of truth for the request lifecycle extension points, so the\n// `ServerRequestExtType` union and the runtime `HapiLifecycleMethodNames` set\n// below can't drift apart.\nconst LIFECYCLE_EXT_POINTS = [\n 'onPreAuth',\n 'onCredentials',\n 'onPostAuth',\n 'onPreHandler',\n 'onPostHandler',\n 'onPreResponse',\n 'onRequest',\n] as const;\n\nexport type ServerRequestExtType = (typeof LIFECYCLE_EXT_POINTS)[number];\n\nexport type LifecycleMethod = (request: unknown, h: unknown, err?: Error) => unknown;\n\nexport interface ServerRouteOptions {\n handler?: LifecycleMethod | unknown;\n [key: string]: unknown;\n}\n\nexport interface ServerRoute {\n path: string;\n method: string;\n handler?: LifecycleMethod | unknown;\n options?: ((server: unknown) => ServerRouteOptions) | ServerRouteOptions;\n [key: string]: unknown;\n}\n\nexport interface ServerExtEventsObject {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface ServerExtEventsRequestObject {\n type: ServerRequestExtType;\n method: LifecycleMethod;\n [key: string]: unknown;\n}\n\nexport interface ServerExtOptions {\n [key: string]: unknown;\n}\n\n/**\n * This symbol is used to mark a Hapi route handler or server extension handler as\n * already patched, since it's possible to use these handlers multiple times\n * i.e. when allowing multiple versions of one plugin, or when registering a plugin\n * multiple times on different servers.\n */\nexport const handlerPatched: unique symbol = Symbol('hapi-handler-patched');\n\nexport type PatchableServerRoute = ServerRoute & {\n [handlerPatched]?: boolean;\n};\n\nexport type PatchableExtMethod = LifecycleMethod & {\n [handlerPatched]?: boolean;\n};\n\nexport type ServerExtDirectInput = [ServerRequestExtType, LifecycleMethod, (ServerExtOptions | undefined)?];\n\nexport const HapiLayerType = {\n ROUTER: 'router',\n PLUGIN: 'plugin',\n EXT: 'server.ext',\n} as const;\n\nexport const HapiLifecycleMethodNames = new Set<string>(LIFECYCLE_EXT_POINTS);\n\nexport enum AttributeNames {\n HAPI_TYPE = 'hapi.type',\n PLUGIN_NAME = 'hapi.plugin.name',\n EXT_TYPE = 'server.ext.type',\n}\n"],"names":["AttributeNames"],"mappings":";;AAUA,MAAM,oBAAA,GAAuB;AAAA,EAC3B,WAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA;AAwCO,MAAM,cAAA,0BAAuC,sBAAsB;AAYnE,MAAM,aAAA,GAAgB;AAAA,EAC3B,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ,QAAA;AAAA,EACR,GAAA,EAAK;AACP;AAEO,MAAM,wBAAA,GAA2B,IAAI,GAAA,CAAY,oBAAoB;AAErE,IAAK,cAAA,qBAAAA,eAAAA,KAAL;AACL,EAAAA,gBAAA,WAAA,CAAA,GAAY,WAAA;AACZ,EAAAA,gBAAA,aAAA,CAAA,GAAc,kBAAA;AACd,EAAAA,gBAAA,UAAA,CAAA,GAAW,iBAAA;AAHD,EAAA,OAAAA,eAAAA;AAAA,CAAA,EAAA,cAAA,IAAA,EAAA;;;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const core = require('@sentry/core');
const attributes = require('@sentry/conventions/attributes');
const hapiTypes = require('./hapi-types.js');
function setHttpServerSpanRouteAttribute(route) {
const activeSpan = core.getActiveSpan();
if (!activeSpan) {
return;
}
const rootSpan = core.getRootSpan(activeSpan);
if (!rootSpan) {
return;
}
if (core.spanToJSON(rootSpan).data[core.SEMANTIC_ATTRIBUTE_SENTRY_OP] !== "http.server") {
return;
}
rootSpan.setAttribute(attributes.HTTP_ROUTE, route);
}
const isLifecycleExtType = (variableToCheck) => {
return typeof variableToCheck === "string" && hapiTypes.HapiLifecycleMethodNames.has(variableToCheck);
};
const isLifecycleExtEventObj = (variableToCheck) => {
const event = variableToCheck?.type;
return event !== void 0 && isLifecycleExtType(event);
};
const isDirectExtInput = (variableToCheck) => {
return Array.isArray(variableToCheck) && variableToCheck.length <= 3 && isLifecycleExtType(variableToCheck[0]) && typeof variableToCheck[1] === "function";
};
const isPatchableExtMethod = (variableToCheck) => {
return !Array.isArray(variableToCheck);
};
const getRouteMetadata = (route, pluginName) => {
const attributes$1 = {
[attributes.HTTP_ROUTE]: route.path,
// eslint-disable-next-line typescript/no-deprecated -- TODO(v11): Replace deprecated attributes
[attributes.HTTP_METHOD]: route.method
};
let name;
if (pluginName) {
attributes$1[hapiTypes.AttributeNames.HAPI_TYPE] = hapiTypes.HapiLayerType.PLUGIN;
attributes$1[hapiTypes.AttributeNames.PLUGIN_NAME] = pluginName;
name = `${pluginName}: route - ${route.path}`;
} else {
attributes$1[hapiTypes.AttributeNames.HAPI_TYPE] = hapiTypes.HapiLayerType.ROUTER;
name = `route - ${route.path}`;
}
return { attributes: attributes$1, name };
};
const getExtMetadata = (extPoint, pluginName, methodName) => {
let baseName = `ext - ${extPoint}`;
if (methodName && methodName !== "method") {
baseName = `ext - ${extPoint} - ${methodName}`;
}
if (pluginName) {
return {
attributes: {
[hapiTypes.AttributeNames.EXT_TYPE]: extPoint,
[hapiTypes.AttributeNames.HAPI_TYPE]: hapiTypes.HapiLayerType.EXT,
[hapiTypes.AttributeNames.PLUGIN_NAME]: pluginName
},
name: `${pluginName}: ${baseName}`
};
}
return {
attributes: {
[hapiTypes.AttributeNames.EXT_TYPE]: extPoint,
[hapiTypes.AttributeNames.HAPI_TYPE]: hapiTypes.HapiLayerType.EXT
},
name: baseName
};
};
function startMetadataSpan(metadata, original) {
return core.startSpan(
{
name: metadata.name,
op: `${metadata.attributes[hapiTypes.AttributeNames.HAPI_TYPE]}.hapi`,
attributes: {
...metadata.attributes,
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.orchestrion.hapi"
}
},
original
);
}
function wrapRouteHandler(route, pluginName) {
if (route[hapiTypes.handlerPatched] === true) return route;
route[hapiTypes.handlerPatched] = true;
const wrapHandler = (oldHandler) => {
return function(...params) {
if (!core.getActiveSpan()) {
return oldHandler.call(this, ...params);
}
setHttpServerSpanRouteAttribute(route.path);
const metadata = getRouteMetadata(route, pluginName);
return startMetadataSpan(metadata, () => oldHandler.call(this, ...params));
};
};
if (typeof route.handler === "function") {
route.handler = wrapHandler(route.handler);
} else if (typeof route.options === "function") {
const oldOptions = route.options;
route.options = function(server) {
const options = oldOptions(server);
if (typeof options.handler === "function") {
options.handler = wrapHandler(options.handler);
}
return options;
};
} else if (typeof route.options?.handler === "function") {
route.options.handler = wrapHandler(route.options.handler);
}
return route;
}
function wrapExtMethods(method, extPoint, pluginName) {
if (Array.isArray(method)) {
for (let i = 0; i < method.length; i++) {
method[i] = wrapExtMethods(method[i], extPoint);
}
return method;
} else if (isPatchableExtMethod(method)) {
if (method[hapiTypes.handlerPatched] === true) return method;
method[hapiTypes.handlerPatched] = true;
const newHandler = function(...params) {
if (!core.getActiveSpan()) {
return method.apply(this, params);
}
const metadata = getExtMetadata(extPoint, pluginName, method.name);
return startMetadataSpan(metadata, () => method.apply(void 0, params));
};
newHandler[hapiTypes.handlerPatched] = true;
return newHandler;
}
return method;
}
function wrapRouteArguments(args, pluginName) {
const route = args[0];
if (Array.isArray(route)) {
for (let i = 0; i < route.length; i++) {
route[i] = wrapRouteHandler(route[i], pluginName);
}
} else {
args[0] = wrapRouteHandler(route, pluginName);
}
}
function wrapExtArguments(args, pluginName) {
if (Array.isArray(args[0])) {
const eventsList = args[0];
for (let i = 0; i < eventsList.length; i++) {
const eventObj = eventsList[i];
if (isLifecycleExtType(eventObj.type)) {
const lifecycleEventObj = eventObj;
const handler = wrapExtMethods(lifecycleEventObj.method, eventObj.type, pluginName);
lifecycleEventObj.method = handler;
eventsList[i] = lifecycleEventObj;
}
}
return;
} else if (isDirectExtInput(args)) {
const extInput = args;
const method = extInput[1];
const handler = wrapExtMethods(method, extInput[0], pluginName);
args[1] = handler;
return;
} else if (isLifecycleExtEventObj(args[0])) {
const lifecycleEventObj = args[0];
const handler = wrapExtMethods(lifecycleEventObj.method, lifecycleEventObj.type, pluginName);
lifecycleEventObj.method = handler;
}
}
exports.getExtMetadata = getExtMetadata;
exports.getRouteMetadata = getRouteMetadata;
exports.wrapExtArguments = wrapExtArguments;
exports.wrapRouteArguments = wrapRouteArguments;
//# sourceMappingURL=hapi-utils.js.map
{"version":3,"file":"hapi-utils.js","sources":["../../../../src/integrations/tracing-channel/hapi-utils.ts"],"sourcesContent":["/*\n * OTel-free, `@hapi/*`-free port of the span-building helpers and handler/ext\n * wrap logic from the vendored `@opentelemetry/instrumentation-hapi`\n * (upstream @opentelemetry/instrumentation-hapi@0.64.0). Span output (names,\n * ops, origins, attributes) is kept byte-identical to that instrumentation;\n * span creation goes through the `@sentry/core` API and the OTel active-span\n * guard is replaced with `getActiveSpan()`.\n */\n\nimport {\n getActiveSpan,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n startSpan,\n} from '@sentry/core';\nimport type {\n LifecycleMethod,\n PatchableExtMethod,\n PatchableServerRoute,\n ServerExtDirectInput,\n ServerExtEventsObject,\n ServerExtEventsRequestObject,\n ServerRequestExtType,\n ServerRoute,\n ServerRouteOptions,\n} from './hapi-types';\n// eslint-disable-next-line typescript/no-deprecated -- TODO(v11): Replace deprecated attributes\nimport { HTTP_METHOD, HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport { AttributeNames, handlerPatched, HapiLayerType, HapiLifecycleMethodNames } from './hapi-types';\n\ntype SpanAttributes = Record<string, string | undefined>;\n\ninterface SpanMetadata {\n attributes: SpanAttributes;\n name: string;\n}\n\n/**\n * Set the `http.route` attribute on the root HTTP server span for the current trace.\n *\n * No-op when there is no active span, no root span, or the root span is not an\n * `http.server` span — so framework instrumentations can call this unconditionally\n * without risking attribute pollution on non-HTTP root spans.\n */\nfunction setHttpServerSpanRouteAttribute(route: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) {\n return;\n }\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) {\n return;\n }\n if (spanToJSON(rootSpan).data[SEMANTIC_ATTRIBUTE_SENTRY_OP] !== 'http.server') {\n return;\n }\n rootSpan.setAttribute(HTTP_ROUTE, route);\n}\n\nconst isLifecycleExtType = (variableToCheck: unknown): variableToCheck is ServerRequestExtType => {\n return typeof variableToCheck === 'string' && HapiLifecycleMethodNames.has(variableToCheck);\n};\n\nconst isLifecycleExtEventObj = (variableToCheck: unknown): variableToCheck is ServerExtEventsRequestObject => {\n const event = (variableToCheck as ServerExtEventsRequestObject)?.type;\n return event !== undefined && isLifecycleExtType(event);\n};\n\nconst isDirectExtInput = (variableToCheck: unknown): variableToCheck is ServerExtDirectInput => {\n return (\n Array.isArray(variableToCheck) &&\n variableToCheck.length <= 3 &&\n isLifecycleExtType(variableToCheck[0]) &&\n typeof variableToCheck[1] === 'function'\n );\n};\n\nconst isPatchableExtMethod = (\n variableToCheck: PatchableExtMethod | PatchableExtMethod[],\n): variableToCheck is PatchableExtMethod => {\n return !Array.isArray(variableToCheck);\n};\n\n/** Build the span name and attributes for a Hapi route. */\nexport const getRouteMetadata = (route: ServerRoute, pluginName?: string): SpanMetadata => {\n const attributes: SpanAttributes = {\n [HTTP_ROUTE]: route.path,\n // eslint-disable-next-line typescript/no-deprecated -- TODO(v11): Replace deprecated attributes\n [HTTP_METHOD]: route.method,\n };\n\n let name;\n if (pluginName) {\n attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.PLUGIN;\n attributes[AttributeNames.PLUGIN_NAME] = pluginName;\n name = `${pluginName}: route - ${route.path}`;\n } else {\n attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.ROUTER;\n name = `route - ${route.path}`;\n }\n\n return { attributes, name };\n};\n\n/** Build the span name and attributes for a Hapi server extension. */\nexport const getExtMetadata = (\n extPoint: ServerRequestExtType,\n pluginName?: string,\n methodName?: string,\n): SpanMetadata => {\n let baseName = `ext - ${extPoint}`;\n if (methodName && methodName !== 'method') {\n // `method` is the default name for the extension in the ServerExtEventsObject format.\n baseName = `ext - ${extPoint} - ${methodName}`;\n }\n if (pluginName) {\n return {\n attributes: {\n [AttributeNames.EXT_TYPE]: extPoint,\n [AttributeNames.HAPI_TYPE]: HapiLayerType.EXT,\n [AttributeNames.PLUGIN_NAME]: pluginName,\n },\n name: `${pluginName}: ${baseName}`,\n };\n }\n return {\n attributes: {\n [AttributeNames.EXT_TYPE]: extPoint,\n [AttributeNames.HAPI_TYPE]: HapiLayerType.EXT,\n },\n name: baseName,\n };\n};\n\nfunction startMetadataSpan(metadata: SpanMetadata, original: () => unknown): unknown {\n return startSpan(\n {\n name: metadata.name,\n op: `${metadata.attributes[AttributeNames.HAPI_TYPE]}.hapi`,\n attributes: {\n ...metadata.attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.orchestrion.hapi',\n },\n },\n original,\n );\n}\n\n/**\n * Patches each individual route handler method in order to create the span. It\n * does not create spans when there is no parent span.\n */\nfunction wrapRouteHandler(route: PatchableServerRoute, pluginName?: string): PatchableServerRoute {\n if (route[handlerPatched] === true) return route;\n route[handlerPatched] = true;\n\n const wrapHandler: (oldHandler: LifecycleMethod) => LifecycleMethod = oldHandler => {\n return function (this: unknown, ...params: Parameters<LifecycleMethod>) {\n if (!getActiveSpan()) {\n return oldHandler.call(this, ...params);\n }\n setHttpServerSpanRouteAttribute(route.path);\n const metadata = getRouteMetadata(route, pluginName);\n return startMetadataSpan(metadata, () => oldHandler.call(this, ...params));\n };\n };\n\n if (typeof route.handler === 'function') {\n route.handler = wrapHandler(route.handler as LifecycleMethod);\n } else if (typeof route.options === 'function') {\n const oldOptions = route.options;\n route.options = function (server: unknown): ServerRouteOptions {\n const options = oldOptions(server);\n if (typeof options.handler === 'function') {\n options.handler = wrapHandler(options.handler as LifecycleMethod);\n }\n return options;\n };\n } else if (typeof route.options?.handler === 'function') {\n route.options.handler = wrapHandler(route.options.handler as LifecycleMethod);\n }\n return route;\n}\n\n/**\n * Wraps request extension methods to add instrumentation to each new extension\n * handler. It does not create spans when there is no parent span.\n */\nfunction wrapExtMethods<T extends PatchableExtMethod | PatchableExtMethod[]>(\n method: T,\n extPoint: ServerRequestExtType,\n pluginName?: string,\n): T {\n if (Array.isArray(method)) {\n for (let i = 0; i < method.length; i++) {\n method[i] = wrapExtMethods(method[i]!, extPoint);\n }\n return method;\n } else if (isPatchableExtMethod(method)) {\n if (method[handlerPatched] === true) return method;\n method[handlerPatched] = true;\n\n const newHandler: PatchableExtMethod = function (this: unknown, ...params: Parameters<LifecycleMethod>) {\n if (!getActiveSpan()) {\n return method.apply(this, params);\n }\n const metadata = getExtMetadata(extPoint, pluginName, method.name);\n return startMetadataSpan(metadata, () => method.apply(undefined, params));\n };\n // Mark the wrapper too (not just the original)\n newHandler[handlerPatched] = true;\n return newHandler as T;\n }\n return method;\n}\n\n/**\n * Wrap the route handler(s) in the live `server.route` arguments array, mutating\n * `args[0]` in place. `args[0]` is either a single route options object or an\n * array of them. Idempotent via the `handlerPatched` marker.\n */\nexport function wrapRouteArguments(args: unknown[], pluginName?: string): void {\n const route = args[0] as PatchableServerRoute | PatchableServerRoute[];\n if (Array.isArray(route)) {\n for (let i = 0; i < route.length; i++) {\n route[i] = wrapRouteHandler(route[i]!, pluginName);\n }\n } else {\n args[0] = wrapRouteHandler(route, pluginName);\n }\n}\n\n/**\n * Wrap the extension method(s) in the live `server.ext` arguments array,\n * mutating `args` in place. Handles the three accepted input shapes:\n * `(eventsArray)`, `(lifecycleEventObject)`, and `(extTypeString, method, options)`.\n * Idempotent via the `handlerPatched` marker.\n */\nexport function wrapExtArguments(args: unknown[], pluginName?: string): void {\n if (Array.isArray(args[0])) {\n const eventsList = args[0] as ServerExtEventsObject[] | ServerExtEventsRequestObject[];\n for (let i = 0; i < eventsList.length; i++) {\n const eventObj = eventsList[i]!;\n if (isLifecycleExtType(eventObj.type)) {\n const lifecycleEventObj = eventObj as ServerExtEventsRequestObject;\n const handler = wrapExtMethods(lifecycleEventObj.method, eventObj.type, pluginName);\n lifecycleEventObj.method = handler;\n eventsList[i] = lifecycleEventObj;\n }\n }\n return;\n } else if (isDirectExtInput(args)) {\n const extInput: ServerExtDirectInput = args;\n const method: PatchableExtMethod = extInput[1];\n const handler = wrapExtMethods(method, extInput[0], pluginName);\n args[1] = handler;\n return;\n } else if (isLifecycleExtEventObj(args[0])) {\n const lifecycleEventObj = args[0];\n const handler = wrapExtMethods(lifecycleEventObj.method, lifecycleEventObj.type, pluginName);\n lifecycleEventObj.method = handler;\n }\n}\n"],"names":["getActiveSpan","getRootSpan","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","HTTP_ROUTE","HapiLifecycleMethodNames","attributes","HTTP_METHOD","AttributeNames","HapiLayerType","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","handlerPatched"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const diagnosticsChannel = require('node:diagnostics_channel');
const core = require('@sentry/core');
const debugBuild = require('../../debug-build.js');
const channels = require('../../orchestrion/channels.js');
const hapiUtils = require('./hapi-utils.js');
const INTEGRATION_NAME = "Hapi";
const _hapiChannelIntegration = (() => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
debugBuild.DEBUG_BUILD && core.debug.log(`[orchestrion:hapi] subscribing to channels "${channels.CHANNELS.HAPI_ROUTE}" / "${channels.CHANNELS.HAPI_EXT}"`);
diagnosticsChannel.tracingChannel(channels.CHANNELS.HAPI_ROUTE).subscribe({
start(rawCtx) {
const ctx = rawCtx;
hapiUtils.wrapRouteArguments(ctx.arguments, ctx.self?.realm?.plugin);
},
end() {
},
asyncStart() {
},
asyncEnd() {
},
error() {
}
});
diagnosticsChannel.tracingChannel(channels.CHANNELS.HAPI_EXT).subscribe({
start(rawCtx) {
const ctx = rawCtx;
hapiUtils.wrapExtArguments(ctx.arguments, ctx.self?.realm?.plugin);
},
end() {
},
asyncStart() {
},
asyncEnd() {
},
error() {
}
});
}
};
});
const hapiChannelIntegration = core.defineIntegration(_hapiChannelIntegration);
exports.hapiChannelIntegration = hapiChannelIntegration;
//# sourceMappingURL=hapi.js.map
{"version":3,"file":"hapi.js","sources":["../../../../src/integrations/tracing-channel/hapi.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn } from '@sentry/core';\nimport { debug, defineIntegration } from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { wrapExtArguments, wrapRouteArguments } from './hapi-utils';\n\n// NOTE: same name as the OTel integration by design — when enabled, the OTel\n// 'Hapi' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Hapi' as const;\n\n/**\n * The shape orchestrion's transform attaches to the `@hapi/hapi` route/ext\n * tracing-channel `context` objects.\n *\n * `arguments` is the *live* args array passed to `server.route` / `server.ext`;\n * we mutate it in place to swap handlers for span-creating proxies. `self` is\n * the hapi server instance: the root server has `self.realm.plugin === undefined`,\n * while a plugin's clone server exposes the registering plugin's name there.\n */\ninterface HapiChannelContext {\n arguments: unknown[];\n self?: { realm?: { plugin?: string } };\n}\n\nconst _hapiChannelIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD &&\n debug.log(`[orchestrion:hapi] subscribing to channels \"${CHANNELS.HAPI_ROUTE}\" / \"${CHANNELS.HAPI_EXT}\"`);\n\n // `subscribe` requires all five lifecycle hooks. We only act on `start`,\n // which orchestrion fires synchronously with the live args array — that's\n // the moment we mutate the handlers in place.\n diagnosticsChannel.tracingChannel(CHANNELS.HAPI_ROUTE).subscribe({\n start(rawCtx) {\n const ctx = rawCtx as HapiChannelContext;\n wrapRouteArguments(ctx.arguments, ctx.self?.realm?.plugin);\n },\n end() {},\n asyncStart() {},\n asyncEnd() {},\n error() {},\n });\n\n diagnosticsChannel.tracingChannel(CHANNELS.HAPI_EXT).subscribe({\n start(rawCtx) {\n const ctx = rawCtx as HapiChannelContext;\n wrapExtArguments(ctx.arguments, ctx.self?.realm?.plugin);\n },\n end() {},\n asyncStart() {},\n asyncEnd() {},\n error() {},\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * EXPERIMENTAL — orchestrion-driven hapi integration. Subscribes to the\n * `orchestrion:@hapi/hapi:route` / `:ext` channels injected into `@hapi/hapi`'s\n * `lib/server.js`. Requires the orchestrion runtime hook or bundler plugin.\n */\nexport const hapiChannelIntegration = defineIntegration(_hapiChannelIntegration);\n"],"names":["DEBUG_BUILD","debug","CHANNELS","wrapRouteArguments","wrapExtArguments","defineIntegration"],"mappings":";;;;;;;;AASA,MAAM,gBAAA,GAAmB,MAAA;AAgBzB,MAAM,2BAA2B,MAAM;AACrC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,IAAI,CAAC,mBAAmB,cAAA,EAAgB;AACtC,QAAA;AAAA,MACF;AAEA,MAAAA,sBAAA,IACEC,UAAA,CAAM,IAAI,CAAA,4CAAA,EAA+CC,iBAAA,CAAS,UAAU,CAAA,KAAA,EAAQA,iBAAA,CAAS,QAAQ,CAAA,CAAA,CAAG,CAAA;AAK1G,MAAA,kBAAA,CAAmB,cAAA,CAAeA,iBAAA,CAAS,UAAU,CAAA,CAAE,SAAA,CAAU;AAAA,QAC/D,MAAM,MAAA,EAAQ;AACZ,UAAA,MAAM,GAAA,GAAM,MAAA;AACZ,UAAAC,4BAAA,CAAmB,GAAA,CAAI,SAAA,EAAW,GAAA,CAAI,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,QAC3D,CAAA;AAAA,QACA,GAAA,GAAM;AAAA,QAAC,CAAA;AAAA,QACP,UAAA,GAAa;AAAA,QAAC,CAAA;AAAA,QACd,QAAA,GAAW;AAAA,QAAC,CAAA;AAAA,QACZ,KAAA,GAAQ;AAAA,QAAC;AAAA,OACV,CAAA;AAED,MAAA,kBAAA,CAAmB,cAAA,CAAeD,iBAAA,CAAS,QAAQ,CAAA,CAAE,SAAA,CAAU;AAAA,QAC7D,MAAM,MAAA,EAAQ;AACZ,UAAA,MAAM,GAAA,GAAM,MAAA;AACZ,UAAAE,0BAAA,CAAiB,GAAA,CAAI,SAAA,EAAW,GAAA,CAAI,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,QACzD,CAAA;AAAA,QACA,GAAA,GAAM;AAAA,QAAC,CAAA;AAAA,QACP,UAAA,GAAa;AAAA,QAAC,CAAA;AAAA,QACd,QAAA,GAAW;AAAA,QAAC,CAAA;AAAA,QACZ,KAAA,GAAQ;AAAA,QAAC;AAAA,OACV,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAA,CAAA;AAOO,MAAM,sBAAA,GAAyBC,uBAAkB,uBAAuB;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const diagnosticsChannel = require('node:diagnostics_channel');
const attributes = require('@sentry/conventions/attributes');
const core = require('@sentry/core');
const debugBuild = require('../../debug-build.js');
const channels = require('../../orchestrion/channels.js');
const redisStatementSerializer = require('../../redis/redis-statement-serializer.js');
const tracingChannel = require('../../tracing-channel.js');
const INTEGRATION_NAME = "IORedis";
const ORIGIN = "auto.db.orchestrion.redis";
const ATTR_DB_CONNECTION_STRING = "db.connection_string";
function getConnectionOptions(self) {
return { host: self?.options?.host, port: self?.options?.port };
}
function connectionAttributes(host, port) {
return {
[attributes.DB_SYSTEM]: "redis",
[ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`,
[attributes.NET_PEER_NAME]: host,
[attributes.NET_PEER_PORT]: port,
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN
};
}
const _ioredisChannelIntegration = ((options = {}) => {
const responseHook = options.responseHook;
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
debugBuild.DEBUG_BUILD && core.debug.log(`[orchestrion:ioredis] subscribing to "${channels.CHANNELS.IOREDIS_COMMAND}"/"${channels.CHANNELS.IOREDIS_CONNECT}"`);
const commandChannel = diagnosticsChannel.tracingChannel(
channels.CHANNELS.IOREDIS_COMMAND
);
const connectChannel = diagnosticsChannel.tracingChannel(
channels.CHANNELS.IOREDIS_CONNECT
);
core.waitForTracingChannelBinding(() => {
tracingChannel.bindTracingChannelToSpan(
commandChannel,
(data) => {
if (!core.getActiveSpan()) {
return void 0;
}
const command = data.arguments?.[0];
if (!command || typeof command !== "object") {
return void 0;
}
const { host, port } = getConnectionOptions(data.self);
const statement = redisStatementSerializer.defaultDbStatementSerializer(command.name, command.args ?? []);
return core.startInactiveSpan({
name: statement,
op: "db",
attributes: { ...connectionAttributes(host, port), [attributes.DB_STATEMENT]: statement }
});
},
{
beforeSpanEnd(span, data) {
if ("error" in data || !responseHook) {
return;
}
const command = data.arguments?.[0];
if (command) {
runResponseHook(responseHook, span, command, data.result);
}
}
}
);
tracingChannel.bindTracingChannelToSpan(connectChannel, (data) => {
if (!core.getActiveSpan()) {
return void 0;
}
const { host, port } = getConnectionOptions(data.self);
return core.startInactiveSpan({
name: "connect",
op: "db",
attributes: { ...connectionAttributes(host, port), [attributes.DB_STATEMENT]: "connect" }
});
});
});
}
};
});
function runResponseHook(hook, span, command, result) {
try {
hook(span, command.name, command.args, result);
} catch {
}
}
const ioredisChannelIntegration = core.defineIntegration(_ioredisChannelIntegration);
exports.ioredisChannelIntegration = ioredisChannelIntegration;
//# sourceMappingURL=ioredis.js.map
{"version":3,"file":"ioredis.js","sources":["../../../../src/integrations/tracing-channel/ioredis.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-deprecated -- we intentionally emit the OLD db/net semconv\n to match `@opentelemetry/instrumentation-ioredis` (and Sentry's `inferDbSpanData`, which keys off\n `db.statement`). TODO(v11): switch to the non-deprecated `db.system.name`/`db.query.text`/\n `server.address`/`server.port` conventions and drop this disable. */\nimport * as diagnosticsChannel from 'node:diagnostics_channel';\nimport { DB_STATEMENT, DB_SYSTEM, NET_PEER_NAME, NET_PEER_PORT } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n debug,\n defineIntegration,\n getActiveSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { defaultDbStatementSerializer } from '../../redis/redis-statement-serializer';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// Distinct from the OTel `Redis` integration, which is composite (node-redis +\n// ioredis + the >=5.11.0 diagnostics_channel subscriber) and stays in the set;\n// only its ioredis monkey-patch is gated off in the node SDK when this is active.\nconst INTEGRATION_NAME = 'IORedis' as const;\n\nconst ORIGIN = 'auto.db.orchestrion.redis';\n\n// todo(v11): Let's drop this as this is already covered with host and port\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\n\n/** Mirrors `@opentelemetry/instrumentation-ioredis`' response hook. Not called for failed commands. */\nexport type IORedisResponseHook = (span: Span, command: string, args: Array<string | Buffer>, result: unknown) => void;\n\nexport interface IORedisChannelIntegrationOptions {\n responseHook?: IORedisResponseHook;\n}\n\n/** Structural type for the command object ioredis passes to `sendCommand`. */\ninterface RedisCommand {\n name: string;\n args: Array<string | Buffer>;\n}\n\ninterface RedisClientLike {\n options?: { host?: string; port?: number };\n}\n\ninterface IORedisCommandContext {\n arguments?: unknown[];\n self?: RedisClientLike;\n result?: unknown;\n error?: unknown;\n}\n\ntype IORedisConnectContext = Omit<IORedisCommandContext, 'arguments'>;\n\nfunction getConnectionOptions(self: RedisClientLike | undefined): { host?: string; port?: number } {\n return { host: self?.options?.host, port: self?.options?.port };\n}\n\nfunction connectionAttributes(host: string | undefined, port: number | undefined): Record<string, unknown> {\n return {\n [DB_SYSTEM]: 'redis',\n [ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`,\n [NET_PEER_NAME]: host,\n [NET_PEER_PORT]: port,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n };\n}\n\nconst _ioredisChannelIntegration = ((options: IORedisChannelIntegrationOptions = {}) => {\n const responseHook = options.responseHook;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD &&\n debug.log(`[orchestrion:ioredis] subscribing to \"${CHANNELS.IOREDIS_COMMAND}\"/\"${CHANNELS.IOREDIS_CONNECT}\"`);\n\n const commandChannel = diagnosticsChannel.tracingChannel<IORedisCommandContext, IORedisCommandContext>(\n CHANNELS.IOREDIS_COMMAND,\n );\n const connectChannel = diagnosticsChannel.tracingChannel<IORedisConnectContext, IORedisConnectContext>(\n CHANNELS.IOREDIS_CONNECT,\n );\n\n // `bindTracingChannelToSpan` uses `bindStore`, which needs the async-context\n // binding that `initOpenTelemetry()` registers after integration `setupOnce` —\n // defer until it's available (matches the native redis diagnostics-channel subscriber).\n waitForTracingChannelBinding(() => {\n bindTracingChannelToSpan(\n commandChannel,\n data => {\n // ioredis' `requireParentSpan` default: only create a span under an active span.\n if (!getActiveSpan()) {\n return undefined;\n }\n const command = data.arguments?.[0] as RedisCommand | undefined;\n if (!command || typeof command !== 'object') {\n return undefined;\n }\n const { host, port } = getConnectionOptions(data.self);\n const statement = defaultDbStatementSerializer(command.name, command.args ?? []);\n return startInactiveSpan({\n name: statement,\n op: 'db',\n attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: statement },\n });\n },\n {\n beforeSpanEnd(span, data) {\n if ('error' in data || !responseHook) {\n return;\n }\n const command = data.arguments?.[0] as RedisCommand | undefined;\n if (command) {\n runResponseHook(responseHook, span, command, data.result);\n }\n },\n },\n );\n\n bindTracingChannelToSpan(connectChannel, data => {\n if (!getActiveSpan()) {\n return undefined;\n }\n const { host, port } = getConnectionOptions(data.self);\n return startInactiveSpan({\n name: 'connect',\n op: 'db',\n attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: 'connect' },\n });\n });\n });\n },\n };\n}) satisfies IntegrationFn;\n\nfunction runResponseHook(hook: IORedisResponseHook, span: Span, command: RedisCommand, result: unknown): void {\n try {\n hook(span, command.name, command.args, result);\n } catch {\n // never let a user-provided response hook break instrumentation\n }\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven ioredis integration. Subscribes to\n * `orchestrion:ioredis:command` / `:connect` (injected into ioredis' `<5.11.0`\n * `sendCommand`/`connect`) and creates db spans matching\n * `@opentelemetry/instrumentation-ioredis`. Requires the orchestrion runtime hook\n * or bundler plugin.\n */\nexport const ioredisChannelIntegration = defineIntegration(_ioredisChannelIntegration);\n"],"names":["DB_SYSTEM","NET_PEER_NAME","NET_PEER_PORT","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","DEBUG_BUILD","debug","CHANNELS","waitForTracingChannelBinding","bindTracingChannelToSpan","getActiveSpan","defaultDbStatementSerializer","startInactiveSpan","DB_STATEMENT","defineIntegration"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const diagnosticsChannel = require('node:diagnostics_channel');
const core = require('@sentry/core');
const debugBuild = require('../../debug-build.js');
const channels = require('../../orchestrion/channels.js');
const tracingChannel = require('../../tracing-channel.js');
const INTEGRATION_NAME = "OpenAI";
const ORIGIN = "auto.ai.orchestrion.openai";
const INSTRUMENTED_CHANNELS = [
{ channel: channels.CHANNELS.OPENAI_CHAT, operation: "chat" },
{ channel: channels.CHANNELS.OPENAI_RESPONSES, operation: "chat" },
{ channel: channels.CHANNELS.OPENAI_EMBEDDINGS, operation: "embeddings" },
{ channel: channels.CHANNELS.OPENAI_CONVERSATIONS, operation: "chat" }
];
let subscribed = false;
const _openaiChannelIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel || subscribed) {
return;
}
subscribed = true;
core.waitForTracingChannelBinding(() => {
for (const { channel, operation } of INSTRUMENTED_CHANNELS) {
debugBuild.DEBUG_BUILD && core.debug.log(`[orchestrion:openai] subscribing to channel "${channel}"`);
tracingChannel.bindTracingChannelToSpan(
diagnosticsChannel.tracingChannel(channel),
(data) => createGenAiSpan(data, operation, options),
{
beforeSpanEnd: (span, data) => {
core.addOpenAiResponseAttributes(span, data.result, core.resolveAIRecordingOptions(options).recordOutputs);
},
// Streaming: the result is a `Stream` consumed later, so instrument it and let it end the span.
deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, options)
}
);
}
});
}
};
});
function createGenAiSpan(data, operation, options) {
if (core._INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {
return void 0;
}
const args = data.arguments ?? [];
const params = args[0];
const { recordInputs } = core.resolveAIRecordingOptions(options);
const enableTruncation = core.shouldEnableTruncation(options.enableTruncation);
const attributes = core.extractOpenAiRequestAttributes(args, operation);
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const model = params?.model || "unknown";
const span = core.startInactiveSpan({
name: `${operation} ${model}`,
op: `gen_ai.${operation}`,
attributes
});
if (recordInputs && params) {
core.addOpenAiRequestAttributes(span, params, operation, enableTruncation);
}
return span;
}
function isAsyncIterable(value) {
return !!value && typeof value[Symbol.asyncIterator] === "function";
}
function wrapStreamResult(span, data, options) {
const result = data.result;
if (!isAsyncIterable(result)) {
return false;
}
const { recordOutputs } = core.resolveAIRecordingOptions(options);
const iterate = result[Symbol.asyncIterator].bind(result);
const instrumented = core.instrumentOpenAiStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs ?? false);
result[Symbol.asyncIterator] = () => instrumented;
return true;
}
const openaiChannelIntegration = core.defineIntegration(_openaiChannelIntegration);
exports.openaiChannelIntegration = openaiChannelIntegration;
//# sourceMappingURL=openai.js.map
{"version":3,"file":"openai.js","sources":["../../../../src/integrations/tracing-channel/openai.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, OpenAiOptions, Span, SpanAttributeValue } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n addOpenAiRequestAttributes,\n addOpenAiResponseAttributes,\n debug,\n defineIntegration,\n extractOpenAiRequestAttributes,\n instrumentOpenAiStream,\n resolveAIRecordingOptions,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// Same name as the OTel integration by design: when enabled, the OTel 'OpenAI'\n// integration is dropped from the default set (see the Node opt-in loader).\nconst INTEGRATION_NAME = 'OpenAI' as const;\n\n// Distinct from the proxy's `auto.ai.openai` so spans from the orchestrion path\n// are attributable separately from the OTel/proxy one.\nconst ORIGIN = 'auto.ai.orchestrion.openai';\n\n// Each instrumented `create` method maps to the gen_ai operation its span reports.\nconst INSTRUMENTED_CHANNELS = [\n { channel: CHANNELS.OPENAI_CHAT, operation: 'chat' },\n { channel: CHANNELS.OPENAI_RESPONSES, operation: 'chat' },\n { channel: CHANNELS.OPENAI_EMBEDDINGS, operation: 'embeddings' },\n { channel: CHANNELS.OPENAI_CONVERSATIONS, operation: 'chat' },\n] as const;\n\n/**\n * The context object orchestrion shares across the tracing-channel lifecycle hooks: `arguments` is the\n * live args array passed to `Completions.create(body, options)`, and Node's `tracingChannel` attaches\n * `result` when the returned promise settles.\n */\ninterface OpenAiChatChannelContext {\n arguments: unknown[];\n result?: unknown;\n}\n\nlet subscribed = false;\n\nconst _openaiChannelIntegration = ((options: OpenAiOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19, and a second `init()` would double-subscribe.\n if (!diagnosticsChannel.tracingChannel || subscribed) {\n return;\n }\n subscribed = true;\n\n // `bindTracingChannelToSpan` needs the async-context binding that `initOpenTelemetry()` registers\n // after `setupOnce` runs, so wait for it before subscribing.\n waitForTracingChannelBinding(() => {\n for (const { channel, operation } of INSTRUMENTED_CHANNELS) {\n DEBUG_BUILD && debug.log(`[orchestrion:openai] subscribing to channel \"${channel}\"`);\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<OpenAiChatChannelContext>(channel),\n data => createGenAiSpan(data, operation, options),\n {\n beforeSpanEnd: (span, data) => {\n addOpenAiResponseAttributes(span, data.result, resolveAIRecordingOptions(options).recordOutputs);\n },\n // Streaming: the result is a `Stream` consumed later, so instrument it and let it end the span.\n deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, options),\n },\n );\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Build the span for an instrumented `create` call.\n * Returning `undefined` opts the payload out so no span is opened.\n */\nfunction createGenAiSpan(data: OpenAiChatChannelContext, operation: string, options: OpenAiOptions): Span | undefined {\n // langchain drives the openai SDK itself and instruments at its own layer; skip here to avoid double spans.\n if (_INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {\n return undefined;\n }\n\n const args = data.arguments ?? [];\n const params = args[0] as Record<string, unknown> | undefined;\n\n const { recordInputs } = resolveAIRecordingOptions(options);\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n\n const attributes = extractOpenAiRequestAttributes(args, operation);\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;\n const model = (params?.model as string) || 'unknown';\n\n const span = startInactiveSpan({\n name: `${operation} ${model}`,\n op: `gen_ai.${operation}`,\n attributes: attributes as Record<string, SpanAttributeValue>,\n });\n\n if (recordInputs && params) {\n addOpenAiRequestAttributes(span, params, operation, enableTruncation);\n }\n\n return span;\n}\n\ntype AsyncIterableStream = { [Symbol.asyncIterator]: () => AsyncIterator<unknown> };\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterableStream {\n return !!value && typeof (value as AsyncIterableStream)[Symbol.asyncIterator] === 'function';\n}\n\n/**\n * For a streaming `create({ stream: true })` the result is a `Stream` the caller consumes later. We can't\n * swap what `create` returns, but the `Stream` in `data.result` is the same instance the caller holds and\n * `asyncEnd` fires before the caller iterates — so we patch its async iterator in place to run through\n * `instrumentOpenAiStream`, which accumulates the streamed attributes and ends the span when iteration finishes.\n * Only a streaming call resolves to an async-iterable, so that check alone distinguishes it. Returns `true`\n * to hand span-ending ownership to `instrumentOpenAiStream`; `false` for non-streaming/errored results, which end\n * via the normal `beforeSpanEnd` path.\n */\nfunction wrapStreamResult(span: Span, data: OpenAiChatChannelContext, options: OpenAiOptions): boolean {\n const result = data.result;\n if (!isAsyncIterable(result)) {\n return false;\n }\n\n const { recordOutputs } = resolveAIRecordingOptions(options);\n const iterate = result[Symbol.asyncIterator].bind(result);\n const instrumented = instrumentOpenAiStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs ?? false);\n result[Symbol.asyncIterator] = () => instrumented;\n\n return true;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven OpenAI integration. Subscribes to the `orchestrion:openai:*`\n * diagnostics_channels injected into `openai`'s `create` methods (chat completions, responses, embeddings,\n * conversations), so it requires the orchestrion runtime hook or bundler plugin.\n */\nexport const openaiChannelIntegration = defineIntegration(_openaiChannelIntegration);\n"],"names":["CHANNELS","waitForTracingChannelBinding","DEBUG_BUILD","debug","bindTracingChannelToSpan","addOpenAiResponseAttributes","resolveAIRecordingOptions","_INTERNAL_shouldSkipAiProviderWrapping","shouldEnableTruncation","extractOpenAiRequestAttributes","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startInactiveSpan","addOpenAiRequestAttributes","instrumentOpenAiStream","defineIntegration"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const diagnosticsChannel = require('node:diagnostics_channel');
const core = require('@sentry/core');
const debugBuild = require('../../debug-build.js');
const channels = require('../../orchestrion/channels.js');
const tracingChannel = require('../../tracing-channel.js');
const INTEGRATION_NAME = "Postgres";
const ORIGIN = "auto.db.orchestrion.postgres";
const ATTR_DB_SYSTEM = "db.system";
const ATTR_DB_NAME = "db.name";
const ATTR_DB_CONNECTION_STRING = "db.connection_string";
const ATTR_DB_USER = "db.user";
const ATTR_DB_STATEMENT = "db.statement";
const ATTR_NET_PEER_NAME = "net.peer.name";
const ATTR_NET_PEER_PORT = "net.peer.port";
const ATTR_PG_PLAN = "db.postgresql.plan";
const ATTR_PG_IDLE_TIMEOUT = "db.postgresql.idle.timeout.millis";
const ATTR_PG_MAX_CLIENT = "db.postgresql.max.client";
const DB_SYSTEM_POSTGRESQL = "postgresql";
const SPAN_QUERY_FALLBACK = "pg.query";
const SPAN_CONNECT = "pg.connect";
const SPAN_POOL_CONNECT = "pg-pool.connect";
const _postgresChannelIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
core.waitForTracingChannelBinding(() => {
subscribeQueryLikeChannel(channels.CHANNELS.PG_QUERY, querySpanOptions, { deferStreamedResult: true });
if (!options.ignoreConnectSpans) {
subscribeQueryLikeChannel(channels.CHANNELS.PG_CONNECT, connectSpanOptions);
subscribeQueryLikeChannel(channels.CHANNELS.PGPOOL_CONNECT, poolConnectSpanOptions);
}
});
}
};
});
function subscribeQueryLikeChannel(channelName, getSpanOptions, { deferStreamedResult = false } = {}) {
debugBuild.DEBUG_BUILD && core.debug.log(`[orchestrion:pg] subscribing to channel "${channelName}"`);
tracingChannel.bindTracingChannelToSpan(
diagnosticsChannel.tracingChannel(channelName),
(data) => {
if (!core.getActiveSpan()) {
return void 0;
}
data._sentryCallerScope = core.getCurrentScope();
return core.startInactiveSpan({ ...getSpanOptions(data), kind: core.SPAN_KIND.CLIENT });
},
// `connect`/`pool-connect` resolve with a persistent `Client` (itself an
// `EventEmitter`), which is NOT a streamed result. Deferring their span
// to that emitter's `'end'`/`'error'` would keep it open for the whole
// connection lifetime, so it never ends in time and is dropped. Only
// `query` can return a streamable `Submittable`, so only it defers.
deferStreamedResult ? {
// Streamable `Submittable` (e.g. `client.query(new Query())`)
// returns an emitter that orchestrion stores on `ctx.result` while
// firing no async events; the query isn't done until the emitter
// emits `'end'`/`'error'`. Defer ending to those events for that
// path; the callback, promise, and sync-throw paths carry no
// emitter, so the helper ends the span as usual.
deferSpanEnd({ data, end }) {
const result = data.result;
if (!result || typeof result !== "object" || !hasOnMethod(result)) {
return false;
}
const callerScope = data._sentryCallerScope;
if (callerScope) {
core.bindScopeToEmitter(result, callerScope);
}
result.on("error", (err) => end(err));
result.on("end", () => end());
return true;
}
} : void 0
);
}
function querySpanOptions(ctx) {
const params = ctx.self?.connectionParameters ?? {};
const queryConfig = extractQueryConfig(ctx.arguments);
return {
// The description is the SQL statement
name: queryConfig?.text ?? SPAN_QUERY_FALLBACK,
op: "db",
attributes: {
...getConnectionAttributes(params),
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[ATTR_DB_STATEMENT]: queryConfig?.text || void 0,
[ATTR_PG_PLAN]: typeof queryConfig?.name === "string" ? queryConfig.name : void 0
}
};
}
function connectSpanOptions(ctx) {
const params = ctx.self?.connectionParameters ?? {};
return { name: SPAN_CONNECT, op: "db", attributes: getConnectionAttributes(params) };
}
function poolConnectSpanOptions(ctx) {
const opts = ctx.self?.options ?? {};
return { name: SPAN_POOL_CONNECT, op: "db", attributes: getPoolConnectionAttributes(opts) };
}
function hasOnMethod(obj) {
return "on" in obj && typeof obj.on === "function";
}
function extractQueryConfig(args) {
const arg0 = args[0];
if (typeof arg0 === "string") {
return { text: arg0 };
}
if (arg0 && typeof arg0 === "object" && typeof arg0.text === "string") {
const obj = arg0;
return { text: obj.text, name: obj.name };
}
return void 0;
}
function getConnectionAttributes(params) {
return {
[ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,
[ATTR_DB_CONNECTION_STRING]: getConnectionString(params),
[ATTR_DB_NAME]: params.database,
[ATTR_DB_USER]: params.user,
[ATTR_NET_PEER_NAME]: params.host,
[ATTR_NET_PEER_PORT]: Number.isInteger(params.port) ? params.port : void 0
};
}
function getPoolConnectionAttributes(opts) {
let url;
try {
url = opts.connectionString ? new URL(opts.connectionString) : void 0;
} catch {
url = void 0;
}
const database = url?.pathname.slice(1) || opts.database;
const host = url?.hostname || opts.host;
const port = Number(url?.port) || (Number.isInteger(opts.port) ? opts.port : void 0);
const user = url?.username || opts.user;
return {
[ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,
[ATTR_DB_CONNECTION_STRING]: getConnectionString(opts),
[ATTR_PG_IDLE_TIMEOUT]: opts.idleTimeoutMillis,
[ATTR_PG_MAX_CLIENT]: opts.max,
[ATTR_DB_NAME]: database,
[ATTR_NET_PEER_PORT]: port,
// these two come from a url parse and slice, can be ''
[ATTR_NET_PEER_NAME]: host || void 0,
[ATTR_DB_USER]: user || void 0
};
}
function getConnectionString(params) {
if (params.connectionString) {
try {
const url = new URL(params.connectionString);
url.username = "";
url.password = "";
return url.toString();
} catch {
return "postgresql://localhost:5432/";
}
}
const host = params.host || "localhost";
const port = params.port || 5432;
const database = params.database || "";
return `postgresql://${host}:${port}/${database}`;
}
const postgresChannelIntegration = core.defineIntegration(_postgresChannelIntegration);
exports.postgresChannelIntegration = postgresChannelIntegration;
//# sourceMappingURL=postgres.js.map
{"version":3,"file":"postgres.js","sources":["../../../../src/integrations/tracing-channel/postgres.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, Scope, SpanAttributes } from '@sentry/core';\nimport {\n bindScopeToEmitter,\n debug,\n defineIntegration,\n getActiveSpan,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// NOTE: this uses the same name as the OTel integration by design.\n// When enabled, the OTel 'Postgres' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Postgres' as const;\n\n// Only the query span carries an origin (the connect/pool-connect spans don't,\n// so they default to 'manual').\nconst ORIGIN = 'auto.db.orchestrion.postgres';\n\n// OpenTelemetry \"OLD\" db/net semantic-conventions, inlined to keep this\n// integration free of `@opentelemetry/*` deps.\nconst ATTR_DB_SYSTEM = 'db.system';\nconst ATTR_DB_NAME = 'db.name';\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nconst ATTR_DB_USER = 'db.user';\nconst ATTR_DB_STATEMENT = 'db.statement';\nconst ATTR_NET_PEER_NAME = 'net.peer.name';\nconst ATTR_NET_PEER_PORT = 'net.peer.port';\nconst ATTR_PG_PLAN = 'db.postgresql.plan';\nconst ATTR_PG_IDLE_TIMEOUT = 'db.postgresql.idle.timeout.millis';\nconst ATTR_PG_MAX_CLIENT = 'db.postgresql.max.client';\nconst DB_SYSTEM_POSTGRESQL = 'postgresql';\n\n// We set `op: 'db'` and the SQL description directly here (same as mysql\n// orchestrion) rather than relying on the OTel pipeline's `inferDbSpanData`\n// processor, which only runs in the node SDK, so setting them here is what\n// makes the spans correct on the other runtimes\n//\n// The user-visible span is identical to OTel: query spans are named after\n// `db.statement`; connect/pool-connect spans keep these names.\nconst SPAN_QUERY_FALLBACK = 'pg.query';\nconst SPAN_CONNECT = 'pg.connect';\nconst SPAN_POOL_CONNECT = 'pg-pool.connect';\n\n/**\n * The shape orchestrion's transform attaches to the tracing-channel `context`. Documented here rather\n * than imported because orchestrion's runtime doesn't export it.\n */\ninterface PgChannelContext {\n // The live args array passed to the wrapped `query`/`connect` call.\n arguments: unknown[];\n self?: unknown;\n result?: unknown;\n error?: unknown;\n // The caller's scope, captured at `start` and replayed onto a streamed `Submittable` emitter (see below).\n _sentryCallerScope?: Scope;\n}\n\ninterface PgConnectionParams {\n database?: string;\n host?: string;\n port?: number;\n user?: string;\n connectionString?: string;\n}\n\ninterface PgPoolOptions extends PgConnectionParams {\n idleTimeoutMillis?: number;\n // pg-pool stores the max pool size as `max` (defaulting it to 10 in its\n // constructor). The OTel pg instrumentation reads a `maxClient` field that\n // pg-pool never sets, so its `db.postgresql.max.client` attribute is always\n // dropped; we read the real `max` so the attribute is actually populated.\n max?: number;\n}\n\nconst _postgresChannelIntegration = ((options: { ignoreConnectSpans?: boolean } = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19 so do nothing in that case.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n waitForTracingChannelBinding(() => {\n // Query spans: `pg`/native `Client.prototype.query`. Only this channel can return a streamable\n // `Submittable` result, so it's the only one that defers span-ending to the emitter (see below).\n subscribeQueryLikeChannel(CHANNELS.PG_QUERY, querySpanOptions, { deferStreamedResult: true });\n\n // Connect spans, gated by `ignoreConnectSpans` (same as OTel pg).\n // `Client.prototype.connect` (pg + native)\n // and `Pool.prototype.connect` (pg-pool).\n if (!options.ignoreConnectSpans) {\n subscribeQueryLikeChannel(CHANNELS.PG_CONNECT, connectSpanOptions);\n subscribeQueryLikeChannel(CHANNELS.PGPOOL_CONNECT, poolConnectSpanOptions);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Subscribe to a pg tracing-channel and manage a span across its lifecycle.\n * Shared by the query/connect/pool-connect channels. They differ only in how\n * the span's name + attributes are built (`getSpanOptions`), and whether the\n * result can be a streamable emitter (`deferStreamedResult`, query-only).\n */\nfunction subscribeQueryLikeChannel(\n channelName: string,\n getSpanOptions: (ctx: PgChannelContext) => { name: string; op: string; attributes: SpanAttributes },\n { deferStreamedResult = false }: { deferStreamedResult?: boolean } = {},\n): void {\n DEBUG_BUILD && debug.log(`[orchestrion:pg] subscribing to channel \"${channelName}\"`);\n\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<PgChannelContext>(channelName),\n data => {\n // Only instrument when there's an active span; returning `undefined` opts this call out entirely,\n // leaving the active context untouched (e.g. connects issued during app startup).\n if (!getActiveSpan()) {\n return undefined;\n }\n\n // Capture the caller's scope while still synchronously inside the call, for the streamed path:\n // pg dispatches a `Submittable` emitter's events outside the original async scope, so `deferSpanEnd`\n // replays this scope onto that emitter.\n data._sentryCallerScope = getCurrentScope();\n\n // `kind: CLIENT` mirrors the OTel pg instrumentation, so the emitted\n // `otel.kind` matches across the OTel and diagnostics-channel paths.\n return startInactiveSpan({ ...getSpanOptions(data), kind: SPAN_KIND.CLIENT });\n },\n // `connect`/`pool-connect` resolve with a persistent `Client` (itself an\n // `EventEmitter`), which is NOT a streamed result. Deferring their span\n // to that emitter's `'end'`/`'error'` would keep it open for the whole\n // connection lifetime, so it never ends in time and is dropped. Only\n // `query` can return a streamable `Submittable`, so only it defers.\n deferStreamedResult\n ? {\n // Streamable `Submittable` (e.g. `client.query(new Query())`)\n // returns an emitter that orchestrion stores on `ctx.result` while\n // firing no async events; the query isn't done until the emitter\n // emits `'end'`/`'error'`. Defer ending to those events for that\n // path; the callback, promise, and sync-throw paths carry no\n // emitter, so the helper ends the span as usual.\n deferSpanEnd({ data, end }) {\n const result = data.result;\n if (!result || typeof result !== 'object' || !hasOnMethod(result)) {\n return false;\n }\n\n // Replay the caller's scope onto the emitter so listeners theu\n // user attaches after the call returns (and any spans they start)\n // nest under the caller, not a fresh root trace.\n const callerScope = data._sentryCallerScope;\n if (callerScope) {\n bindScopeToEmitter(result, callerScope);\n }\n\n result.on('error', err => end(err));\n result.on('end', () => end());\n\n return true;\n },\n }\n : undefined,\n );\n}\n\nfunction querySpanOptions(ctx: PgChannelContext): { name: string; op: string; attributes: SpanAttributes } {\n const params = (ctx.self as { connectionParameters?: PgConnectionParams } | undefined)?.connectionParameters ?? {};\n const queryConfig = extractQueryConfig(ctx.arguments);\n return {\n // The description is the SQL statement\n name: queryConfig?.text ?? SPAN_QUERY_FALLBACK,\n op: 'db',\n attributes: {\n ...getConnectionAttributes(params),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [ATTR_DB_STATEMENT]: queryConfig?.text || undefined,\n [ATTR_PG_PLAN]: typeof queryConfig?.name === 'string' ? queryConfig.name : undefined,\n },\n };\n}\n\nfunction connectSpanOptions(ctx: PgChannelContext): { name: string; op: string; attributes: SpanAttributes } {\n const params = (ctx.self as { connectionParameters?: PgConnectionParams } | undefined)?.connectionParameters ?? {};\n // No origin set -> defaults to 'manual'\n return { name: SPAN_CONNECT, op: 'db', attributes: getConnectionAttributes(params) };\n}\n\nfunction poolConnectSpanOptions(ctx: PgChannelContext): { name: string; op: string; attributes: SpanAttributes } {\n const opts = (ctx.self as { options?: PgPoolOptions } | undefined)?.options ?? {};\n return { name: SPAN_POOL_CONNECT, op: 'db', attributes: getPoolConnectionAttributes(opts) };\n}\n\nfunction hasOnMethod(obj: object): obj is { on: (event: string, listener: (arg?: unknown) => void) => unknown } {\n return 'on' in obj && typeof (obj as { on?: unknown }).on === 'function';\n}\n\n// `client.query(text, cb?)`, `client.query(text, values, cb?)`, and\n// `client.query(configObj, cb?)` are all valid; normalize to `{ text, name }`\n// (the only fields the span needs). Returns undefined for invalid args.\nfunction extractQueryConfig(args: unknown[]): { text: string; name?: unknown } | undefined {\n const arg0 = args[0];\n if (typeof arg0 === 'string') {\n return { text: arg0 };\n }\n if (arg0 && typeof arg0 === 'object' && typeof (arg0 as { text?: unknown }).text === 'string') {\n const obj = arg0 as { text: string; name?: unknown };\n return { text: obj.text, name: obj.name };\n }\n return undefined;\n}\n\nfunction getConnectionAttributes(params: PgConnectionParams): SpanAttributes {\n return {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),\n [ATTR_DB_NAME]: params.database,\n [ATTR_DB_USER]: params.user,\n [ATTR_NET_PEER_NAME]: params.host,\n [ATTR_NET_PEER_PORT]: Number.isInteger(params.port) ? params.port : undefined,\n };\n}\n\nfunction getPoolConnectionAttributes(opts: PgPoolOptions): SpanAttributes {\n let url: URL | undefined;\n try {\n url = opts.connectionString ? new URL(opts.connectionString) : undefined;\n } catch {\n url = undefined;\n }\n const database = url?.pathname.slice(1) || opts.database;\n const host = url?.hostname || opts.host;\n // Mirror OTel's `getSemanticAttributesFromPoolConnection`: prefer the URL's\n // port, but fall back to an explicit `opts.port` when the connection string\n // omits it (`Number('')` / `Number(undefined)` -> falsy).\n const port = Number(url?.port) || (Number.isInteger(opts.port) ? opts.port : undefined);\n const user = url?.username || opts.user;\n return {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(opts),\n [ATTR_PG_IDLE_TIMEOUT]: opts.idleTimeoutMillis,\n [ATTR_PG_MAX_CLIENT]: opts.max,\n [ATTR_DB_NAME]: database,\n [ATTR_NET_PEER_PORT]: port,\n // these two come from a url parse and slice, can be ''\n [ATTR_NET_PEER_NAME]: host || undefined,\n [ATTR_DB_USER]: user || undefined,\n };\n}\n\n// Builds `postgresql://host:port/database`, masking credentials when a raw\n// connection string was provided.\nfunction getConnectionString(params: PgConnectionParams): string {\n if (params.connectionString) {\n try {\n const url = new URL(params.connectionString);\n url.username = '';\n url.password = '';\n return url.toString();\n } catch {\n return 'postgresql://localhost:5432/';\n }\n }\n const host = params.host || 'localhost';\n const port = params.port || 5432;\n const database = params.database || '';\n return `postgresql://${host}:${port}/${database}`;\n}\n\n/**\n * EXPERIMENTAL: orchestrion-driven `pg` (node-postgres) integration.\n *\n * Subscribes to the `orchestrion:pg:query`/`:connect` and\n * `orchestrion:pg-pool:connect` diagnostics_channels that the orchestrion code\n * transform injects into `pg`'s `Client.prototype.query`/`connect`\n * and `pg-pool`'s `Pool.prototype.connect`. Requires the orchestrion runtime\n * hook or bundler plugin to be active.\n */\nexport const postgresChannelIntegration = defineIntegration(_postgresChannelIntegration);\n"],"names":["waitForTracingChannelBinding","CHANNELS","DEBUG_BUILD","debug","bindTracingChannelToSpan","getActiveSpan","getCurrentScope","startInactiveSpan","SPAN_KIND","bindScopeToEmitter","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","defineIntegration"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const core = require('@sentry/core');
const index = require('../../vercel-ai/index.js');
const diagnosticsChannel = require('node:diagnostics_channel');
const vercelAiOrchestrionV6Subscriber = require('../../vercel-ai/vercel-ai-orchestrion-v6-subscriber.js');
const _vercelAiChannelIntegration = ((options = {}) => {
const parentIntegration = index.vercelAiIntegration(options);
return core.extendIntegration(parentIntegration, {
options,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
core.waitForTracingChannelBinding(() => {
vercelAiOrchestrionV6Subscriber.subscribeVercelAiOrchestrionChannels(diagnosticsChannel.tracingChannel, options);
});
}
});
});
const vercelAiChannelIntegration = core.defineIntegration(_vercelAiChannelIntegration);
exports.vercelAiChannelIntegration = vercelAiChannelIntegration;
//# sourceMappingURL=vercel-ai.js.map
{"version":3,"file":"vercel-ai.js","sources":["../../../../src/integrations/tracing-channel/vercel-ai.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration, extendIntegration, waitForTracingChannelBinding } from '@sentry/core';\nimport { vercelAiIntegration as baseVercelAiIntegration } from '../../vercel-ai';\nimport * as dc from 'node:diagnostics_channel';\nimport { subscribeVercelAiOrchestrionChannels } from '../../vercel-ai/vercel-ai-orchestrion-v6-subscriber';\n\ntype VercelAiOptions = Parameters<typeof baseVercelAiIntegration>[0];\n\n// In channel-based (orchestrion) mode we emit our own `gen_ai.*` spans from the\n// diagnostics channels. The `ai` SDK would otherwise emit its own native\n// OpenTelemetry spans whenever the user enables `experimental_telemetry`, which\n// would be duplicates. Rather than dropping those after the fact, the v6\n// subscriber suppresses them at the source: it flips the wrapped call's\n// `experimental_telemetry.isEnabled` to `false`, so `ai` falls back to its\n// internal no-op tracer and never creates the native spans in the first place.\n// See `subscribeVercelAiOrchestrionChannels`.\nconst _vercelAiChannelIntegration = ((options: VercelAiOptions = {}) => {\n const parentIntegration = baseVercelAiIntegration(options);\n\n return extendIntegration(parentIntegration, {\n options,\n setupOnce() {\n // Bail if this is not available\n if (!dc.tracingChannel) {\n return;\n }\n\n waitForTracingChannelBinding(() => {\n subscribeVercelAiOrchestrionChannels(dc.tracingChannel, options);\n });\n },\n });\n}) satisfies IntegrationFn;\n\n/**\n * Auto-instrument the `ai` SDK. Supported are:\n * - v7 via native `ai:telemetry` tracing channel\n * - v6 via orchestrion `orchestrion:ai:*` channels\n */\nexport const vercelAiChannelIntegration = defineIntegration(_vercelAiChannelIntegration);\n"],"names":["baseVercelAiIntegration","extendIntegration","dc","waitForTracingChannelBinding","subscribeVercelAiOrchestrionChannels","defineIntegration"],"mappings":";;;;;;;AAgBA,MAAM,2BAAA,IAA+B,CAAC,OAAA,GAA2B,EAAC,KAAM;AACtE,EAAA,MAAM,iBAAA,GAAoBA,0BAAwB,OAAO,CAAA;AAEzD,EAAA,OAAOC,uBAAkB,iBAAA,EAAmB;AAAA,IAC1C,OAAA;AAAA,IACA,SAAA,GAAY;AAEV,MAAA,IAAI,CAACC,mBAAG,cAAA,EAAgB;AACtB,QAAA;AAAA,MACF;AAEA,MAAAC,iCAAA,CAA6B,MAAM;AACjC,QAAAC,oEAAA,CAAqCF,kBAAA,CAAG,gBAAgB,OAAO,CAAA;AAAA,MACjE,CAAC,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH,CAAA,CAAA;AAOO,MAAM,0BAAA,GAA6BG,uBAAkB,2BAA2B;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const core = require('@sentry/core');
const diagnosticsChannel = require('node:diagnostics_channel');
const mongooseDcSubscriber = require('./mongoose-dc-subscriber.js');
const _mongooseIntegration = (() => {
return {
name: "Mongoose",
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
core.waitForTracingChannelBinding(() => {
mongooseDcSubscriber.subscribeMongooseDiagnosticChannels(diagnosticsChannel.tracingChannel);
});
}
};
});
const mongooseIntegration = core.defineIntegration(_mongooseIntegration);
exports.mongooseIntegration = mongooseIntegration;
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../../src/mongoose/index.ts"],"sourcesContent":["import { defineIntegration, type IntegrationFn, waitForTracingChannelBinding } from '@sentry/core';\nimport * as dc from 'node:diagnostics_channel';\nimport { subscribeMongooseDiagnosticChannels } from './mongoose-dc-subscriber';\n\nconst _mongooseIntegration = (() => {\n return {\n name: 'Mongoose',\n setupOnce() {\n // Bail on Node <= 18.18.0, where `tracingChannel` does not exist.\n if (!dc.tracingChannel) {\n return;\n }\n\n // Subscribe to mongoose's native tracing channels (mongoose >= 9.7).\n // This is a no-op on versions that don't publish to the channels, so it is always safe to call.\n waitForTracingChannelBinding(() => {\n subscribeMongooseDiagnosticChannels(dc.tracingChannel);\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Auto-instrument the [mongoose](https://www.npmjs.com/package/mongoose) library via its native\n * `node:diagnostics_channel` tracing channels (mongoose >= 9.7).\n *\n * On older mongoose versions the channels are never published to, so this integration is inert and\n * the IITM-based patcher (gated to `< 9.7.0`) handles instrumentation instead.\n */\nexport const mongooseIntegration = defineIntegration(_mongooseIntegration);\n"],"names":["dc","waitForTracingChannelBinding","subscribeMongooseDiagnosticChannels","defineIntegration"],"mappings":";;;;;;AAIA,MAAM,wBAAwB,MAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,SAAA,GAAY;AAEV,MAAA,IAAI,CAACA,mBAAG,cAAA,EAAgB;AACtB,QAAA;AAAA,MACF;AAIA,MAAAC,iCAAA,CAA6B,MAAM;AACjC,QAAAC,wDAAA,CAAoCF,mBAAG,cAAc,CAAA;AAAA,MACvD,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAA,CAAA;AASO,MAAM,mBAAA,GAAsBG,uBAAkB,oBAAoB;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const attributes = require('@sentry/conventions/attributes');
const core = require('@sentry/core');
const debugBuild = require('../debug-build.js');
const tracingChannel = require('../tracing-channel.js');
const MONGOOSE_DC_CHANNEL_QUERY = "mongoose:query";
const MONGOOSE_DC_CHANNEL_AGGREGATE = "mongoose:aggregate";
const MONGOOSE_DC_CHANNEL_MODEL_SAVE = "mongoose:model:save";
const MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = "mongoose:model:insertMany";
const MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = "mongoose:model:bulkWrite";
const MONGOOSE_DC_CHANNEL_CURSOR_NEXT = "mongoose:cursor:next";
const ORIGIN = "auto.db.mongoose.diagnostic_channel";
const DB_SYSTEM_NAME_VALUE_MONGODB = "mongodb";
const MAX_REDACTION_DEPTH = 10;
let subscribed = false;
function subscribeMongooseDiagnosticChannels(tracingChannel) {
if (subscribed) {
return;
}
subscribed = true;
try {
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_QUERY);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_AGGREGATE);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_SAVE);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_CURSOR_NEXT);
} catch {
debugBuild.DEBUG_BUILD && core.debug.log("Mongoose node:diagnostics_channel subscription failed.");
}
}
function setupChannel(tracingChannel$1, channelName) {
tracingChannel.bindTracingChannelToSpan(tracingChannel$1(channelName), (data) => {
const collection = data.collection;
const queryText = redactMongoQuery(data.args?.pipeline ?? data.args?.filter);
const batchSize = getBatchSize(data);
return core.startInactiveSpan({
name: collection ? `mongoose.${collection}.${data.operation}` : `mongoose.${data.operation}`,
attributes: {
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "db",
[attributes.DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_MONGODB,
[attributes.DB_OPERATION_NAME]: data.operation,
[attributes.DB_COLLECTION_NAME]: collection ?? void 0,
[attributes.DB_NAMESPACE]: data.database ?? void 0,
[attributes.DB_QUERY_TEXT]: queryText ?? void 0,
[attributes.DB_OPERATION_BATCH_SIZE]: batchSize ?? void 0,
[attributes.SERVER_ADDRESS]: data.serverAddress ?? void 0,
[attributes.SERVER_PORT]: data.serverPort ?? void 0
}
});
});
}
function getBatchSize(data) {
const args = data.args;
const batch = data.operation === "insertMany" ? args?.docs : data.operation === "bulkWrite" ? args?.ops : void 0;
return Array.isArray(batch) && batch.length > 1 ? batch.length : void 0;
}
function redactMongoQuery(value) {
if (value == null) {
return void 0;
}
try {
const redacted = redactValue(value, 0);
const text = JSON.stringify(redacted);
return text == null || text === "{}" || text === "[]" ? void 0 : text;
} catch {
return void 0;
}
}
function redactValue(value, depth) {
if (depth > MAX_REDACTION_DEPTH) {
return "?";
}
if (Array.isArray(value)) {
return value.map((item) => redactValue(item, depth + 1));
}
if (value && typeof value === "object") {
const out = {};
for (const key of Object.keys(value)) {
out[key] = redactValue(value[key], depth + 1);
}
return out;
}
return "?";
}
exports.MONGOOSE_DC_CHANNEL_AGGREGATE = MONGOOSE_DC_CHANNEL_AGGREGATE;
exports.MONGOOSE_DC_CHANNEL_CURSOR_NEXT = MONGOOSE_DC_CHANNEL_CURSOR_NEXT;
exports.MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE;
exports.MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY;
exports.MONGOOSE_DC_CHANNEL_MODEL_SAVE = MONGOOSE_DC_CHANNEL_MODEL_SAVE;
exports.MONGOOSE_DC_CHANNEL_QUERY = MONGOOSE_DC_CHANNEL_QUERY;
exports.subscribeMongooseDiagnosticChannels = subscribeMongooseDiagnosticChannels;
//# sourceMappingURL=mongoose-dc-subscriber.js.map
{"version":3,"file":"mongoose-dc-subscriber.js","sources":["../../../src/mongoose/mongoose-dc-subscriber.ts"],"sourcesContent":["import type { TracingChannel } from 'node:diagnostics_channel';\nimport {\n DB_COLLECTION_NAME,\n DB_NAMESPACE,\n DB_OPERATION_BATCH_SIZE,\n DB_OPERATION_NAME,\n DB_QUERY_TEXT,\n DB_SYSTEM_NAME,\n SERVER_ADDRESS,\n SERVER_PORT,\n} from '@sentry/conventions/attributes';\nimport { debug, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { bindTracingChannelToSpan } from '../tracing-channel';\n\n// Channel names published by mongoose >= 9.7.0 (see mongoose `lib/tracing.js`,\n// `lib/query.js`, `lib/aggregate.js`, `lib/model.js` and `lib/cursor/*`).\n// Hardcoded so the subscriber does not have to import mongoose — the channels\n// just have to be subscribed to before the user's mongoose code publishes.\nexport const MONGOOSE_DC_CHANNEL_QUERY = 'mongoose:query';\nexport const MONGOOSE_DC_CHANNEL_AGGREGATE = 'mongoose:aggregate';\nexport const MONGOOSE_DC_CHANNEL_MODEL_SAVE = 'mongoose:model:save';\nexport const MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = 'mongoose:model:insertMany';\nexport const MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = 'mongoose:model:bulkWrite';\nexport const MONGOOSE_DC_CHANNEL_CURSOR_NEXT = 'mongoose:cursor:next';\n\nconst ORIGIN = 'auto.db.mongoose.diagnostic_channel';\nconst DB_SYSTEM_NAME_VALUE_MONGODB = 'mongodb';\n\n// Cap recursion so a self-referential or pathologically deep query can never\n// stall (or blow the stack in) instrumentation.\nconst MAX_REDACTION_DEPTH = 10;\n\n/**\n * Shape of the context object mongoose >= 9.7.0 publishes on its tracing\n * channels (mongoose's `TracingContext`, see `types/tracing.d.ts`).\n *\n * Node's `tracePromise` mutates this same object with `result`/`error` once the\n * operation settles, which `bindTracingChannelToSpan` reads in its lifecycle\n * handlers — hence both are declared optional here.\n *\n * Unlike redis/ioredis, mongoose does NOT pre-sanitize the payload, so `args`\n * carries the raw user query. We redact it before emitting `db.query.text`.\n */\nexport interface MongooseTracingData {\n operation: string;\n /** Absent for connection-level `aggregate()` calls, which have no model/collection. */\n collection?: string;\n database?: string;\n serverAddress?: string;\n serverPort?: number;\n /** Cursor channels only: the cursor's fetch batch size and tailable flag. */\n batchSize?: number;\n tailable?: boolean;\n /**\n * Operation-specific arguments. `filter` (queries/cursors) and `pipeline`\n * (aggregations) carry the query shape; `docs`/`ops` carry batch payloads.\n */\n args?: {\n filter?: unknown;\n pipeline?: unknown;\n docs?: unknown;\n ops?: unknown;\n [key: string]: unknown;\n };\n result?: unknown;\n error?: Error;\n}\n\n/**\n * Platform-provided factory that creates a native tracing channel for the given name. The\n * subscriber binds the span and its lifecycle onto the channel via `bindTracingChannelToSpan`,\n * which propagates the active span through the runtime's async context.\n *\n * Node passes `node:diagnostics_channel`'s `tracingChannel` directly.\n */\nexport type MongooseTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;\n\nlet subscribed = false;\n\n/**\n * Subscribe Sentry span handlers to mongoose's diagnostics-channel events\n * (`mongoose:query`, `:aggregate`, `:model:save`, `:model:insertMany`,\n * `:model:bulkWrite`, `:cursor:next`), published by mongoose >= 9.7.0.\n *\n * On older mongoose versions the channels are never published to, so the\n * subscribers are inert — there is no double-instrumentation against the\n * IITM-based vendored patcher, which is gated to `< 9.7.0`.\n *\n * Idempotent: subsequent calls are a no-op.\n */\nexport function subscribeMongooseDiagnosticChannels(tracingChannel: MongooseTracingChannelFactory): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n try {\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_QUERY);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_AGGREGATE);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_SAVE);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_CURSOR_NEXT);\n } catch {\n // The factory relies on `node:diagnostics_channel`, which isn't always\n // available. Fail closed; the SDK simply won't emit mongoose spans here.\n DEBUG_BUILD && debug.log('Mongoose node:diagnostics_channel subscription failed.');\n }\n}\n\nfunction setupChannel(tracingChannel: MongooseTracingChannelFactory, channelName: string): void {\n bindTracingChannelToSpan(tracingChannel<MongooseTracingData>(channelName), data => {\n const collection = data.collection;\n const queryText = redactMongoQuery(data.args?.pipeline ?? data.args?.filter);\n const batchSize = getBatchSize(data);\n\n return startInactiveSpan({\n name: collection ? `mongoose.${collection}.${data.operation}` : `mongoose.${data.operation}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db',\n [DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_MONGODB,\n [DB_OPERATION_NAME]: data.operation,\n [DB_COLLECTION_NAME]: collection ?? undefined,\n [DB_NAMESPACE]: data.database ?? undefined,\n [DB_QUERY_TEXT]: queryText ?? undefined,\n [DB_OPERATION_BATCH_SIZE]: batchSize ?? undefined,\n [SERVER_ADDRESS]: data.serverAddress ?? undefined,\n [SERVER_PORT]: data.serverPort ?? undefined,\n },\n });\n });\n}\n\n/**\n * `db.operation.batch.size` is only meaningful for genuine batch operations.\n * Mongoose's cursor `batchSize` is a fetch-tuning option, not a batch operation\n * size, so it is intentionally excluded here.\n */\nfunction getBatchSize(data: MongooseTracingData): number | undefined {\n const args = data.args;\n const batch = data.operation === 'insertMany' ? args?.docs : data.operation === 'bulkWrite' ? args?.ops : undefined;\n\n return Array.isArray(batch) && batch.length > 1 ? batch.length : undefined;\n}\n\n/**\n * Serialize a mongoose filter/pipeline into `db.query.text` while stripping every\n * value: keys and Mongo operators (`$gt`, `$in`, …) are preserved, leaf values\n * become `'?'`. Mongoose does not sanitize its channel payload, so this prevents\n * raw user data (potential PII) from leaving the process. Returns `undefined`\n * (rather than throwing) on anything it cannot serialize.\n */\nfunction redactMongoQuery(value: unknown): string | undefined {\n if (value == null) {\n return undefined;\n }\n\n try {\n const redacted = redactValue(value, 0);\n const text = JSON.stringify(redacted);\n\n // Skip empty/uninformative shapes (e.g. a `findOne()` with no filter).\n return text == null || text === '{}' || text === '[]' ? undefined : text;\n } catch {\n return undefined;\n }\n}\n\nfunction redactValue(value: unknown, depth: number): unknown {\n if (depth > MAX_REDACTION_DEPTH) {\n return '?';\n }\n\n if (Array.isArray(value)) {\n return value.map(item => redactValue(item, depth + 1));\n }\n\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n out[key] = redactValue((value as Record<string, unknown>)[key], depth + 1);\n }\n\n return out;\n }\n\n return '?';\n}\n"],"names":["DEBUG_BUILD","debug","tracingChannel","bindTracingChannelToSpan","startInactiveSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","DB_SYSTEM_NAME","DB_OPERATION_NAME","DB_COLLECTION_NAME","DB_NAMESPACE","DB_QUERY_TEXT","DB_OPERATION_BATCH_SIZE","SERVER_ADDRESS","SERVER_PORT"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const anthropicAiConfig = [
// One entry each for CJS/ESM
...["resources/messages/messages.js", "resources/messages/messages.mjs"].flatMap(
(filePath) => ["create", "countTokens"].map((methodName) => ({
channelName: "chat",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Messages", methodName, kind: "Auto" }
}))
),
...["resources/completions.js", "resources/completions.mjs"].map((filePath) => ({
channelName: "chat",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Completions", methodName: "create", kind: "Auto" }
})),
...["resources/beta/messages/messages.js", "resources/beta/messages/messages.mjs"].map((filePath) => ({
channelName: "chat",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Messages", methodName: "create", kind: "Auto" }
})),
...["resources/models.js", "resources/models.mjs"].map((filePath) => ({
channelName: "models",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Models", methodName: "retrieve", kind: "Auto" }
})),
// `messages.stream()` returns a synchronous emitter, not a promise, so `kind: 'Sync'` is required:
// `Auto`'s promise wrapper never publishes `end` for a non-thenable return, so the span would never end.
...["resources/messages/messages.js", "resources/messages/messages.mjs"].map((filePath) => ({
channelName: "messages-stream",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Messages", methodName: "stream", kind: "Sync" }
}))
];
const anthropicAiChannels = {
ANTHROPIC_CHAT: "orchestrion:@anthropic-ai/sdk:chat",
ANTHROPIC_MODELS: "orchestrion:@anthropic-ai/sdk:models",
ANTHROPIC_MESSAGES_STREAM: "orchestrion:@anthropic-ai/sdk:messages-stream"
};
exports.anthropicAiChannels = anthropicAiChannels;
exports.anthropicAiConfig = anthropicAiConfig;
//# sourceMappingURL=anthropic-ai.js.map
{"version":3,"file":"anthropic-ai.js","sources":["../../../../src/orchestrion/config/anthropic-ai.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const anthropicAiConfig = [\n // One entry each for CJS/ESM\n ...['resources/messages/messages.js', 'resources/messages/messages.mjs'].flatMap(filePath =>\n (['create', 'countTokens'] as const).map(methodName => ({\n channelName: 'chat',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Messages', methodName, kind: 'Auto' as const },\n })),\n ),\n ...['resources/completions.js', 'resources/completions.mjs'].map(filePath => ({\n channelName: 'chat',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Completions', methodName: 'create', kind: 'Auto' as const },\n })),\n ...['resources/beta/messages/messages.js', 'resources/beta/messages/messages.mjs'].map(filePath => ({\n channelName: 'chat',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Messages', methodName: 'create', kind: 'Auto' as const },\n })),\n ...['resources/models.js', 'resources/models.mjs'].map(filePath => ({\n channelName: 'models',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Models', methodName: 'retrieve', kind: 'Auto' as const },\n })),\n // `messages.stream()` returns a synchronous emitter, not a promise, so `kind: 'Sync'` is required:\n // `Auto`'s promise wrapper never publishes `end` for a non-thenable return, so the span would never end.\n ...['resources/messages/messages.js', 'resources/messages/messages.mjs'].map(filePath => ({\n channelName: 'messages-stream',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Messages', methodName: 'stream', kind: 'Sync' as const },\n })),\n] satisfies InstrumentationConfig[];\n\nexport const anthropicAiChannels = {\n ANTHROPIC_CHAT: 'orchestrion:@anthropic-ai/sdk:chat',\n ANTHROPIC_MODELS: 'orchestrion:@anthropic-ai/sdk:models',\n ANTHROPIC_MESSAGES_STREAM: 'orchestrion:@anthropic-ai/sdk:messages-stream',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,iBAAA,GAAoB;AAAA;AAAA,EAE/B,GAAG,CAAC,gCAAA,EAAkC,iCAAiC,CAAA,CAAE,OAAA;AAAA,IAAQ,cAC9E,CAAC,QAAA,EAAU,aAAa,CAAA,CAAY,IAAI,CAAA,UAAA,MAAe;AAAA,MACtD,WAAA,EAAa,MAAA;AAAA,MACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,MAC3E,eAAe,EAAE,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,MAAM,MAAA;AAAgB,KAC5E,CAAE;AAAA,GACJ;AAAA,EACA,GAAG,CAAC,0BAAA,EAA4B,2BAA2B,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC5E,WAAA,EAAa,MAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,eAAe,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACzF,CAAE,CAAA;AAAA,EACF,GAAG,CAAC,qCAAA,EAAuC,sCAAsC,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAClG,WAAA,EAAa,MAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,YAAY,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACtF,CAAE,CAAA;AAAA,EACF,GAAG,CAAC,qBAAA,EAAuB,sBAAsB,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAClE,WAAA,EAAa,QAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,UAAU,UAAA,EAAY,UAAA,EAAY,MAAM,MAAA;AAAgB,GACtF,CAAE,CAAA;AAAA;AAAA;AAAA,EAGF,GAAG,CAAC,gCAAA,EAAkC,iCAAiC,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IACxF,WAAA,EAAa,iBAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,YAAY,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACtF,CAAE;AACJ;AAEO,MAAM,mBAAA,GAAsB;AAAA,EACjC,cAAA,EAAgB,oCAAA;AAAA,EAChB,gBAAA,EAAkB,sCAAA;AAAA,EAClB,yBAAA,EAA2B;AAC7B;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const hapiConfig = [
// hapi's `route`/`ext` live on an anonymous class (`internals.Server = class {}`),
// so `{className}` can't match — `{methodName}` targets them in lib/server.js. Both
// are synchronous void methods, so `Sync` suffices: we only use `start` to swap
// handlers in `ctx.arguments`. Shape verified across the whole range.
{
channelName: "route",
module: { name: "@hapi/hapi", versionRange: ">=17.0.0 <22.0.0", filePath: "lib/server.js" },
functionQuery: { methodName: "route", kind: "Sync" }
},
{
channelName: "ext",
module: { name: "@hapi/hapi", versionRange: ">=17.0.0 <22.0.0", filePath: "lib/server.js" },
functionQuery: { methodName: "ext", kind: "Sync" }
}
];
const hapiChannels = {
HAPI_ROUTE: "orchestrion:@hapi/hapi:route",
HAPI_EXT: "orchestrion:@hapi/hapi:ext"
};
exports.hapiChannels = hapiChannels;
exports.hapiConfig = hapiConfig;
//# sourceMappingURL=hapi.js.map
{"version":3,"file":"hapi.js","sources":["../../../../src/orchestrion/config/hapi.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const hapiConfig = [\n // hapi's `route`/`ext` live on an anonymous class (`internals.Server = class {}`),\n // so `{className}` can't match — `{methodName}` targets them in lib/server.js. Both\n // are synchronous void methods, so `Sync` suffices: we only use `start` to swap\n // handlers in `ctx.arguments`. Shape verified across the whole range.\n {\n channelName: 'route',\n module: { name: '@hapi/hapi', versionRange: '>=17.0.0 <22.0.0', filePath: 'lib/server.js' },\n functionQuery: { methodName: 'route', kind: 'Sync' },\n },\n {\n channelName: 'ext',\n module: { name: '@hapi/hapi', versionRange: '>=17.0.0 <22.0.0', filePath: 'lib/server.js' },\n functionQuery: { methodName: 'ext', kind: 'Sync' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const hapiChannels = {\n HAPI_ROUTE: 'orchestrion:@hapi/hapi:route',\n HAPI_EXT: 'orchestrion:@hapi/hapi:ext',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,cAAc,YAAA,EAAc,kBAAA,EAAoB,UAAU,eAAA,EAAgB;AAAA,IAC1F,aAAA,EAAe,EAAE,UAAA,EAAY,OAAA,EAAS,MAAM,MAAA;AAAO,GACrD;AAAA,EACA;AAAA,IACE,WAAA,EAAa,KAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,cAAc,YAAA,EAAc,kBAAA,EAAoB,UAAU,eAAA,EAAgB;AAAA,IAC1F,aAAA,EAAe,EAAE,UAAA,EAAY,KAAA,EAAO,MAAM,MAAA;AAAO;AAErD;AAEO,MAAM,YAAA,GAAe;AAAA,EAC1B,UAAA,EAAY,8BAAA;AAAA,EACZ,QAAA,EAAU;AACZ;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const mysql = require('./mysql.js');
const lruMemoizer = require('./lru-memoizer.js');
const ioredis = require('./ioredis.js');
const openai = require('./openai.js');
const pg = require('./pg.js');
const anthropicAi = require('./anthropic-ai.js');
const vercelAi = require('./vercel-ai.js');
const hapi = require('./hapi.js');
const SENTRY_INSTRUMENTATIONS = [
...mysql.mysqlConfig,
...lruMemoizer.lruMemoizerConfig,
...ioredis.ioredisConfig,
...openai.openaiConfig,
...pg.pgConfig,
...anthropicAi.anthropicAiConfig,
...vercelAi.vercelAiConfig,
...hapi.hapiConfig
];
const INSTRUMENTED_MODULE_NAMES = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map((i) => i.module.name)));
function withoutInstrumentedExternals(external) {
if (!external) {
return void 0;
}
return external.filter(
(entry) => !INSTRUMENTED_MODULE_NAMES.some((name) => entry === name || entry.startsWith(`${name}/`))
);
}
exports.INSTRUMENTED_MODULE_NAMES = INSTRUMENTED_MODULE_NAMES;
exports.SENTRY_INSTRUMENTATIONS = SENTRY_INSTRUMENTATIONS;
exports.withoutInstrumentedExternals = withoutInstrumentedExternals;
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../../../src/orchestrion/config/index.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\nimport { mysqlConfig } from './mysql';\nimport { lruMemoizerConfig } from './lru-memoizer';\nimport { ioredisConfig } from './ioredis';\nimport { openaiConfig } from './openai';\nimport { pgConfig } from './pg';\nimport { anthropicAiConfig } from './anthropic-ai';\nimport { vercelAiConfig } from './vercel-ai';\nimport { hapiConfig } from './hapi';\n\nexport const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[] = [\n ...mysqlConfig,\n ...lruMemoizerConfig,\n ...ioredisConfig,\n ...openaiConfig,\n ...pgConfig,\n ...anthropicAiConfig,\n ...vercelAiConfig,\n ...hapiConfig,\n];\n\n/**\n * The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`\n * (e.g. `['mysql']`).\n *\n * Bundler plugins MUST ensure these are actually bundled rather than\n * externalized: an externalized dependency is resolved from `node_modules` at\n * runtime and never passes through the code transform's `onLoad`, so its\n * diagnostics_channel calls are silently never injected.\n */\nexport const INSTRUMENTED_MODULE_NAMES: string[] = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map(i => i.module.name)));\n\n/**\n * Returns `external` with any instrumented packages removed, so a bundler that\n * uses an \"external\" denylist (esbuild, Bun, Rollup) still bundles — and thus\n * transforms — them. Matches an exact package name (`'mysql'`) or a subpath\n * (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`\n * is returned unchanged.\n *\n * (Vite uses an `ssr.noExternal` allowlist instead, so it consumes\n * `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)\n */\nexport function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined {\n if (!external) {\n return undefined;\n }\n return external.filter(\n entry => !INSTRUMENTED_MODULE_NAMES.some(name => entry === name || entry.startsWith(`${name}/`)),\n );\n}\n"],"names":["mysqlConfig","lruMemoizerConfig","ioredisConfig","openaiConfig","pgConfig","anthropicAiConfig","vercelAiConfig","hapiConfig"],"mappings":";;;;;;;;;;;AAUO,MAAM,uBAAA,GAAmD;AAAA,EAC9D,GAAGA,iBAAA;AAAA,EACH,GAAGC,6BAAA;AAAA,EACH,GAAGC,qBAAA;AAAA,EACH,GAAGC,mBAAA;AAAA,EACH,GAAGC,WAAA;AAAA,EACH,GAAGC,6BAAA;AAAA,EACH,GAAGC,uBAAA;AAAA,EACH,GAAGC;AACL;AAWO,MAAM,yBAAA,GAAsC,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,uBAAA,CAAwB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,IAAI,CAAC,CAAC;AAY/G,SAAS,6BAA6B,QAAA,EAA+D;AAC1G,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,CAAS,MAAA;AAAA,IACd,CAAA,KAAA,KAAS,CAAC,yBAAA,CAA0B,IAAA,CAAK,CAAA,IAAA,KAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,CAAM,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAC;AAAA,GACjG;AACF;;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const ioredisConfig = [
// ioredis `<5.11.0` (>=5.11.0 publishes its own `ioredis:*` diagnostics_channel)
...["lib/redis.js", "built/redis.js", "built/redis/index.js"].flatMap((filePath) => [
{
channelName: "command",
module: { name: "ioredis", versionRange: ">=2.0.0 <5.0.0", filePath },
functionQuery: { expressionName: "sendCommand", kind: "Async" }
},
{
channelName: "connect",
module: { name: "ioredis", versionRange: ">=2.0.0 <5.0.0", filePath },
functionQuery: { expressionName: "connect", kind: "Async" }
}
]),
{
channelName: "command",
module: { name: "ioredis", versionRange: ">=5.0.0 <5.11.0", filePath: "built/Redis.js" },
functionQuery: { className: "Redis", methodName: "sendCommand", kind: "Async" }
},
{
channelName: "connect",
module: { name: "ioredis", versionRange: ">=5.0.0 <5.11.0", filePath: "built/Redis.js" },
functionQuery: { className: "Redis", methodName: "connect", kind: "Async" }
}
];
const ioredisChannels = {
IOREDIS_COMMAND: "orchestrion:ioredis:command",
IOREDIS_CONNECT: "orchestrion:ioredis:connect"
};
exports.ioredisChannels = ioredisChannels;
exports.ioredisConfig = ioredisConfig;
//# sourceMappingURL=ioredis.js.map
{"version":3,"file":"ioredis.js","sources":["../../../../src/orchestrion/config/ioredis.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const ioredisConfig = [\n // ioredis `<5.11.0` (>=5.11.0 publishes its own `ioredis:*` diagnostics_channel)\n ...['lib/redis.js', 'built/redis.js', 'built/redis/index.js'].flatMap((filePath): InstrumentationConfig[] => [\n {\n channelName: 'command',\n module: { name: 'ioredis', versionRange: '>=2.0.0 <5.0.0', filePath },\n functionQuery: { expressionName: 'sendCommand', kind: 'Async' },\n },\n {\n channelName: 'connect',\n module: { name: 'ioredis', versionRange: '>=2.0.0 <5.0.0', filePath },\n functionQuery: { expressionName: 'connect', kind: 'Async' },\n },\n ]),\n {\n channelName: 'command',\n module: { name: 'ioredis', versionRange: '>=5.0.0 <5.11.0', filePath: 'built/Redis.js' },\n functionQuery: { className: 'Redis', methodName: 'sendCommand', kind: 'Async' },\n },\n {\n channelName: 'connect',\n module: { name: 'ioredis', versionRange: '>=5.0.0 <5.11.0', filePath: 'built/Redis.js' },\n functionQuery: { className: 'Redis', methodName: 'connect', kind: 'Async' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const ioredisChannels = {\n IOREDIS_COMMAND: 'orchestrion:ioredis:command',\n IOREDIS_CONNECT: 'orchestrion:ioredis:connect',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,GAAG,CAAC,cAAA,EAAgB,gBAAA,EAAkB,sBAAsB,CAAA,CAAE,OAAA,CAAQ,CAAC,QAAA,KAAsC;AAAA,IAC3G;AAAA,MACE,WAAA,EAAa,SAAA;AAAA,MACb,QAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,YAAA,EAAc,kBAAkB,QAAA,EAAS;AAAA,MACpE,aAAA,EAAe,EAAE,cAAA,EAAgB,aAAA,EAAe,MAAM,OAAA;AAAQ,KAChE;AAAA,IACA;AAAA,MACE,WAAA,EAAa,SAAA;AAAA,MACb,QAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,YAAA,EAAc,kBAAkB,QAAA,EAAS;AAAA,MACpE,aAAA,EAAe,EAAE,cAAA,EAAgB,SAAA,EAAW,MAAM,OAAA;AAAQ;AAC5D,GACD,CAAA;AAAA,EACD;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,WAAW,YAAA,EAAc,iBAAA,EAAmB,UAAU,gBAAA,EAAiB;AAAA,IACvF,eAAe,EAAE,SAAA,EAAW,SAAS,UAAA,EAAY,aAAA,EAAe,MAAM,OAAA;AAAQ,GAChF;AAAA,EACA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,WAAW,YAAA,EAAc,iBAAA,EAAmB,UAAU,gBAAA,EAAiB;AAAA,IACvF,eAAe,EAAE,SAAA,EAAW,SAAS,UAAA,EAAY,SAAA,EAAW,MAAM,OAAA;AAAQ;AAE9E;AAEO,MAAM,eAAA,GAAkB;AAAA,EAC7B,eAAA,EAAiB,6BAAA;AAAA,EACjB,eAAA,EAAiB;AACnB;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const lruMemoizerConfig = [
{
channelName: "load",
// `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0
module: { name: "lru-memoizer", versionRange: ">=2.1.0 <4", filePath: "lib/async.js" },
functionQuery: { functionName: "memoizedFunction", kind: "Callback" }
}
];
const lruMemoizerChannels = {
LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load"
};
exports.lruMemoizerChannels = lruMemoizerChannels;
exports.lruMemoizerConfig = lruMemoizerConfig;
//# sourceMappingURL=lru-memoizer.js.map
{"version":3,"file":"lru-memoizer.js","sources":["../../../../src/orchestrion/config/lru-memoizer.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const lruMemoizerConfig = [\n {\n channelName: 'load',\n // `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0\n module: { name: 'lru-memoizer', versionRange: '>=2.1.0 <4', filePath: 'lib/async.js' },\n functionQuery: { functionName: 'memoizedFunction', kind: 'Callback' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const lruMemoizerChannels = {\n LRU_MEMOIZER_LOAD: 'orchestrion:lru-memoizer:load',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,iBAAA,GAAoB;AAAA,EAC/B;AAAA,IACE,WAAA,EAAa,MAAA;AAAA;AAAA,IAEb,QAAQ,EAAE,IAAA,EAAM,gBAAgB,YAAA,EAAc,YAAA,EAAc,UAAU,cAAA,EAAe;AAAA,IACrF,aAAA,EAAe,EAAE,YAAA,EAAc,kBAAA,EAAoB,MAAM,UAAA;AAAW;AAExE;AAEO,MAAM,mBAAA,GAAsB;AAAA,EACjC,iBAAA,EAAmB;AACrB;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const mysqlConfig = [
{
channelName: "query",
module: { name: "mysql", versionRange: ">=2.0.0 <3", filePath: "lib/Connection.js" },
functionQuery: { expressionName: "query", kind: "Auto" }
}
];
const mysqlChannels = {
MYSQL_QUERY: "orchestrion:mysql:query"
};
exports.mysqlChannels = mysqlChannels;
exports.mysqlConfig = mysqlConfig;
//# sourceMappingURL=mysql.js.map
{"version":3,"file":"mysql.js","sources":["../../../../src/orchestrion/config/mysql.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const mysqlConfig = [\n {\n channelName: 'query',\n module: { name: 'mysql', versionRange: '>=2.0.0 <3', filePath: 'lib/Connection.js' },\n functionQuery: { expressionName: 'query', kind: 'Auto' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const mysqlChannels = {\n MYSQL_QUERY: 'orchestrion:mysql:query',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,WAAA,GAAc;AAAA,EACzB;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,SAAS,YAAA,EAAc,YAAA,EAAc,UAAU,mBAAA,EAAoB;AAAA,IACnF,aAAA,EAAe,EAAE,cAAA,EAAgB,OAAA,EAAS,MAAM,MAAA;AAAO;AAE3D;AAEO,MAAM,aAAA,GAAgB;AAAA,EAC3B,WAAA,EAAa;AACf;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const openaiConfig = [
// OpenAI chat completions. `Completions.create` returns a thenable `APIPromise` with no callback arg,
// so `kind: 'Auto'` resolves to `wrapPromise`. openai ships dual CJS/ESM and the matcher compares
// `filePath` exactly, hence one entry per built file (`.js` for `require`, `.mjs` for `import`).
...["resources/chat/completions/completions.js", "resources/chat/completions/completions.mjs"].map((filePath) => ({
channelName: "chat",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Completions", methodName: "create", kind: "Auto" }
})),
// OpenAI responses API — same `create(body, options)` shape as chat completions.
...["resources/responses/responses.js", "resources/responses/responses.mjs"].map((filePath) => ({
channelName: "responses",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Responses", methodName: "create", kind: "Auto" }
})),
// OpenAI embeddings API — same `create(body, options)` shape as chat completions.
...["resources/embeddings.js", "resources/embeddings.mjs"].map((filePath) => ({
channelName: "embeddings",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Embeddings", methodName: "create", kind: "Auto" }
})),
// OpenAI conversations API — same `create(body, options)` shape as chat completions.
...["resources/conversations/conversations.js", "resources/conversations/conversations.mjs"].map((filePath) => ({
channelName: "conversations",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Conversations", methodName: "create", kind: "Auto" }
}))
];
const openaiChannels = {
OPENAI_CHAT: "orchestrion:openai:chat",
OPENAI_RESPONSES: "orchestrion:openai:responses",
OPENAI_EMBEDDINGS: "orchestrion:openai:embeddings",
OPENAI_CONVERSATIONS: "orchestrion:openai:conversations"
};
exports.openaiChannels = openaiChannels;
exports.openaiConfig = openaiConfig;
//# sourceMappingURL=openai.js.map
{"version":3,"file":"openai.js","sources":["../../../../src/orchestrion/config/openai.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const openaiConfig = [\n // OpenAI chat completions. `Completions.create` returns a thenable `APIPromise` with no callback arg,\n // so `kind: 'Auto'` resolves to `wrapPromise`. openai ships dual CJS/ESM and the matcher compares\n // `filePath` exactly, hence one entry per built file (`.js` for `require`, `.mjs` for `import`).\n ...['resources/chat/completions/completions.js', 'resources/chat/completions/completions.mjs'].map(filePath => ({\n channelName: 'chat',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Completions', methodName: 'create', kind: 'Auto' as const },\n })),\n // OpenAI responses API — same `create(body, options)` shape as chat completions.\n ...['resources/responses/responses.js', 'resources/responses/responses.mjs'].map(filePath => ({\n channelName: 'responses',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Responses', methodName: 'create', kind: 'Auto' as const },\n })),\n // OpenAI embeddings API — same `create(body, options)` shape as chat completions.\n ...['resources/embeddings.js', 'resources/embeddings.mjs'].map(filePath => ({\n channelName: 'embeddings',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Embeddings', methodName: 'create', kind: 'Auto' as const },\n })),\n // OpenAI conversations API — same `create(body, options)` shape as chat completions.\n ...['resources/conversations/conversations.js', 'resources/conversations/conversations.mjs'].map(filePath => ({\n channelName: 'conversations',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Conversations', methodName: 'create', kind: 'Auto' as const },\n })),\n] satisfies InstrumentationConfig[];\n\nexport const openaiChannels = {\n OPENAI_CHAT: 'orchestrion:openai:chat',\n OPENAI_RESPONSES: 'orchestrion:openai:responses',\n OPENAI_EMBEDDINGS: 'orchestrion:openai:embeddings',\n OPENAI_CONVERSATIONS: 'orchestrion:openai:conversations',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,YAAA,GAAe;AAAA;AAAA;AAAA;AAAA,EAI1B,GAAG,CAAC,2CAAA,EAA6C,4CAA4C,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC9G,WAAA,EAAa,MAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,eAAe,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACzF,CAAE,CAAA;AAAA;AAAA,EAEF,GAAG,CAAC,kCAAA,EAAoC,mCAAmC,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC5F,WAAA,EAAa,WAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,aAAa,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACvF,CAAE,CAAA;AAAA;AAAA,EAEF,GAAG,CAAC,yBAAA,EAA2B,0BAA0B,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC1E,WAAA,EAAa,YAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,cAAc,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACxF,CAAE,CAAA;AAAA;AAAA,EAEF,GAAG,CAAC,0CAAA,EAA4C,2CAA2C,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC5G,WAAA,EAAa,eAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,iBAAiB,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GAC3F,CAAE;AACJ;AAEO,MAAM,cAAA,GAAiB;AAAA,EAC5B,WAAA,EAAa,yBAAA;AAAA,EACb,gBAAA,EAAkB,8BAAA;AAAA,EAClB,iBAAA,EAAmB,+BAAA;AAAA,EACnB,oBAAA,EAAsB;AACxB;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const pgConfig = [
// `pg` (node-postgres).
// instruments `Client.prototype.query`/`connect` (both the JS and native
// clients) plus `pg-pool`'s `Pool.prototype.connect`.
// `Auto` covers the callback, promise, and streamable-`Submittable`
// call shapes (like mysql).
// `pg/lib/client.js` is `class Client { query() {...} connect() {...} }`,
// so `className`+`methodName` matches directly.
{
channelName: "query",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/client.js" },
functionQuery: { className: "Client", methodName: "query", kind: "Auto" }
},
{
channelName: "connect",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/client.js" },
functionQuery: { className: "Client", methodName: "connect", kind: "Auto" }
},
// The native client (`pg/lib/native/client.js`) is a constructor function,
// not a class.
// `Client.prototype.query = function (config, values, callback) {...}`
// so it needs `expressionName` (the mysql shape), publishing to the SAME
// `orchestrion:pg:query`/`:connect` channels as the JS client.
{
channelName: "query",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/native/client.js" },
functionQuery: { expressionName: "query", kind: "Auto" }
},
{
channelName: "connect",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/native/client.js" },
functionQuery: { expressionName: "connect", kind: "Auto" }
},
// `pg-pool` is `class Pool extends EventEmitter { connect(cb) {...} }`.
{
channelName: "connect",
module: { name: "pg-pool", versionRange: ">=2.0.0 <4", filePath: "index.js" },
functionQuery: { className: "Pool", methodName: "connect", kind: "Auto" }
}
];
const pgChannels = {
PG_QUERY: "orchestrion:pg:query",
PG_CONNECT: "orchestrion:pg:connect",
PGPOOL_CONNECT: "orchestrion:pg-pool:connect"
};
exports.pgChannels = pgChannels;
exports.pgConfig = pgConfig;
//# sourceMappingURL=pg.js.map
{"version":3,"file":"pg.js","sources":["../../../../src/orchestrion/config/pg.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const pgConfig = [\n // `pg` (node-postgres).\n // instruments `Client.prototype.query`/`connect` (both the JS and native\n // clients) plus `pg-pool`'s `Pool.prototype.connect`.\n // `Auto` covers the callback, promise, and streamable-`Submittable`\n // call shapes (like mysql).\n // `pg/lib/client.js` is `class Client { query() {...} connect() {...} }`,\n // so `className`+`methodName` matches directly.\n {\n channelName: 'query',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/client.js' },\n functionQuery: { className: 'Client', methodName: 'query', kind: 'Auto' },\n },\n {\n channelName: 'connect',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/client.js' },\n functionQuery: { className: 'Client', methodName: 'connect', kind: 'Auto' },\n },\n // The native client (`pg/lib/native/client.js`) is a constructor function,\n // not a class.\n // `Client.prototype.query = function (config, values, callback) {...}`\n // so it needs `expressionName` (the mysql shape), publishing to the SAME\n // `orchestrion:pg:query`/`:connect` channels as the JS client.\n {\n channelName: 'query',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/native/client.js' },\n functionQuery: { expressionName: 'query', kind: 'Auto' },\n },\n {\n channelName: 'connect',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/native/client.js' },\n functionQuery: { expressionName: 'connect', kind: 'Auto' },\n },\n // `pg-pool` is `class Pool extends EventEmitter { connect(cb) {...} }`.\n {\n channelName: 'connect',\n module: { name: 'pg-pool', versionRange: '>=2.0.0 <4', filePath: 'index.js' },\n functionQuery: { className: 'Pool', methodName: 'connect', kind: 'Auto' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const pgChannels = {\n PG_QUERY: 'orchestrion:pg:query',\n PG_CONNECT: 'orchestrion:pg:connect',\n PGPOOL_CONNECT: 'orchestrion:pg-pool:connect',\n} as const;\n"],"names":[],"mappings":";;AAEO,MAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,eAAA,EAAgB;AAAA,IAC5E,eAAe,EAAE,SAAA,EAAW,UAAU,UAAA,EAAY,OAAA,EAAS,MAAM,MAAA;AAAO,GAC1E;AAAA,EACA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,eAAA,EAAgB;AAAA,IAC5E,eAAe,EAAE,SAAA,EAAW,UAAU,UAAA,EAAY,SAAA,EAAW,MAAM,MAAA;AAAO,GAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,sBAAA,EAAuB;AAAA,IACnF,aAAA,EAAe,EAAE,cAAA,EAAgB,OAAA,EAAS,MAAM,MAAA;AAAO,GACzD;AAAA,EACA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,sBAAA,EAAuB;AAAA,IACnF,aAAA,EAAe,EAAE,cAAA,EAAgB,SAAA,EAAW,MAAM,MAAA;AAAO,GAC3D;AAAA;AAAA,EAEA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,WAAW,YAAA,EAAc,YAAA,EAAc,UAAU,UAAA,EAAW;AAAA,IAC5E,eAAe,EAAE,SAAA,EAAW,QAAQ,UAAA,EAAY,SAAA,EAAW,MAAM,MAAA;AAAO;AAE5E;AAEO,MAAM,UAAA,GAAa;AAAA,EACxB,QAAA,EAAU,sBAAA;AAAA,EACV,UAAA,EAAY,wBAAA;AAAA,EACZ,cAAA,EAAgB;AAClB;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const vercelAiConfig = [
// Vercel AI v6: mirror the v7 native `ai:telemetry` channel by injecting
// channels into the top-level entry points. `resolveLanguageModel` is wrapped
// not to span it, but so the subscriber can monkey-patch `doGenerate`/
// `doStream` on the returned model (the only way to span the model call,
// which is an inline call with no injectable definition in `ai`).
// `streamText` returns its result synchronously (streaming is lazy), so it's
// `Sync`; the subscriber binds the span via `bindTracingChannelToSpan`, which
// ends it when the (synchronous) call returns.
...vercelAiV6Entries("generateText", "generateText", "Async"),
...vercelAiV6Entries("streamText", "streamText", "Sync"),
...vercelAiV6Entries("embed", "embed", "Async"),
...vercelAiV6Entries("embedMany", "embedMany", "Async"),
...vercelAiV6Entries("executeToolCall", "executeToolCall", "Async"),
...vercelAiV6Entries("resolveLanguageModel", "resolveLanguageModel", "Sync")
];
const vercelAiChannels = {
// Vercel AI (`ai`) v6: orchestrion injects these so the same channel-based
// integration that consumes `ai`'s native `ai:telemetry` channel (v7) can
// also instrument v6. Each maps to a top-level function in `ai`'s bundle.
VERCEL_AI_GENERATE_TEXT: "orchestrion:ai:generateText",
VERCEL_AI_STREAM_TEXT: "orchestrion:ai:streamText",
VERCEL_AI_EMBED: "orchestrion:ai:embed",
VERCEL_AI_EMBED_MANY: "orchestrion:ai:embedMany",
VERCEL_AI_EXECUTE_TOOL_CALL: "orchestrion:ai:executeToolCall",
// `resolveLanguageModel` is the single chokepoint every model call flows
// through; we wrap it to monkey-patch `doGenerate`/`doStream` on the returned
// model (the model-call site itself is an inline call with no injectable
// definition).
VERCEL_AI_RESOLVE_LANGUAGE_MODEL: "orchestrion:ai:resolveLanguageModel"
};
function vercelAiV6Entries(channelName, functionName, kind) {
return ["dist/index.js", "dist/index.mjs"].map((filePath) => ({
channelName,
module: { name: "ai", versionRange: ">=6.0.0 <7.0.0", filePath },
functionQuery: { functionName, kind }
}));
}
exports.vercelAiChannels = vercelAiChannels;
exports.vercelAiConfig = vercelAiConfig;
//# sourceMappingURL=vercel-ai.js.map
{"version":3,"file":"vercel-ai.js","sources":["../../../../src/orchestrion/config/vercel-ai.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const vercelAiConfig = [\n // Vercel AI v6: mirror the v7 native `ai:telemetry` channel by injecting\n // channels into the top-level entry points. `resolveLanguageModel` is wrapped\n // not to span it, but so the subscriber can monkey-patch `doGenerate`/\n // `doStream` on the returned model (the only way to span the model call,\n // which is an inline call with no injectable definition in `ai`).\n // `streamText` returns its result synchronously (streaming is lazy), so it's\n // `Sync`; the subscriber binds the span via `bindTracingChannelToSpan`, which\n // ends it when the (synchronous) call returns.\n ...vercelAiV6Entries('generateText', 'generateText', 'Async'),\n ...vercelAiV6Entries('streamText', 'streamText', 'Sync'),\n ...vercelAiV6Entries('embed', 'embed', 'Async'),\n ...vercelAiV6Entries('embedMany', 'embedMany', 'Async'),\n ...vercelAiV6Entries('executeToolCall', 'executeToolCall', 'Async'),\n ...vercelAiV6Entries('resolveLanguageModel', 'resolveLanguageModel', 'Sync'),\n] satisfies InstrumentationConfig[];\n\nexport const vercelAiChannels = {\n // Vercel AI (`ai`) v6: orchestrion injects these so the same channel-based\n // integration that consumes `ai`'s native `ai:telemetry` channel (v7) can\n // also instrument v6. Each maps to a top-level function in `ai`'s bundle.\n VERCEL_AI_GENERATE_TEXT: 'orchestrion:ai:generateText',\n VERCEL_AI_STREAM_TEXT: 'orchestrion:ai:streamText',\n VERCEL_AI_EMBED: 'orchestrion:ai:embed',\n VERCEL_AI_EMBED_MANY: 'orchestrion:ai:embedMany',\n VERCEL_AI_EXECUTE_TOOL_CALL: 'orchestrion:ai:executeToolCall',\n // `resolveLanguageModel` is the single chokepoint every model call flows\n // through; we wrap it to monkey-patch `doGenerate`/`doStream` on the returned\n // model (the model-call site itself is an inline call with no injectable\n // definition).\n VERCEL_AI_RESOLVE_LANGUAGE_MODEL: 'orchestrion:ai:resolveLanguageModel',\n} as const;\n\n/**\n * The central list of channel injections orchestrion should perform.\n *\n * This module has NO side effects — it's the only thing both the runtime hook\n * (`runtime/import-hook.mjs`) and the bundler plugins (`bundler/vite.ts`, …)\n * import from. Adding a new instrumented method is one entry here plus one\n * subscriber in `integrations/<lib>/tracing-channel.ts`.\n *\n * `channelName` here is the unprefixed suffix; the actual diagnostics_channel\n * name is `orchestrion:${module.name}:${channelName}` (see `channels.ts`).\n */\n/**\n * `ai` ships a single bundled entry per module system, so each instrumented\n * function needs one config entry per file (the app loads whichever matches its\n * module system). This expands a single target into both.\n */\nfunction vercelAiV6Entries(channelName: string, functionName: string, kind: 'Async' | 'Sync'): InstrumentationConfig[] {\n return ['dist/index.js', 'dist/index.mjs'].map(filePath => ({\n channelName,\n module: { name: 'ai', versionRange: '>=6.0.0 <7.0.0', filePath },\n functionQuery: { functionName, kind },\n }));\n}\n"],"names":[],"mappings":";;AAEO,MAAM,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS5B,GAAG,iBAAA,CAAkB,cAAA,EAAgB,cAAA,EAAgB,OAAO,CAAA;AAAA,EAC5D,GAAG,iBAAA,CAAkB,YAAA,EAAc,YAAA,EAAc,MAAM,CAAA;AAAA,EACvD,GAAG,iBAAA,CAAkB,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA;AAAA,EAC9C,GAAG,iBAAA,CAAkB,WAAA,EAAa,WAAA,EAAa,OAAO,CAAA;AAAA,EACtD,GAAG,iBAAA,CAAkB,iBAAA,EAAmB,iBAAA,EAAmB,OAAO,CAAA;AAAA,EAClE,GAAG,iBAAA,CAAkB,sBAAA,EAAwB,sBAAA,EAAwB,MAAM;AAC7E;AAEO,MAAM,gBAAA,GAAmB;AAAA;AAAA;AAAA;AAAA,EAI9B,uBAAA,EAAyB,6BAAA;AAAA,EACzB,qBAAA,EAAuB,2BAAA;AAAA,EACvB,eAAA,EAAiB,sBAAA;AAAA,EACjB,oBAAA,EAAsB,0BAAA;AAAA,EACtB,2BAAA,EAA6B,gCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,gCAAA,EAAkC;AACpC;AAkBA,SAAS,iBAAA,CAAkB,WAAA,EAAqB,YAAA,EAAsB,IAAA,EAAiD;AACrH,EAAA,OAAO,CAAC,eAAA,EAAiB,gBAAgB,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC1D,WAAA;AAAA,IACA,QAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,YAAA,EAAc,kBAAkB,QAAA,EAAS;AAAA,IAC/D,aAAA,EAAe,EAAE,YAAA,EAAc,IAAA;AAAK,GACtC,CAAE,CAAA;AACJ;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const serializationSubsets = [
{
regex: /^ECHO/i,
args: 0
},
{
regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,
args: 1
},
{
regex: /^(HSET|HMSET|LSET|LINSERT)/i,
args: 2
},
{
regex: /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,
args: -1
}
];
const defaultDbStatementSerializer = (cmdName, cmdArgs) => {
if (Array.isArray(cmdArgs) && cmdArgs.length) {
const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;
const argsToSerialize = nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();
if (cmdArgs.length > argsToSerialize.length) {
argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);
}
return `${cmdName} ${argsToSerialize.join(" ")}`;
}
return cmdName;
};
exports.defaultDbStatementSerializer = defaultDbStatementSerializer;
//# sourceMappingURL=redis-statement-serializer.js.map
{"version":3,"file":"redis-statement-serializer.js","sources":["../../../src/redis/redis-statement-serializer.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/redis-common\n * - Upstream version: @opentelemetry/redis-common@0.38.2\n *\n * Single canonical copy, shared by the orchestrion ioredis subscriber here and\n * the node SDK's vendored redis/ioredis instrumentations (which re-export it via\n * `packages/node/src/integrations/tracing/redis/vendored/redis-common.ts`).\n */\n/* eslint-disable -- vendored @opentelemetry/redis-common */\n\n/**\n * List of regexes and the number of arguments that should be serialized for matching commands.\n * For example, HSET should serialize which key and field it's operating on, but not its value.\n * Setting the subset to -1 will serialize all arguments.\n * Commands without a match will have their first argument serialized.\n *\n * Refer to https://redis.io/commands/ for the full list.\n */\nconst serializationSubsets = [\n {\n regex: /^ECHO/i,\n args: 0,\n },\n {\n regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,\n args: 1,\n },\n {\n regex: /^(HSET|HMSET|LSET|LINSERT)/i,\n args: 2,\n },\n {\n regex:\n /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,\n args: -1,\n },\n];\n\n/**\n * Given the redis command name and arguments, return a combination of the\n * command name + the allowed arguments according to `serializationSubsets`.\n */\nexport const defaultDbStatementSerializer = (\n cmdName: string,\n cmdArgs: Array<string | Buffer | number | unknown[]>,\n): string => {\n if (Array.isArray(cmdArgs) && cmdArgs.length) {\n const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;\n const argsToSerialize: Array<string | Buffer | number | unknown[]> =\n nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();\n if (cmdArgs.length > argsToSerialize.length) {\n argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);\n }\n return `${cmdName} ${argsToSerialize.join(' ')}`;\n }\n return cmdName;\n};\n"],"names":[],"mappings":";;AAsBA,MAAM,oBAAA,GAAuB;AAAA,EAC3B;AAAA,IACE,KAAA,EAAO,QAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAA,EAAO,8DAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAA,EAAO,6BAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAA,EACE,kLAAA;AAAA,IACF,IAAA,EAAM;AAAA;AAEV,CAAA;AAMO,MAAM,4BAAA,GAA+B,CAC1C,OAAA,EACA,OAAA,KACW;AACX,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,IAAK,QAAQ,MAAA,EAAQ;AAC5C,IAAA,MAAM,gBAAA,GAAmB,oBAAA,CAAqB,IAAA,CAAK,CAAC,EAAE,KAAA,EAAM,KAAM,KAAA,CAAM,IAAA,CAAK,OAAO,CAAC,CAAA,EAAG,IAAA,IAAQ,CAAA;AAChG,IAAA,MAAM,eAAA,GACJ,oBAAoB,CAAA,GAAI,OAAA,CAAQ,MAAM,CAAA,EAAG,gBAAgB,CAAA,GAAI,OAAA,CAAQ,KAAA,EAAM;AAC7E,IAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,eAAA,CAAgB,MAAA,EAAQ;AAC3C,MAAA,eAAA,CAAgB,IAAA,CAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,MAAA,GAAS,gBAAgB,CAAA,iBAAA,CAAmB,CAAA;AAAA,IAC/E;AACA,IAAA,OAAO,GAAG,OAAO,CAAA,CAAA,EAAI,eAAA,CAAgB,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,OAAA;AACT;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const core = require('@sentry/core');
const debugBuild = require('../debug-build.js');
const channels = require('../orchestrion/channels.js');
const tracingChannel = require('../tracing-channel.js');
const vercelAiDcSubscriber = require('./vercel-ai-dc-subscriber.js');
const PATCHED = /* @__PURE__ */ Symbol("SentryVercelAiModelPatched");
let callIdCounter = 0;
function nextCallId() {
return `v6-${++callIdCounter}`;
}
const messages = /* @__PURE__ */ new WeakMap();
const operationSpans = /* @__PURE__ */ new WeakSet();
const callIdBySpan = /* @__PURE__ */ new WeakMap();
const recordingBySpan = /* @__PURE__ */ new WeakMap();
const suppressedTelemetry = /* @__PURE__ */ new WeakSet();
let subscribed = false;
function subscribeVercelAiOrchestrionChannels(tracingChannel, options = {}) {
if (subscribed) {
return;
}
subscribed = true;
try {
bindOperation(tracingChannel, channels.CHANNELS.VERCEL_AI_GENERATE_TEXT, buildTextMessage("generateText"), options);
bindOperation(tracingChannel, channels.CHANNELS.VERCEL_AI_STREAM_TEXT, buildTextMessage("streamText"), options);
bindOperation(
tracingChannel,
channels.CHANNELS.VERCEL_AI_EMBED,
(callOptions, telemetry) => ({
type: "embed",
event: {
callId: nextCallId(),
...modelFields(callOptions.model),
maxRetries: callOptions.maxRetries,
value: callOptions.value,
...recording(telemetry)
}
}),
options
);
bindOperation(
tracingChannel,
channels.CHANNELS.VERCEL_AI_EMBED_MANY,
// `embedMany` takes a `values` array (vs `embed`'s single `value`); the shared core reads it as the
// embeddings input, matching the OTel path's batch `ai.embedMany` span.
(callOptions, telemetry) => ({
type: "embedMany",
event: {
callId: nextCallId(),
...modelFields(callOptions.model),
maxRetries: callOptions.maxRetries,
values: callOptions.values,
...recording(telemetry)
}
}),
options
);
bindOperation(
tracingChannel,
channels.CHANNELS.VERCEL_AI_EXECUTE_TOOL_CALL,
(callOptions, telemetry) => ({
type: "executeTool",
// v6 carries the tool definitions on the executeToolCall args (a record keyed by name);
// the shared core reads the matching tool's `description` for the span.
event: {
callId: nextCallId(),
toolCall: callOptions.toolCall,
tools: callOptions.tools,
...recording(telemetry)
}
}),
options
);
subscribeResolveLanguageModel(tracingChannel, channels.CHANNELS.VERCEL_AI_RESOLVE_LANGUAGE_MODEL, options);
} catch {
debugBuild.DEBUG_BUILD && core.debug.log("Vercel AI orchestrion channel subscription failed.");
}
}
function bindOperation(tracingChannel$1, channelName, build, options) {
const channel = tracingChannel$1(channelName);
const buildOperationSpan = (data) => {
const callOptions = isRecord(data.arguments[0]) ? data.arguments[0] : {};
const telemetry = isRecord(callOptions.experimental_telemetry) ? callOptions.experimental_telemetry : {};
if (telemetry.isEnabled === false && !suppressedTelemetry.has(telemetry)) {
return void 0;
}
const message = build(callOptions, telemetry);
suppressNativeTelemetry(callOptions, telemetry);
const span = vercelAiDcSubscriber.createSpanFromMessage(message, options);
if (span) {
messages.set(data, message);
operationSpans.add(span);
const callId = asString(message.event.callId);
if (callId) {
callIdBySpan.set(span, callId);
}
recordingBySpan.set(span, recording(telemetry));
}
return span;
};
tracingChannel.bindTracingChannelToSpan(
channel,
(data) => buildOperationSpan(data),
{
beforeSpanEnd: (span, data) => {
const message = messages.get(data);
if (!message) {
return;
}
if (!("error" in data)) {
message.result = message.type === "executeTool" ? { output: data.result } : data.result;
vercelAiDcSubscriber.enrichSpanOnEnd(span, message, options);
}
if (message.type !== "streamText") {
vercelAiDcSubscriber.clearOperationId(message);
}
messages.delete(data);
}
}
);
}
function suppressNativeTelemetry(callOptions, telemetry) {
if (telemetry.isEnabled !== true) {
return;
}
const suppressed = { ...telemetry, isEnabled: false };
suppressedTelemetry.add(suppressed);
callOptions.experimental_telemetry = suppressed;
}
function subscribeResolveLanguageModel(tracingChannel, channelName, options) {
tracingChannel(channelName).subscribe({
end(rawCtx) {
const ctx = rawCtx;
if (!isRecord(ctx.result)) {
return;
}
const model = ctx.result;
if (!model[PATCHED]) {
model[PATCHED] = true;
patchModelMethod(model, "doGenerate", options);
patchModelMethod(model, "doStream", options);
}
},
start() {
},
asyncStart() {
},
asyncEnd() {
},
error() {
}
});
}
function resolveModelCallParent() {
const active = core.getActiveSpan();
return active && operationSpans.has(active) ? active : void 0;
}
function patchModelMethod(model, method, options) {
const original = model[method];
if (typeof original !== "function") {
return;
}
model[method] = function(...args) {
const parent = resolveModelCallParent();
if (!parent) {
return Promise.resolve(original.apply(this, args));
}
const callArgs = isRecord(args[0]) ? args[0] : {};
const callId = callIdBySpan.get(parent);
const message = {
type: "languageModelCall",
event: {
callId,
provider: model.provider,
modelId: model.modelId,
tools: callArgs.tools,
messages: callArgs.prompt,
// Inherit the enclosing operation's per-call recording flags so inputs/tools/outputs are recorded on
// the model-call span whenever they are on the parent `invoke_agent` span.
...recordingBySpan.get(parent)
}
};
const span = core.withActiveSpan(parent, () => vercelAiDcSubscriber.createSpanFromMessage(message, options));
if (!span) {
return Promise.resolve(original.apply(this, args));
}
const clearStreamCallId = () => {
if (method === "doStream" && callId) {
vercelAiDcSubscriber.clearOperationCallId(callId);
}
};
const failSpan = (error) => {
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: error instanceof Error ? error.message : "unknown_error" });
span.end();
clearStreamCallId();
throw error;
};
try {
const result = Promise.resolve(original.apply(this, args));
return result.then((value) => {
message.result = value;
vercelAiDcSubscriber.enrichSpanOnEnd(span, message, options);
span.end();
clearStreamCallId();
return value;
}, failSpan);
} catch (error) {
return failSpan(error);
}
};
}
function buildTextMessage(type) {
return (options, telemetry) => ({
type,
event: {
callId: nextCallId(),
operationId: `ai.${type}`,
functionId: asString(telemetry.functionId),
...modelFields(options.model),
maxRetries: options.maxRetries,
// Normalize to the message-array shape the shared core (and v7's channel) expects: a bare string
// `prompt` becomes a single user message, matching the SDK's own normalization.
messages: normalizePromptMessages(options),
...recording(telemetry)
}
});
}
function normalizePromptMessages(options) {
if (Array.isArray(options.messages)) {
return options.messages;
}
if (typeof options.prompt === "string") {
return [{ role: "user", content: options.prompt }];
}
return options.messages ?? options.prompt;
}
function recording(telemetry) {
return { recordInputs: telemetry.recordInputs, recordOutputs: telemetry.recordOutputs };
}
function modelFields(model) {
return { provider: modelField(model, "provider"), modelId: modelField(model, "modelId") };
}
function modelField(model, field) {
return isRecord(model) ? asString(model[field]) : void 0;
}
function asString(value) {
return typeof value === "string" ? value : void 0;
}
function isRecord(value) {
return typeof value === "object" && value !== null;
}
exports.subscribeVercelAiOrchestrionChannels = subscribeVercelAiOrchestrionChannels;
//# sourceMappingURL=vercel-ai-orchestrion-v6-subscriber.js.map
{"version":3,"file":"vercel-ai-orchestrion-v6-subscriber.js","sources":["../../../src/vercel-ai/vercel-ai-orchestrion-v6-subscriber.ts"],"sourcesContent":["import type { Span } from '@sentry/core';\nimport { debug, getActiveSpan, SPAN_STATUS_ERROR, withActiveSpan } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { CHANNELS } from '../orchestrion/channels';\nimport { bindTracingChannelToSpan, type TracingChannelPayloadWithSpan } from '../tracing-channel';\nimport {\n clearOperationCallId,\n clearOperationId,\n createSpanFromMessage,\n enrichSpanOnEnd,\n type VercelAiChannelMessage,\n type VercelAiChannelOptions,\n type VercelAiTracingChannelFactory,\n} from './vercel-ai-dc-subscriber';\n\n/**\n * v6 channel adapter for the Vercel AI (`ai`) SDK.\n *\n * `ai` >= 7 publishes a normalized `ai:telemetry` tracing channel natively\n * (consumed by `subscribeVercelAiTracingChannel`). v6 has no such channel, so\n * orchestrion injects `orchestrion:ai:*` channels around the top-level\n * functions (see `orchestrion/config/index.ts`). The injected channels carry only the\n * wrapped call's `{ arguments, result, error }` — NOT v7's normalized `event`\n * object — so this adapter reconstructs an equivalent {@link VercelAiChannelMessage}\n * from v6's argument/result shapes and delegates to the SAME span-building core\n * (`createSpanFromMessage` / `enrichSpanOnEnd`) the v7 subscriber uses, so the\n * emitted spans are identical between v6 and v7.\n *\n * The model call (`languageModelCall` / `generate_content` span) has no\n * injectable definition in `ai`, so we instead wrap `resolveLanguageModel` (the\n * single chokepoint every model call flows through) and monkey-patch\n * `doGenerate`/`doStream` on the returned model.\n */\n\n/** Shape orchestrion's transform attaches to the tracing-channel context. */\ninterface OrchestrionContext {\n arguments: unknown[];\n result?: unknown;\n error?: unknown;\n}\n\n/** Builds the normalized message for a channel from the wrapped call's first-arg options. */\ntype MessageBuilder = (options: Record<string, unknown>, telemetry: Record<string, unknown>) => VercelAiChannelMessage;\n\n/** A resolved `ai` language model — has `doGenerate`/`doStream` and identity fields. */\ninterface ResolvedModel {\n modelId?: string;\n provider?: string;\n doGenerate?: (...args: unknown[]) => Promise<unknown>;\n doStream?: (...args: unknown[]) => Promise<unknown>;\n}\n\nconst PATCHED = Symbol('SentryVercelAiModelPatched');\n\n/** A resolved model with our patch bookkeeping (idempotency flag). */\ntype PatchableModel = ResolvedModel & { [PATCHED]?: boolean };\n\n// Per-operation correlation id. No Date/random (unavailable / non-deterministic) — a counter is enough.\nlet callIdCounter = 0;\nfunction nextCallId(): string {\n return `v6-${++callIdCounter}`;\n}\n\n// The message built on `start` for each operation, keyed by the (stable-identity) channel context, so\n// the `beforeSpanEnd` handler can enrich the span from the settled result and clear the `callId` maps.\nconst messages = new WeakMap<object, VercelAiChannelMessage>();\n// The spans we opened for top-level operations, and each one's `callId`. A model call resolves its\n// parent against this set (so it never mis-attributes to the enclosing `main`/user span) and reads the\n// parent's `callId` so its span can be named after the operation (e.g. `ai.streamText.doStream`).\nconst operationSpans = new WeakSet<Span>();\nconst callIdBySpan = new WeakMap<Span, string>();\n// The operation's per-call recording flags (`experimental_telemetry.recordInputs/recordOutputs`), keyed by\n// its span. A model call carries no telemetry of its own, so it inherits the enclosing operation's flags —\n// otherwise a per-call `recordInputs: true` would record inputs on the `invoke_agent` span but not on the\n// child `generate_content` span (whose event would fall back to the global default). v7's channel forwards\n// these flags on every event, so this keeps v6 identical.\nconst recordingBySpan = new WeakMap<Span, ReturnType<typeof recording>>();\n\n// The `experimental_telemetry` objects we swapped in to suppress `ai`'s native OTel spans (see\n// `suppressNativeTelemetry`). Our skip logic treats `isEnabled === false` as \"user disabled telemetry,\n// emit no span\"; without this set, a call whose options object we already neutralized — or a user-shared\n// telemetry object we replaced on a prior call — would be misread as user-disabled and lose its span.\nconst suppressedTelemetry = new WeakSet<object>();\n\nlet subscribed = false;\n\n/**\n * Subscribe the v6 orchestrion channel adapter. Safe to always call: inert on\n * `ai` >= 7 (those channels are never published) and when orchestrion injection\n * isn't active. Idempotent.\n *\n * `tracingChannel` is the platform-provided factory (the same one passed to\n * `subscribeVercelAiTracingChannel`); `options` pins the recording settings at\n * subscribe time so we never look the integration up per event.\n */\nexport function subscribeVercelAiOrchestrionChannels(\n tracingChannel: VercelAiTracingChannelFactory,\n options: VercelAiChannelOptions = {},\n): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n try {\n bindOperation(tracingChannel, CHANNELS.VERCEL_AI_GENERATE_TEXT, buildTextMessage('generateText'), options);\n bindOperation(tracingChannel, CHANNELS.VERCEL_AI_STREAM_TEXT, buildTextMessage('streamText'), options);\n bindOperation(\n tracingChannel,\n CHANNELS.VERCEL_AI_EMBED,\n (callOptions, telemetry) => ({\n type: 'embed',\n event: {\n callId: nextCallId(),\n ...modelFields(callOptions.model),\n maxRetries: callOptions.maxRetries,\n value: callOptions.value,\n ...recording(telemetry),\n },\n }),\n options,\n );\n bindOperation(\n tracingChannel,\n CHANNELS.VERCEL_AI_EMBED_MANY,\n // `embedMany` takes a `values` array (vs `embed`'s single `value`); the shared core reads it as the\n // embeddings input, matching the OTel path's batch `ai.embedMany` span.\n (callOptions, telemetry) => ({\n type: 'embedMany',\n event: {\n callId: nextCallId(),\n ...modelFields(callOptions.model),\n maxRetries: callOptions.maxRetries,\n values: callOptions.values,\n ...recording(telemetry),\n },\n }),\n options,\n );\n bindOperation(\n tracingChannel,\n CHANNELS.VERCEL_AI_EXECUTE_TOOL_CALL,\n (callOptions, telemetry) => ({\n type: 'executeTool',\n // v6 carries the tool definitions on the executeToolCall args (a record keyed by name);\n // the shared core reads the matching tool's `description` for the span.\n event: {\n callId: nextCallId(),\n toolCall: callOptions.toolCall,\n tools: callOptions.tools,\n ...recording(telemetry),\n },\n }),\n options,\n );\n subscribeResolveLanguageModel(tracingChannel, CHANNELS.VERCEL_AI_RESOLVE_LANGUAGE_MODEL, options);\n } catch {\n DEBUG_BUILD && debug.log('Vercel AI orchestrion channel subscription failed.');\n }\n}\n\n/**\n * Bind one operation channel: `getSpan` opens a span from the message reconstructed out of the wrapped\n * call's first argument; `beforeSpanEnd` enriches it from the settled result (tokens, output messages,\n * finish reasons, …) before the helper ends the span.\n *\n * An operation whose `experimental_telemetry.isEnabled` is explicitly `false` is skipped entirely (no\n * span): the orchestrion channel fires regardless of that flag, whereas v7's native `ai:telemetry`\n * channel is simply not published in that case — so we reproduce v7's \"no telemetry → no span\".\n */\nfunction bindOperation(\n tracingChannel: VercelAiTracingChannelFactory,\n channelName: string,\n build: MessageBuilder,\n options: VercelAiChannelOptions,\n): void {\n const channel = tracingChannel<OrchestrionContext>(channelName);\n\n // Build the operation span from the wrapped call's first argument and track it (so a model call can\n // resolve it as its parent). `bindTracingChannelToSpan` calls this once at channel `start` and makes\n // the returned span the active async context for the operation's duration — that active span is what\n // `resolveModelCallParent` reads. It also sets `data._sentrySpan`, so we don't here.\n const buildOperationSpan = (data: TracingChannelPayloadWithSpan<OrchestrionContext>): Span | undefined => {\n const callOptions = isRecord(data.arguments[0]) ? data.arguments[0] : {};\n const telemetry = isRecord(callOptions.experimental_telemetry) ? callOptions.experimental_telemetry : {};\n // `isEnabled === false` means the user opted out — emit no span. But `isEnabled` is also `false` on\n // the telemetry object we swap in to suppress native spans, so don't mistake our own object for a\n // user opt-out (which would drop the span on a call whose options we already neutralized).\n if (telemetry.isEnabled === false && !suppressedTelemetry.has(telemetry)) {\n return undefined;\n }\n const message = build(callOptions, telemetry);\n // Stop `ai` from emitting its own native OTel spans for this call — we build the equivalent spans\n // from the channels, so the SDK's would be duplicates. Reads above have already captured everything\n // we need off `telemetry`.\n suppressNativeTelemetry(callOptions, telemetry);\n const span = createSpanFromMessage(message, options);\n if (span) {\n messages.set(data, message);\n operationSpans.add(span);\n const callId = asString(message.event.callId);\n if (callId) {\n callIdBySpan.set(span, callId);\n }\n recordingBySpan.set(span, recording(telemetry));\n }\n return span;\n };\n\n bindTracingChannelToSpan(\n channel,\n (data: TracingChannelPayloadWithSpan<OrchestrionContext>) => buildOperationSpan(data),\n {\n beforeSpanEnd: (span, data) => {\n const message = messages.get(data);\n if (!message) {\n return;\n }\n // The helper's `error` handler already set the span status; only enrich from a successful result.\n if (!('error' in data)) {\n // v6's `executeToolCall` returns the tool result/error object directly, whereas the shared core\n // (matching v7) expects it nested under `output`; wrap it so tool-error detection works.\n message.result = message.type === 'executeTool' ? { output: data.result } : data.result;\n enrichSpanOnEnd(span, message, options);\n }\n // A `streamText` model call runs after this (synchronously-returning) operation's span has\n // already ended, so its `callId` entry must outlive the operation — it's cleared once the model\n // call settles (see `patchModelMethod`). Every other operation can clear here.\n if (message.type !== 'streamText') {\n clearOperationId(message);\n }\n messages.delete(data);\n },\n },\n );\n}\n\n/**\n * Neutralize `ai`'s native OpenTelemetry instrumentation for this call by pointing\n * `experimental_telemetry` at a copy with `isEnabled: false`. `ai`'s `getTracer` then returns its\n * internal no-op tracer, so it never creates (nor sets active) the duplicate `ai.*` spans we'd\n * otherwise have to drop.\n *\n * Only a call that explicitly enabled telemetry emits native spans — otherwise `ai` already uses its\n * no-op tracer, so there's nothing to suppress and we leave the user's options untouched. When\n * `isEnabled === true`, `telemetry` is `callOptions.experimental_telemetry` and `callOptions` is the\n * real first argument the SDK will read, so the reassignment takes effect for the wrapped call. We\n * replace rather than mutate in place, so a telemetry object the user shares across calls keeps its own\n * `isEnabled: true`; the replacement is tracked in `suppressedTelemetry` so our skip logic doesn't\n * later read it back as a user opt-out.\n */\nfunction suppressNativeTelemetry(callOptions: Record<string, unknown>, telemetry: Record<string, unknown>): void {\n if (telemetry.isEnabled !== true) {\n return;\n }\n const suppressed = { ...telemetry, isEnabled: false };\n suppressedTelemetry.add(suppressed);\n callOptions.experimental_telemetry = suppressed;\n}\n\n/**\n * `resolveLanguageModel` returns the model every call flows through. We don't span it — on `end` we\n * monkey-patch `doGenerate`/`doStream` on the returned model so each invocation produces a\n * `languageModelCall` span parented to the enclosing invoke_agent span.\n */\nfunction subscribeResolveLanguageModel(\n tracingChannel: VercelAiTracingChannelFactory,\n channelName: string,\n options: VercelAiChannelOptions,\n): void {\n tracingChannel<OrchestrionContext>(channelName).subscribe({\n end(rawCtx) {\n const ctx = rawCtx as OrchestrionContext;\n if (!isRecord(ctx.result)) {\n return;\n }\n const model = ctx.result as PatchableModel;\n // Patch the model's `doGenerate`/`doStream` once. The model call recovers its parent from the\n // active async context at call time (the operation span `bindTracingChannelToSpan` bound), which\n // propagates into the model call for `streamText` too, so there is nothing to capture on the model here.\n if (!model[PATCHED]) {\n model[PATCHED] = true;\n patchModelMethod(model, 'doGenerate', options);\n patchModelMethod(model, 'doStream', options);\n }\n },\n start() {\n /* no-op */\n },\n asyncStart() {\n /* no-op */\n },\n asyncEnd() {\n /* no-op */\n },\n error() {\n /* no-op */\n },\n });\n}\n\n/**\n * Pick the invoke_agent span a model call should hang under: the operation span that\n * `bindTracingChannelToSpan` planted as the active async context for the enclosing operation.\n *\n * Because we suppress `ai`'s native telemetry (so it never installs its own span as active), the active\n * span inside `doGenerate`/`doStream` is our operation span. The `operationSpans` gate makes this return\n * `undefined` when the active span isn't one of ours — e.g. telemetry was disabled for the call so we\n * opened no operation span and the active span is the user's enclosing span — so the model call is\n * skipped rather than mis-parented.\n *\n * This covers `generateText`/`embed` (whose model call is awaited inside the operation body) and\n * `streamText` alike — `ai` initiates the stream synchronously within the operation's bound context, so\n * the later `doStream` continuation restores the same active span even though the operation's span has\n * already ended. The per-operation binding also disambiguates concurrent calls that share one model\n * instance (a single mutable slot on the shared model could not — it would hold whichever operation\n * resolved the model last).\n */\nfunction resolveModelCallParent(): Span | undefined {\n const active = getActiveSpan();\n return active && operationSpans.has(active) ? active : undefined;\n}\n\nfunction patchModelMethod(\n model: PatchableModel,\n method: 'doGenerate' | 'doStream',\n options: VercelAiChannelOptions,\n): void {\n const original = model[method];\n if (typeof original !== 'function') {\n return;\n }\n model[method] = function (this: unknown, ...args: unknown[]): Promise<unknown> {\n const parent = resolveModelCallParent();\n // No enclosing operation span (e.g. telemetry disabled for the call) → don't open a model-call span.\n if (!parent) {\n return Promise.resolve(original.apply(this, args));\n }\n\n const callArgs = isRecord(args[0]) ? args[0] : {};\n // Carry the operation's `callId` so the shared core can name the span after it\n // (`ai.generateText.doGenerate` / `ai.streamText.doStream`).\n const callId = callIdBySpan.get(parent);\n const message: VercelAiChannelMessage = {\n type: 'languageModelCall',\n event: {\n callId,\n provider: model.provider,\n modelId: model.modelId,\n tools: callArgs.tools,\n messages: callArgs.prompt,\n // Inherit the enclosing operation's per-call recording flags so inputs/tools/outputs are recorded on\n // the model-call span whenever they are on the parent `invoke_agent` span.\n ...recordingBySpan.get(parent),\n },\n };\n const span = withActiveSpan(parent, () => createSpanFromMessage(message, options));\n // `languageModelCall` always opens a span; the guard just keeps the wrapper safe if that changes.\n if (!span) {\n return Promise.resolve(original.apply(this, args));\n }\n\n // `streamText` ends its operation span synchronously, so its `callId` entry was deliberately left in\n // place for this later model call; drop it now that we've used it.\n const clearStreamCallId = (): void => {\n if (method === 'doStream' && callId) {\n clearOperationCallId(callId);\n }\n };\n\n // Both the synchronous throw and the async rejection of the model call must end the span with an\n // error status (an `async` `doGenerate`/`doStream` that throws rejects rather than throwing here).\n const failSpan = (error: unknown): never => {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: error instanceof Error ? error.message : 'unknown_error' });\n span.end();\n clearStreamCallId();\n throw error;\n };\n\n try {\n const result = Promise.resolve(original.apply(this, args));\n // `doStream` resolves to `{ stream, ... }` before the stream is consumed; we end here (start/end\n // bracket the call) to match the channel timing.\n return result.then(value => {\n message.result = value;\n enrichSpanOnEnd(span, message, options);\n span.end();\n clearStreamCallId();\n return value;\n }, failSpan);\n } catch (error) {\n return failSpan(error);\n }\n };\n}\n\nfunction buildTextMessage(type: 'generateText' | 'streamText'): MessageBuilder {\n return (options, telemetry) => ({\n type,\n event: {\n callId: nextCallId(),\n operationId: `ai.${type}`,\n functionId: asString(telemetry.functionId),\n ...modelFields(options.model),\n maxRetries: options.maxRetries,\n // Normalize to the message-array shape the shared core (and v7's channel) expects: a bare string\n // `prompt` becomes a single user message, matching the SDK's own normalization.\n messages: normalizePromptMessages(options),\n ...recording(telemetry),\n },\n });\n}\n\nfunction normalizePromptMessages(options: Record<string, unknown>): unknown {\n if (Array.isArray(options.messages)) {\n return options.messages;\n }\n if (typeof options.prompt === 'string') {\n return [{ role: 'user', content: options.prompt }];\n }\n return options.messages ?? options.prompt;\n}\n\nfunction recording(telemetry: Record<string, unknown>): { recordInputs: unknown; recordOutputs: unknown } {\n return { recordInputs: telemetry.recordInputs, recordOutputs: telemetry.recordOutputs };\n}\n\nfunction modelFields(model: unknown): { provider?: string; modelId?: string } {\n return { provider: modelField(model, 'provider'), modelId: modelField(model, 'modelId') };\n}\n\nfunction modelField(model: unknown, field: 'modelId' | 'provider'): string | undefined {\n return isRecord(model) ? asString(model[field]) : undefined;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n"],"names":["CHANNELS","DEBUG_BUILD","debug","tracingChannel","createSpanFromMessage","bindTracingChannelToSpan","enrichSpanOnEnd","clearOperationId","getActiveSpan","withActiveSpan","clearOperationCallId","SPAN_STATUS_ERROR"],"mappings":"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"}
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { defineIntegration, waitForTracingChannelBinding, debug, _INTERNAL_shouldSkipAiProviderWrapping, resolveAIRecordingOptions, shouldEnableTruncation, extractAnthropicRequestAttributes, GEN_AI_REQUEST_MODEL_ATTRIBUTE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan, addAnthropicRequestAttributes, addAnthropicResponseAttributes, instrumentAsyncIterableStream, instrumentMessageStream } from '@sentry/core';
import { DEBUG_BUILD } from '../../debug-build.js';
import { CHANNELS } from '../../orchestrion/channels.js';
import { bindTracingChannelToSpan } from '../../tracing-channel.js';
const INTEGRATION_NAME = "Anthropic_AI";
const ORIGIN = "auto.ai.orchestrion.anthropic";
const INSTRUMENTED_CHANNELS = [
{ channel: CHANNELS.ANTHROPIC_CHAT, operation: "chat", methodPath: "messages.create", stream: "async-iterable" },
{ channel: CHANNELS.ANTHROPIC_MODELS, operation: "models", methodPath: "models.retrieve", stream: "none" },
{
channel: CHANNELS.ANTHROPIC_MESSAGES_STREAM,
operation: "chat",
methodPath: "messages.stream",
stream: "message-stream"
}
];
let subscribed = false;
const _anthropicChannelIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel || subscribed) {
return;
}
subscribed = true;
waitForTracingChannelBinding(() => {
for (const { channel, operation, methodPath, stream } of INSTRUMENTED_CHANNELS) {
DEBUG_BUILD && debug.log(`[orchestrion:anthropic] subscribing to channel "${channel}"`);
bindTracingChannelToSpan(
diagnosticsChannel.tracingChannel(channel),
(data) => createGenAiSpan(data, operation, methodPath, options),
{
beforeSpanEnd: (span, data) => {
addAnthropicResponseAttributes(
span,
data.result,
resolveAIRecordingOptions(options).recordOutputs
);
},
deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, stream, options)
}
);
}
});
}
};
});
function createGenAiSpan(data, operation, methodPath, options) {
const args = data.arguments ?? [];
if (_INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {
return void 0;
}
const requestOptions = args[1];
if (requestOptions?.headers?.["X-Stainless-Helper-Method"] === "stream") {
return void 0;
}
const params = typeof args[0] === "object" && args[0] !== null ? args[0] : void 0;
const { recordInputs } = resolveAIRecordingOptions(options);
const enableTruncation = shouldEnableTruncation(options.enableTruncation);
const attributes = extractAnthropicRequestAttributes(args, methodPath, operation);
const model = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] || "unknown";
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const span = startInactiveSpan({
name: `${operation} ${model}`,
op: `gen_ai.${operation}`,
attributes
});
if (recordInputs && params) {
addAnthropicRequestAttributes(span, params, enableTruncation);
}
return span;
}
function isAsyncIterable(value) {
return !!value && typeof value[Symbol.asyncIterator] === "function";
}
function isMessageStream(value) {
return !!value && typeof value.on === "function";
}
function wrapStreamResult(span, data, stream, options) {
const { recordOutputs } = resolveAIRecordingOptions(options);
const result = data.result;
if (stream === "async-iterable" && isAsyncIterable(result)) {
const iterate = result[Symbol.asyncIterator].bind(result);
const instrumented = instrumentAsyncIterableStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs);
result[Symbol.asyncIterator] = () => instrumented;
return true;
}
if (stream === "message-stream" && isMessageStream(result)) {
instrumentMessageStream(result, span, recordOutputs);
return true;
}
return false;
}
const anthropicChannelIntegration = defineIntegration(_anthropicChannelIntegration);
export { anthropicChannelIntegration };
//# sourceMappingURL=anthropic.js.map
{"version":3,"file":"anthropic.js","sources":["../../../../src/integrations/tracing-channel/anthropic.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { AnthropicAiOptions, AnthropicAiResponse, IntegrationFn, Span, SpanAttributeValue } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n addAnthropicRequestAttributes,\n addAnthropicResponseAttributes,\n debug,\n defineIntegration,\n extractAnthropicRequestAttributes,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n instrumentAsyncIterableStream,\n instrumentMessageStream,\n resolveAIRecordingOptions,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// Same name as the OTel integration by design: when enabled, the OTel 'Anthropic_AI'\n// integration is dropped from the default set (see the Node opt-in loader).\nconst INTEGRATION_NAME = 'Anthropic_AI' as const;\n\n// Distinct from the proxy's `auto.ai.anthropic` so spans from the orchestrion path\n// are attributable separately from the OTel/proxy one.\nconst ORIGIN = 'auto.ai.orchestrion.anthropic';\n\n// `stream` determines how the span is ended\nconst INSTRUMENTED_CHANNELS = [\n { channel: CHANNELS.ANTHROPIC_CHAT, operation: 'chat', methodPath: 'messages.create', stream: 'async-iterable' },\n { channel: CHANNELS.ANTHROPIC_MODELS, operation: 'models', methodPath: 'models.retrieve', stream: 'none' },\n {\n channel: CHANNELS.ANTHROPIC_MESSAGES_STREAM,\n operation: 'chat',\n methodPath: 'messages.stream',\n stream: 'message-stream',\n },\n] as const;\n\ntype StreamMode = (typeof INSTRUMENTED_CHANNELS)[number]['stream'];\n\ninterface AnthropicChannelContext {\n arguments: unknown[];\n result?: unknown;\n}\n\nlet subscribed = false;\n\nconst _anthropicChannelIntegration = ((options: AnthropicAiOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // tracingChannel is unavailable before Node 18.19 and prevent double-subscribe\n if (!diagnosticsChannel.tracingChannel || subscribed) {\n return;\n }\n subscribed = true;\n\n // `bindTracingChannelToSpan` needs the async-context binding that `initOpenTelemetry()` registers\n // after `setupOnce` runs, so wait for it before subscribing.\n waitForTracingChannelBinding(() => {\n for (const { channel, operation, methodPath, stream } of INSTRUMENTED_CHANNELS) {\n DEBUG_BUILD && debug.log(`[orchestrion:anthropic] subscribing to channel \"${channel}\"`);\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<AnthropicChannelContext>(channel),\n data => createGenAiSpan(data, operation, methodPath, options),\n {\n beforeSpanEnd: (span, data) => {\n addAnthropicResponseAttributes(\n span,\n data.result as AnthropicAiResponse,\n resolveAIRecordingOptions(options).recordOutputs,\n );\n },\n deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, stream, options),\n },\n );\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Build the span for an instrumented call.\n * Returning `undefined` opts the payload out so no span is opened.\n */\nfunction createGenAiSpan(\n data: AnthropicChannelContext,\n operation: string,\n methodPath: string,\n options: AnthropicAiOptions,\n): Span | undefined {\n const args = data.arguments ?? [];\n\n // When LangChain (or another provider) is driving the SDK, it records the spans itself and marks this\n // provider as skipped — mirror the OTel integration and don't double-instrument.\n if (_INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {\n return undefined;\n }\n\n // `messages.stream()` internally calls the instrumented `messages.create({ stream: true })` tagged with\n // an `X-Stainless-Helper-Method: 'stream'` header. The messages-stream channel already covers it, so skip\n // the nested create to avoid a duplicate span.\n const requestOptions = args[1] as { headers?: Record<string, unknown> } | undefined;\n if (requestOptions?.headers?.['X-Stainless-Helper-Method'] === 'stream') {\n return undefined;\n }\n\n const params = typeof args[0] === 'object' && args[0] !== null ? (args[0] as Record<string, unknown>) : undefined;\n\n const { recordInputs } = resolveAIRecordingOptions(options);\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n\n const attributes = extractAnthropicRequestAttributes(args, methodPath, operation);\n const model = (attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;\n\n const span = startInactiveSpan({\n name: `${operation} ${model}`,\n op: `gen_ai.${operation}`,\n attributes: attributes as Record<string, SpanAttributeValue>,\n });\n\n if (recordInputs && params) {\n addAnthropicRequestAttributes(span, params, enableTruncation);\n }\n\n return span;\n}\n\ntype AsyncIterableStream = { [Symbol.asyncIterator]: () => AsyncIterator<unknown> };\ntype MessageStreamEmitter = { on: (...args: unknown[]) => void };\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterableStream {\n return !!value && typeof (value as AsyncIterableStream)[Symbol.asyncIterator] === 'function';\n}\n\nfunction isMessageStream(value: unknown): value is MessageStreamEmitter {\n return !!value && typeof (value as MessageStreamEmitter).on === 'function';\n}\n\n/**\n * Hand span-ending ownership to a streamed result: returns `true` to skip the normal `beforeSpanEnd`,\n * `false` for non-streaming results (which end via `beforeSpanEnd`).\n *\n * - `async-iterable`: patch the `Stream`'s async iterator in place so `instrumentAsyncIterableStream` ends\n * the span when iteration finishes.\n * - `message-stream`: `instrumentMessageStream` attaches `'message'`/`'error'` listeners that end the span.\n */\nfunction wrapStreamResult(\n span: Span,\n data: AnthropicChannelContext,\n stream: StreamMode,\n options: AnthropicAiOptions,\n): boolean {\n const { recordOutputs } = resolveAIRecordingOptions(options);\n const result = data.result;\n\n if (stream === 'async-iterable' && isAsyncIterable(result)) {\n const iterate = result[Symbol.asyncIterator].bind(result);\n const instrumented = instrumentAsyncIterableStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs);\n result[Symbol.asyncIterator] = () => instrumented;\n return true;\n }\n\n if (stream === 'message-stream' && isMessageStream(result)) {\n instrumentMessageStream(result, span, recordOutputs);\n return true;\n }\n\n return false;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven Anthropic integration. Subscribes to the `orchestrion:@anthropic-ai/sdk:*`\n * diagnostics_channels injected into the SDK's chat (`messages`/`completions`/beta `messages`), `models`, and\n * `messages.stream()` methods, so it requires the orchestrion runtime hook or bundler plugin.\n */\nexport const anthropicChannelIntegration = defineIntegration(_anthropicChannelIntegration);\n"],"names":[],"mappings":"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"}
const LIFECYCLE_EXT_POINTS = [
"onPreAuth",
"onCredentials",
"onPostAuth",
"onPreHandler",
"onPostHandler",
"onPreResponse",
"onRequest"
];
const handlerPatched = /* @__PURE__ */ Symbol("hapi-handler-patched");
const HapiLayerType = {
ROUTER: "router",
PLUGIN: "plugin",
EXT: "server.ext"
};
const HapiLifecycleMethodNames = new Set(LIFECYCLE_EXT_POINTS);
var AttributeNames = /* @__PURE__ */ ((AttributeNames2) => {
AttributeNames2["HAPI_TYPE"] = "hapi.type";
AttributeNames2["PLUGIN_NAME"] = "hapi.plugin.name";
AttributeNames2["EXT_TYPE"] = "server.ext.type";
return AttributeNames2;
})(AttributeNames || {});
export { AttributeNames, HapiLayerType, HapiLifecycleMethodNames, handlerPatched };
//# sourceMappingURL=hapi-types.js.map
{"version":3,"file":"hapi-types.js","sources":["../../../../src/integrations/tracing-channel/hapi-types.ts"],"sourcesContent":["/*\n * Structural type definitions and constants ported from the vendored\n * `@opentelemetry/instrumentation-hapi` types, with all `@hapi/*` and\n * `@opentelemetry/*` dependencies removed. Only the shapes actually accessed by\n * the orchestrion hapi subscriber are kept.\n */\n\n// Single source of truth for the request lifecycle extension points, so the\n// `ServerRequestExtType` union and the runtime `HapiLifecycleMethodNames` set\n// below can't drift apart.\nconst LIFECYCLE_EXT_POINTS = [\n 'onPreAuth',\n 'onCredentials',\n 'onPostAuth',\n 'onPreHandler',\n 'onPostHandler',\n 'onPreResponse',\n 'onRequest',\n] as const;\n\nexport type ServerRequestExtType = (typeof LIFECYCLE_EXT_POINTS)[number];\n\nexport type LifecycleMethod = (request: unknown, h: unknown, err?: Error) => unknown;\n\nexport interface ServerRouteOptions {\n handler?: LifecycleMethod | unknown;\n [key: string]: unknown;\n}\n\nexport interface ServerRoute {\n path: string;\n method: string;\n handler?: LifecycleMethod | unknown;\n options?: ((server: unknown) => ServerRouteOptions) | ServerRouteOptions;\n [key: string]: unknown;\n}\n\nexport interface ServerExtEventsObject {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface ServerExtEventsRequestObject {\n type: ServerRequestExtType;\n method: LifecycleMethod;\n [key: string]: unknown;\n}\n\nexport interface ServerExtOptions {\n [key: string]: unknown;\n}\n\n/**\n * This symbol is used to mark a Hapi route handler or server extension handler as\n * already patched, since it's possible to use these handlers multiple times\n * i.e. when allowing multiple versions of one plugin, or when registering a plugin\n * multiple times on different servers.\n */\nexport const handlerPatched: unique symbol = Symbol('hapi-handler-patched');\n\nexport type PatchableServerRoute = ServerRoute & {\n [handlerPatched]?: boolean;\n};\n\nexport type PatchableExtMethod = LifecycleMethod & {\n [handlerPatched]?: boolean;\n};\n\nexport type ServerExtDirectInput = [ServerRequestExtType, LifecycleMethod, (ServerExtOptions | undefined)?];\n\nexport const HapiLayerType = {\n ROUTER: 'router',\n PLUGIN: 'plugin',\n EXT: 'server.ext',\n} as const;\n\nexport const HapiLifecycleMethodNames = new Set<string>(LIFECYCLE_EXT_POINTS);\n\nexport enum AttributeNames {\n HAPI_TYPE = 'hapi.type',\n PLUGIN_NAME = 'hapi.plugin.name',\n EXT_TYPE = 'server.ext.type',\n}\n"],"names":["AttributeNames"],"mappings":"AAUA,MAAM,oBAAA,GAAuB;AAAA,EAC3B,WAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA;AAwCO,MAAM,cAAA,0BAAuC,sBAAsB;AAYnE,MAAM,aAAA,GAAgB;AAAA,EAC3B,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ,QAAA;AAAA,EACR,GAAA,EAAK;AACP;AAEO,MAAM,wBAAA,GAA2B,IAAI,GAAA,CAAY,oBAAoB;AAErE,IAAK,cAAA,qBAAAA,eAAAA,KAAL;AACL,EAAAA,gBAAA,WAAA,CAAA,GAAY,WAAA;AACZ,EAAAA,gBAAA,aAAA,CAAA,GAAc,kBAAA;AACd,EAAAA,gBAAA,UAAA,CAAA,GAAW,iBAAA;AAHD,EAAA,OAAAA,eAAAA;AAAA,CAAA,EAAA,cAAA,IAAA,EAAA;;;;"}
import { getActiveSpan, getRootSpan, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { HTTP_ROUTE, HTTP_METHOD } from '@sentry/conventions/attributes';
import { handlerPatched, HapiLifecycleMethodNames, HapiLayerType, AttributeNames } from './hapi-types.js';
function setHttpServerSpanRouteAttribute(route) {
const activeSpan = getActiveSpan();
if (!activeSpan) {
return;
}
const rootSpan = getRootSpan(activeSpan);
if (!rootSpan) {
return;
}
if (spanToJSON(rootSpan).data[SEMANTIC_ATTRIBUTE_SENTRY_OP] !== "http.server") {
return;
}
rootSpan.setAttribute(HTTP_ROUTE, route);
}
const isLifecycleExtType = (variableToCheck) => {
return typeof variableToCheck === "string" && HapiLifecycleMethodNames.has(variableToCheck);
};
const isLifecycleExtEventObj = (variableToCheck) => {
const event = variableToCheck?.type;
return event !== void 0 && isLifecycleExtType(event);
};
const isDirectExtInput = (variableToCheck) => {
return Array.isArray(variableToCheck) && variableToCheck.length <= 3 && isLifecycleExtType(variableToCheck[0]) && typeof variableToCheck[1] === "function";
};
const isPatchableExtMethod = (variableToCheck) => {
return !Array.isArray(variableToCheck);
};
const getRouteMetadata = (route, pluginName) => {
const attributes = {
[HTTP_ROUTE]: route.path,
// eslint-disable-next-line typescript/no-deprecated -- TODO(v11): Replace deprecated attributes
[HTTP_METHOD]: route.method
};
let name;
if (pluginName) {
attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.PLUGIN;
attributes[AttributeNames.PLUGIN_NAME] = pluginName;
name = `${pluginName}: route - ${route.path}`;
} else {
attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.ROUTER;
name = `route - ${route.path}`;
}
return { attributes, name };
};
const getExtMetadata = (extPoint, pluginName, methodName) => {
let baseName = `ext - ${extPoint}`;
if (methodName && methodName !== "method") {
baseName = `ext - ${extPoint} - ${methodName}`;
}
if (pluginName) {
return {
attributes: {
[AttributeNames.EXT_TYPE]: extPoint,
[AttributeNames.HAPI_TYPE]: HapiLayerType.EXT,
[AttributeNames.PLUGIN_NAME]: pluginName
},
name: `${pluginName}: ${baseName}`
};
}
return {
attributes: {
[AttributeNames.EXT_TYPE]: extPoint,
[AttributeNames.HAPI_TYPE]: HapiLayerType.EXT
},
name: baseName
};
};
function startMetadataSpan(metadata, original) {
return startSpan(
{
name: metadata.name,
op: `${metadata.attributes[AttributeNames.HAPI_TYPE]}.hapi`,
attributes: {
...metadata.attributes,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.orchestrion.hapi"
}
},
original
);
}
function wrapRouteHandler(route, pluginName) {
if (route[handlerPatched] === true) return route;
route[handlerPatched] = true;
const wrapHandler = (oldHandler) => {
return function(...params) {
if (!getActiveSpan()) {
return oldHandler.call(this, ...params);
}
setHttpServerSpanRouteAttribute(route.path);
const metadata = getRouteMetadata(route, pluginName);
return startMetadataSpan(metadata, () => oldHandler.call(this, ...params));
};
};
if (typeof route.handler === "function") {
route.handler = wrapHandler(route.handler);
} else if (typeof route.options === "function") {
const oldOptions = route.options;
route.options = function(server) {
const options = oldOptions(server);
if (typeof options.handler === "function") {
options.handler = wrapHandler(options.handler);
}
return options;
};
} else if (typeof route.options?.handler === "function") {
route.options.handler = wrapHandler(route.options.handler);
}
return route;
}
function wrapExtMethods(method, extPoint, pluginName) {
if (Array.isArray(method)) {
for (let i = 0; i < method.length; i++) {
method[i] = wrapExtMethods(method[i], extPoint);
}
return method;
} else if (isPatchableExtMethod(method)) {
if (method[handlerPatched] === true) return method;
method[handlerPatched] = true;
const newHandler = function(...params) {
if (!getActiveSpan()) {
return method.apply(this, params);
}
const metadata = getExtMetadata(extPoint, pluginName, method.name);
return startMetadataSpan(metadata, () => method.apply(void 0, params));
};
newHandler[handlerPatched] = true;
return newHandler;
}
return method;
}
function wrapRouteArguments(args, pluginName) {
const route = args[0];
if (Array.isArray(route)) {
for (let i = 0; i < route.length; i++) {
route[i] = wrapRouteHandler(route[i], pluginName);
}
} else {
args[0] = wrapRouteHandler(route, pluginName);
}
}
function wrapExtArguments(args, pluginName) {
if (Array.isArray(args[0])) {
const eventsList = args[0];
for (let i = 0; i < eventsList.length; i++) {
const eventObj = eventsList[i];
if (isLifecycleExtType(eventObj.type)) {
const lifecycleEventObj = eventObj;
const handler = wrapExtMethods(lifecycleEventObj.method, eventObj.type, pluginName);
lifecycleEventObj.method = handler;
eventsList[i] = lifecycleEventObj;
}
}
return;
} else if (isDirectExtInput(args)) {
const extInput = args;
const method = extInput[1];
const handler = wrapExtMethods(method, extInput[0], pluginName);
args[1] = handler;
return;
} else if (isLifecycleExtEventObj(args[0])) {
const lifecycleEventObj = args[0];
const handler = wrapExtMethods(lifecycleEventObj.method, lifecycleEventObj.type, pluginName);
lifecycleEventObj.method = handler;
}
}
export { getExtMetadata, getRouteMetadata, wrapExtArguments, wrapRouteArguments };
//# sourceMappingURL=hapi-utils.js.map
{"version":3,"file":"hapi-utils.js","sources":["../../../../src/integrations/tracing-channel/hapi-utils.ts"],"sourcesContent":["/*\n * OTel-free, `@hapi/*`-free port of the span-building helpers and handler/ext\n * wrap logic from the vendored `@opentelemetry/instrumentation-hapi`\n * (upstream @opentelemetry/instrumentation-hapi@0.64.0). Span output (names,\n * ops, origins, attributes) is kept byte-identical to that instrumentation;\n * span creation goes through the `@sentry/core` API and the OTel active-span\n * guard is replaced with `getActiveSpan()`.\n */\n\nimport {\n getActiveSpan,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n startSpan,\n} from '@sentry/core';\nimport type {\n LifecycleMethod,\n PatchableExtMethod,\n PatchableServerRoute,\n ServerExtDirectInput,\n ServerExtEventsObject,\n ServerExtEventsRequestObject,\n ServerRequestExtType,\n ServerRoute,\n ServerRouteOptions,\n} from './hapi-types';\n// eslint-disable-next-line typescript/no-deprecated -- TODO(v11): Replace deprecated attributes\nimport { HTTP_METHOD, HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport { AttributeNames, handlerPatched, HapiLayerType, HapiLifecycleMethodNames } from './hapi-types';\n\ntype SpanAttributes = Record<string, string | undefined>;\n\ninterface SpanMetadata {\n attributes: SpanAttributes;\n name: string;\n}\n\n/**\n * Set the `http.route` attribute on the root HTTP server span for the current trace.\n *\n * No-op when there is no active span, no root span, or the root span is not an\n * `http.server` span — so framework instrumentations can call this unconditionally\n * without risking attribute pollution on non-HTTP root spans.\n */\nfunction setHttpServerSpanRouteAttribute(route: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) {\n return;\n }\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) {\n return;\n }\n if (spanToJSON(rootSpan).data[SEMANTIC_ATTRIBUTE_SENTRY_OP] !== 'http.server') {\n return;\n }\n rootSpan.setAttribute(HTTP_ROUTE, route);\n}\n\nconst isLifecycleExtType = (variableToCheck: unknown): variableToCheck is ServerRequestExtType => {\n return typeof variableToCheck === 'string' && HapiLifecycleMethodNames.has(variableToCheck);\n};\n\nconst isLifecycleExtEventObj = (variableToCheck: unknown): variableToCheck is ServerExtEventsRequestObject => {\n const event = (variableToCheck as ServerExtEventsRequestObject)?.type;\n return event !== undefined && isLifecycleExtType(event);\n};\n\nconst isDirectExtInput = (variableToCheck: unknown): variableToCheck is ServerExtDirectInput => {\n return (\n Array.isArray(variableToCheck) &&\n variableToCheck.length <= 3 &&\n isLifecycleExtType(variableToCheck[0]) &&\n typeof variableToCheck[1] === 'function'\n );\n};\n\nconst isPatchableExtMethod = (\n variableToCheck: PatchableExtMethod | PatchableExtMethod[],\n): variableToCheck is PatchableExtMethod => {\n return !Array.isArray(variableToCheck);\n};\n\n/** Build the span name and attributes for a Hapi route. */\nexport const getRouteMetadata = (route: ServerRoute, pluginName?: string): SpanMetadata => {\n const attributes: SpanAttributes = {\n [HTTP_ROUTE]: route.path,\n // eslint-disable-next-line typescript/no-deprecated -- TODO(v11): Replace deprecated attributes\n [HTTP_METHOD]: route.method,\n };\n\n let name;\n if (pluginName) {\n attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.PLUGIN;\n attributes[AttributeNames.PLUGIN_NAME] = pluginName;\n name = `${pluginName}: route - ${route.path}`;\n } else {\n attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.ROUTER;\n name = `route - ${route.path}`;\n }\n\n return { attributes, name };\n};\n\n/** Build the span name and attributes for a Hapi server extension. */\nexport const getExtMetadata = (\n extPoint: ServerRequestExtType,\n pluginName?: string,\n methodName?: string,\n): SpanMetadata => {\n let baseName = `ext - ${extPoint}`;\n if (methodName && methodName !== 'method') {\n // `method` is the default name for the extension in the ServerExtEventsObject format.\n baseName = `ext - ${extPoint} - ${methodName}`;\n }\n if (pluginName) {\n return {\n attributes: {\n [AttributeNames.EXT_TYPE]: extPoint,\n [AttributeNames.HAPI_TYPE]: HapiLayerType.EXT,\n [AttributeNames.PLUGIN_NAME]: pluginName,\n },\n name: `${pluginName}: ${baseName}`,\n };\n }\n return {\n attributes: {\n [AttributeNames.EXT_TYPE]: extPoint,\n [AttributeNames.HAPI_TYPE]: HapiLayerType.EXT,\n },\n name: baseName,\n };\n};\n\nfunction startMetadataSpan(metadata: SpanMetadata, original: () => unknown): unknown {\n return startSpan(\n {\n name: metadata.name,\n op: `${metadata.attributes[AttributeNames.HAPI_TYPE]}.hapi`,\n attributes: {\n ...metadata.attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.orchestrion.hapi',\n },\n },\n original,\n );\n}\n\n/**\n * Patches each individual route handler method in order to create the span. It\n * does not create spans when there is no parent span.\n */\nfunction wrapRouteHandler(route: PatchableServerRoute, pluginName?: string): PatchableServerRoute {\n if (route[handlerPatched] === true) return route;\n route[handlerPatched] = true;\n\n const wrapHandler: (oldHandler: LifecycleMethod) => LifecycleMethod = oldHandler => {\n return function (this: unknown, ...params: Parameters<LifecycleMethod>) {\n if (!getActiveSpan()) {\n return oldHandler.call(this, ...params);\n }\n setHttpServerSpanRouteAttribute(route.path);\n const metadata = getRouteMetadata(route, pluginName);\n return startMetadataSpan(metadata, () => oldHandler.call(this, ...params));\n };\n };\n\n if (typeof route.handler === 'function') {\n route.handler = wrapHandler(route.handler as LifecycleMethod);\n } else if (typeof route.options === 'function') {\n const oldOptions = route.options;\n route.options = function (server: unknown): ServerRouteOptions {\n const options = oldOptions(server);\n if (typeof options.handler === 'function') {\n options.handler = wrapHandler(options.handler as LifecycleMethod);\n }\n return options;\n };\n } else if (typeof route.options?.handler === 'function') {\n route.options.handler = wrapHandler(route.options.handler as LifecycleMethod);\n }\n return route;\n}\n\n/**\n * Wraps request extension methods to add instrumentation to each new extension\n * handler. It does not create spans when there is no parent span.\n */\nfunction wrapExtMethods<T extends PatchableExtMethod | PatchableExtMethod[]>(\n method: T,\n extPoint: ServerRequestExtType,\n pluginName?: string,\n): T {\n if (Array.isArray(method)) {\n for (let i = 0; i < method.length; i++) {\n method[i] = wrapExtMethods(method[i]!, extPoint);\n }\n return method;\n } else if (isPatchableExtMethod(method)) {\n if (method[handlerPatched] === true) return method;\n method[handlerPatched] = true;\n\n const newHandler: PatchableExtMethod = function (this: unknown, ...params: Parameters<LifecycleMethod>) {\n if (!getActiveSpan()) {\n return method.apply(this, params);\n }\n const metadata = getExtMetadata(extPoint, pluginName, method.name);\n return startMetadataSpan(metadata, () => method.apply(undefined, params));\n };\n // Mark the wrapper too (not just the original)\n newHandler[handlerPatched] = true;\n return newHandler as T;\n }\n return method;\n}\n\n/**\n * Wrap the route handler(s) in the live `server.route` arguments array, mutating\n * `args[0]` in place. `args[0]` is either a single route options object or an\n * array of them. Idempotent via the `handlerPatched` marker.\n */\nexport function wrapRouteArguments(args: unknown[], pluginName?: string): void {\n const route = args[0] as PatchableServerRoute | PatchableServerRoute[];\n if (Array.isArray(route)) {\n for (let i = 0; i < route.length; i++) {\n route[i] = wrapRouteHandler(route[i]!, pluginName);\n }\n } else {\n args[0] = wrapRouteHandler(route, pluginName);\n }\n}\n\n/**\n * Wrap the extension method(s) in the live `server.ext` arguments array,\n * mutating `args` in place. Handles the three accepted input shapes:\n * `(eventsArray)`, `(lifecycleEventObject)`, and `(extTypeString, method, options)`.\n * Idempotent via the `handlerPatched` marker.\n */\nexport function wrapExtArguments(args: unknown[], pluginName?: string): void {\n if (Array.isArray(args[0])) {\n const eventsList = args[0] as ServerExtEventsObject[] | ServerExtEventsRequestObject[];\n for (let i = 0; i < eventsList.length; i++) {\n const eventObj = eventsList[i]!;\n if (isLifecycleExtType(eventObj.type)) {\n const lifecycleEventObj = eventObj as ServerExtEventsRequestObject;\n const handler = wrapExtMethods(lifecycleEventObj.method, eventObj.type, pluginName);\n lifecycleEventObj.method = handler;\n eventsList[i] = lifecycleEventObj;\n }\n }\n return;\n } else if (isDirectExtInput(args)) {\n const extInput: ServerExtDirectInput = args;\n const method: PatchableExtMethod = extInput[1];\n const handler = wrapExtMethods(method, extInput[0], pluginName);\n args[1] = handler;\n return;\n } else if (isLifecycleExtEventObj(args[0])) {\n const lifecycleEventObj = args[0];\n const handler = wrapExtMethods(lifecycleEventObj.method, lifecycleEventObj.type, pluginName);\n lifecycleEventObj.method = handler;\n }\n}\n"],"names":[],"mappings":"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"}
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { defineIntegration, debug } from '@sentry/core';
import { DEBUG_BUILD } from '../../debug-build.js';
import { CHANNELS } from '../../orchestrion/channels.js';
import { wrapRouteArguments, wrapExtArguments } from './hapi-utils.js';
const INTEGRATION_NAME = "Hapi";
const _hapiChannelIntegration = (() => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
DEBUG_BUILD && debug.log(`[orchestrion:hapi] subscribing to channels "${CHANNELS.HAPI_ROUTE}" / "${CHANNELS.HAPI_EXT}"`);
diagnosticsChannel.tracingChannel(CHANNELS.HAPI_ROUTE).subscribe({
start(rawCtx) {
const ctx = rawCtx;
wrapRouteArguments(ctx.arguments, ctx.self?.realm?.plugin);
},
end() {
},
asyncStart() {
},
asyncEnd() {
},
error() {
}
});
diagnosticsChannel.tracingChannel(CHANNELS.HAPI_EXT).subscribe({
start(rawCtx) {
const ctx = rawCtx;
wrapExtArguments(ctx.arguments, ctx.self?.realm?.plugin);
},
end() {
},
asyncStart() {
},
asyncEnd() {
},
error() {
}
});
}
};
});
const hapiChannelIntegration = defineIntegration(_hapiChannelIntegration);
export { hapiChannelIntegration };
//# sourceMappingURL=hapi.js.map
{"version":3,"file":"hapi.js","sources":["../../../../src/integrations/tracing-channel/hapi.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn } from '@sentry/core';\nimport { debug, defineIntegration } from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { wrapExtArguments, wrapRouteArguments } from './hapi-utils';\n\n// NOTE: same name as the OTel integration by design — when enabled, the OTel\n// 'Hapi' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Hapi' as const;\n\n/**\n * The shape orchestrion's transform attaches to the `@hapi/hapi` route/ext\n * tracing-channel `context` objects.\n *\n * `arguments` is the *live* args array passed to `server.route` / `server.ext`;\n * we mutate it in place to swap handlers for span-creating proxies. `self` is\n * the hapi server instance: the root server has `self.realm.plugin === undefined`,\n * while a plugin's clone server exposes the registering plugin's name there.\n */\ninterface HapiChannelContext {\n arguments: unknown[];\n self?: { realm?: { plugin?: string } };\n}\n\nconst _hapiChannelIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD &&\n debug.log(`[orchestrion:hapi] subscribing to channels \"${CHANNELS.HAPI_ROUTE}\" / \"${CHANNELS.HAPI_EXT}\"`);\n\n // `subscribe` requires all five lifecycle hooks. We only act on `start`,\n // which orchestrion fires synchronously with the live args array — that's\n // the moment we mutate the handlers in place.\n diagnosticsChannel.tracingChannel(CHANNELS.HAPI_ROUTE).subscribe({\n start(rawCtx) {\n const ctx = rawCtx as HapiChannelContext;\n wrapRouteArguments(ctx.arguments, ctx.self?.realm?.plugin);\n },\n end() {},\n asyncStart() {},\n asyncEnd() {},\n error() {},\n });\n\n diagnosticsChannel.tracingChannel(CHANNELS.HAPI_EXT).subscribe({\n start(rawCtx) {\n const ctx = rawCtx as HapiChannelContext;\n wrapExtArguments(ctx.arguments, ctx.self?.realm?.plugin);\n },\n end() {},\n asyncStart() {},\n asyncEnd() {},\n error() {},\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * EXPERIMENTAL — orchestrion-driven hapi integration. Subscribes to the\n * `orchestrion:@hapi/hapi:route` / `:ext` channels injected into `@hapi/hapi`'s\n * `lib/server.js`. Requires the orchestrion runtime hook or bundler plugin.\n */\nexport const hapiChannelIntegration = defineIntegration(_hapiChannelIntegration);\n"],"names":[],"mappings":";;;;;;AASA,MAAM,gBAAA,GAAmB,MAAA;AAgBzB,MAAM,2BAA2B,MAAM;AACrC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,IAAI,CAAC,mBAAmB,cAAA,EAAgB;AACtC,QAAA;AAAA,MACF;AAEA,MAAA,WAAA,IACE,KAAA,CAAM,IAAI,CAAA,4CAAA,EAA+C,QAAA,CAAS,UAAU,CAAA,KAAA,EAAQ,QAAA,CAAS,QAAQ,CAAA,CAAA,CAAG,CAAA;AAK1G,MAAA,kBAAA,CAAmB,cAAA,CAAe,QAAA,CAAS,UAAU,CAAA,CAAE,SAAA,CAAU;AAAA,QAC/D,MAAM,MAAA,EAAQ;AACZ,UAAA,MAAM,GAAA,GAAM,MAAA;AACZ,UAAA,kBAAA,CAAmB,GAAA,CAAI,SAAA,EAAW,GAAA,CAAI,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,QAC3D,CAAA;AAAA,QACA,GAAA,GAAM;AAAA,QAAC,CAAA;AAAA,QACP,UAAA,GAAa;AAAA,QAAC,CAAA;AAAA,QACd,QAAA,GAAW;AAAA,QAAC,CAAA;AAAA,QACZ,KAAA,GAAQ;AAAA,QAAC;AAAA,OACV,CAAA;AAED,MAAA,kBAAA,CAAmB,cAAA,CAAe,QAAA,CAAS,QAAQ,CAAA,CAAE,SAAA,CAAU;AAAA,QAC7D,MAAM,MAAA,EAAQ;AACZ,UAAA,MAAM,GAAA,GAAM,MAAA;AACZ,UAAA,gBAAA,CAAiB,GAAA,CAAI,SAAA,EAAW,GAAA,CAAI,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,QACzD,CAAA;AAAA,QACA,GAAA,GAAM;AAAA,QAAC,CAAA;AAAA,QACP,UAAA,GAAa;AAAA,QAAC,CAAA;AAAA,QACd,QAAA,GAAW;AAAA,QAAC,CAAA;AAAA,QACZ,KAAA,GAAQ;AAAA,QAAC;AAAA,OACV,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAA,CAAA;AAOO,MAAM,sBAAA,GAAyB,kBAAkB,uBAAuB;;;;"}
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { DB_STATEMENT, NET_PEER_PORT, NET_PEER_NAME, DB_SYSTEM } from '@sentry/conventions/attributes';
import { defineIntegration, debug, waitForTracingChannelBinding, getActiveSpan, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { DEBUG_BUILD } from '../../debug-build.js';
import { CHANNELS } from '../../orchestrion/channels.js';
import { defaultDbStatementSerializer } from '../../redis/redis-statement-serializer.js';
import { bindTracingChannelToSpan } from '../../tracing-channel.js';
const INTEGRATION_NAME = "IORedis";
const ORIGIN = "auto.db.orchestrion.redis";
const ATTR_DB_CONNECTION_STRING = "db.connection_string";
function getConnectionOptions(self) {
return { host: self?.options?.host, port: self?.options?.port };
}
function connectionAttributes(host, port) {
return {
[DB_SYSTEM]: "redis",
[ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`,
[NET_PEER_NAME]: host,
[NET_PEER_PORT]: port,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN
};
}
const _ioredisChannelIntegration = ((options = {}) => {
const responseHook = options.responseHook;
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
DEBUG_BUILD && debug.log(`[orchestrion:ioredis] subscribing to "${CHANNELS.IOREDIS_COMMAND}"/"${CHANNELS.IOREDIS_CONNECT}"`);
const commandChannel = diagnosticsChannel.tracingChannel(
CHANNELS.IOREDIS_COMMAND
);
const connectChannel = diagnosticsChannel.tracingChannel(
CHANNELS.IOREDIS_CONNECT
);
waitForTracingChannelBinding(() => {
bindTracingChannelToSpan(
commandChannel,
(data) => {
if (!getActiveSpan()) {
return void 0;
}
const command = data.arguments?.[0];
if (!command || typeof command !== "object") {
return void 0;
}
const { host, port } = getConnectionOptions(data.self);
const statement = defaultDbStatementSerializer(command.name, command.args ?? []);
return startInactiveSpan({
name: statement,
op: "db",
attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: statement }
});
},
{
beforeSpanEnd(span, data) {
if ("error" in data || !responseHook) {
return;
}
const command = data.arguments?.[0];
if (command) {
runResponseHook(responseHook, span, command, data.result);
}
}
}
);
bindTracingChannelToSpan(connectChannel, (data) => {
if (!getActiveSpan()) {
return void 0;
}
const { host, port } = getConnectionOptions(data.self);
return startInactiveSpan({
name: "connect",
op: "db",
attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: "connect" }
});
});
});
}
};
});
function runResponseHook(hook, span, command, result) {
try {
hook(span, command.name, command.args, result);
} catch {
}
}
const ioredisChannelIntegration = defineIntegration(_ioredisChannelIntegration);
export { ioredisChannelIntegration };
//# sourceMappingURL=ioredis.js.map
{"version":3,"file":"ioredis.js","sources":["../../../../src/integrations/tracing-channel/ioredis.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-deprecated -- we intentionally emit the OLD db/net semconv\n to match `@opentelemetry/instrumentation-ioredis` (and Sentry's `inferDbSpanData`, which keys off\n `db.statement`). TODO(v11): switch to the non-deprecated `db.system.name`/`db.query.text`/\n `server.address`/`server.port` conventions and drop this disable. */\nimport * as diagnosticsChannel from 'node:diagnostics_channel';\nimport { DB_STATEMENT, DB_SYSTEM, NET_PEER_NAME, NET_PEER_PORT } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n debug,\n defineIntegration,\n getActiveSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { defaultDbStatementSerializer } from '../../redis/redis-statement-serializer';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// Distinct from the OTel `Redis` integration, which is composite (node-redis +\n// ioredis + the >=5.11.0 diagnostics_channel subscriber) and stays in the set;\n// only its ioredis monkey-patch is gated off in the node SDK when this is active.\nconst INTEGRATION_NAME = 'IORedis' as const;\n\nconst ORIGIN = 'auto.db.orchestrion.redis';\n\n// todo(v11): Let's drop this as this is already covered with host and port\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\n\n/** Mirrors `@opentelemetry/instrumentation-ioredis`' response hook. Not called for failed commands. */\nexport type IORedisResponseHook = (span: Span, command: string, args: Array<string | Buffer>, result: unknown) => void;\n\nexport interface IORedisChannelIntegrationOptions {\n responseHook?: IORedisResponseHook;\n}\n\n/** Structural type for the command object ioredis passes to `sendCommand`. */\ninterface RedisCommand {\n name: string;\n args: Array<string | Buffer>;\n}\n\ninterface RedisClientLike {\n options?: { host?: string; port?: number };\n}\n\ninterface IORedisCommandContext {\n arguments?: unknown[];\n self?: RedisClientLike;\n result?: unknown;\n error?: unknown;\n}\n\ntype IORedisConnectContext = Omit<IORedisCommandContext, 'arguments'>;\n\nfunction getConnectionOptions(self: RedisClientLike | undefined): { host?: string; port?: number } {\n return { host: self?.options?.host, port: self?.options?.port };\n}\n\nfunction connectionAttributes(host: string | undefined, port: number | undefined): Record<string, unknown> {\n return {\n [DB_SYSTEM]: 'redis',\n [ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`,\n [NET_PEER_NAME]: host,\n [NET_PEER_PORT]: port,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n };\n}\n\nconst _ioredisChannelIntegration = ((options: IORedisChannelIntegrationOptions = {}) => {\n const responseHook = options.responseHook;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD &&\n debug.log(`[orchestrion:ioredis] subscribing to \"${CHANNELS.IOREDIS_COMMAND}\"/\"${CHANNELS.IOREDIS_CONNECT}\"`);\n\n const commandChannel = diagnosticsChannel.tracingChannel<IORedisCommandContext, IORedisCommandContext>(\n CHANNELS.IOREDIS_COMMAND,\n );\n const connectChannel = diagnosticsChannel.tracingChannel<IORedisConnectContext, IORedisConnectContext>(\n CHANNELS.IOREDIS_CONNECT,\n );\n\n // `bindTracingChannelToSpan` uses `bindStore`, which needs the async-context\n // binding that `initOpenTelemetry()` registers after integration `setupOnce` —\n // defer until it's available (matches the native redis diagnostics-channel subscriber).\n waitForTracingChannelBinding(() => {\n bindTracingChannelToSpan(\n commandChannel,\n data => {\n // ioredis' `requireParentSpan` default: only create a span under an active span.\n if (!getActiveSpan()) {\n return undefined;\n }\n const command = data.arguments?.[0] as RedisCommand | undefined;\n if (!command || typeof command !== 'object') {\n return undefined;\n }\n const { host, port } = getConnectionOptions(data.self);\n const statement = defaultDbStatementSerializer(command.name, command.args ?? []);\n return startInactiveSpan({\n name: statement,\n op: 'db',\n attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: statement },\n });\n },\n {\n beforeSpanEnd(span, data) {\n if ('error' in data || !responseHook) {\n return;\n }\n const command = data.arguments?.[0] as RedisCommand | undefined;\n if (command) {\n runResponseHook(responseHook, span, command, data.result);\n }\n },\n },\n );\n\n bindTracingChannelToSpan(connectChannel, data => {\n if (!getActiveSpan()) {\n return undefined;\n }\n const { host, port } = getConnectionOptions(data.self);\n return startInactiveSpan({\n name: 'connect',\n op: 'db',\n attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: 'connect' },\n });\n });\n });\n },\n };\n}) satisfies IntegrationFn;\n\nfunction runResponseHook(hook: IORedisResponseHook, span: Span, command: RedisCommand, result: unknown): void {\n try {\n hook(span, command.name, command.args, result);\n } catch {\n // never let a user-provided response hook break instrumentation\n }\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven ioredis integration. Subscribes to\n * `orchestrion:ioredis:command` / `:connect` (injected into ioredis' `<5.11.0`\n * `sendCommand`/`connect`) and creates db spans matching\n * `@opentelemetry/instrumentation-ioredis`. Requires the orchestrion runtime hook\n * or bundler plugin.\n */\nexport const ioredisChannelIntegration = defineIntegration(_ioredisChannelIntegration);\n"],"names":[],"mappings":"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"}
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { defineIntegration, waitForTracingChannelBinding, debug, _INTERNAL_shouldSkipAiProviderWrapping, resolveAIRecordingOptions, shouldEnableTruncation, extractOpenAiRequestAttributes, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan, addOpenAiRequestAttributes, addOpenAiResponseAttributes, instrumentOpenAiStream } from '@sentry/core';
import { DEBUG_BUILD } from '../../debug-build.js';
import { CHANNELS } from '../../orchestrion/channels.js';
import { bindTracingChannelToSpan } from '../../tracing-channel.js';
const INTEGRATION_NAME = "OpenAI";
const ORIGIN = "auto.ai.orchestrion.openai";
const INSTRUMENTED_CHANNELS = [
{ channel: CHANNELS.OPENAI_CHAT, operation: "chat" },
{ channel: CHANNELS.OPENAI_RESPONSES, operation: "chat" },
{ channel: CHANNELS.OPENAI_EMBEDDINGS, operation: "embeddings" },
{ channel: CHANNELS.OPENAI_CONVERSATIONS, operation: "chat" }
];
let subscribed = false;
const _openaiChannelIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel || subscribed) {
return;
}
subscribed = true;
waitForTracingChannelBinding(() => {
for (const { channel, operation } of INSTRUMENTED_CHANNELS) {
DEBUG_BUILD && debug.log(`[orchestrion:openai] subscribing to channel "${channel}"`);
bindTracingChannelToSpan(
diagnosticsChannel.tracingChannel(channel),
(data) => createGenAiSpan(data, operation, options),
{
beforeSpanEnd: (span, data) => {
addOpenAiResponseAttributes(span, data.result, resolveAIRecordingOptions(options).recordOutputs);
},
// Streaming: the result is a `Stream` consumed later, so instrument it and let it end the span.
deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, options)
}
);
}
});
}
};
});
function createGenAiSpan(data, operation, options) {
if (_INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {
return void 0;
}
const args = data.arguments ?? [];
const params = args[0];
const { recordInputs } = resolveAIRecordingOptions(options);
const enableTruncation = shouldEnableTruncation(options.enableTruncation);
const attributes = extractOpenAiRequestAttributes(args, operation);
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;
const model = params?.model || "unknown";
const span = startInactiveSpan({
name: `${operation} ${model}`,
op: `gen_ai.${operation}`,
attributes
});
if (recordInputs && params) {
addOpenAiRequestAttributes(span, params, operation, enableTruncation);
}
return span;
}
function isAsyncIterable(value) {
return !!value && typeof value[Symbol.asyncIterator] === "function";
}
function wrapStreamResult(span, data, options) {
const result = data.result;
if (!isAsyncIterable(result)) {
return false;
}
const { recordOutputs } = resolveAIRecordingOptions(options);
const iterate = result[Symbol.asyncIterator].bind(result);
const instrumented = instrumentOpenAiStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs ?? false);
result[Symbol.asyncIterator] = () => instrumented;
return true;
}
const openaiChannelIntegration = defineIntegration(_openaiChannelIntegration);
export { openaiChannelIntegration };
//# sourceMappingURL=openai.js.map
{"version":3,"file":"openai.js","sources":["../../../../src/integrations/tracing-channel/openai.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, OpenAiOptions, Span, SpanAttributeValue } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n addOpenAiRequestAttributes,\n addOpenAiResponseAttributes,\n debug,\n defineIntegration,\n extractOpenAiRequestAttributes,\n instrumentOpenAiStream,\n resolveAIRecordingOptions,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// Same name as the OTel integration by design: when enabled, the OTel 'OpenAI'\n// integration is dropped from the default set (see the Node opt-in loader).\nconst INTEGRATION_NAME = 'OpenAI' as const;\n\n// Distinct from the proxy's `auto.ai.openai` so spans from the orchestrion path\n// are attributable separately from the OTel/proxy one.\nconst ORIGIN = 'auto.ai.orchestrion.openai';\n\n// Each instrumented `create` method maps to the gen_ai operation its span reports.\nconst INSTRUMENTED_CHANNELS = [\n { channel: CHANNELS.OPENAI_CHAT, operation: 'chat' },\n { channel: CHANNELS.OPENAI_RESPONSES, operation: 'chat' },\n { channel: CHANNELS.OPENAI_EMBEDDINGS, operation: 'embeddings' },\n { channel: CHANNELS.OPENAI_CONVERSATIONS, operation: 'chat' },\n] as const;\n\n/**\n * The context object orchestrion shares across the tracing-channel lifecycle hooks: `arguments` is the\n * live args array passed to `Completions.create(body, options)`, and Node's `tracingChannel` attaches\n * `result` when the returned promise settles.\n */\ninterface OpenAiChatChannelContext {\n arguments: unknown[];\n result?: unknown;\n}\n\nlet subscribed = false;\n\nconst _openaiChannelIntegration = ((options: OpenAiOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19, and a second `init()` would double-subscribe.\n if (!diagnosticsChannel.tracingChannel || subscribed) {\n return;\n }\n subscribed = true;\n\n // `bindTracingChannelToSpan` needs the async-context binding that `initOpenTelemetry()` registers\n // after `setupOnce` runs, so wait for it before subscribing.\n waitForTracingChannelBinding(() => {\n for (const { channel, operation } of INSTRUMENTED_CHANNELS) {\n DEBUG_BUILD && debug.log(`[orchestrion:openai] subscribing to channel \"${channel}\"`);\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<OpenAiChatChannelContext>(channel),\n data => createGenAiSpan(data, operation, options),\n {\n beforeSpanEnd: (span, data) => {\n addOpenAiResponseAttributes(span, data.result, resolveAIRecordingOptions(options).recordOutputs);\n },\n // Streaming: the result is a `Stream` consumed later, so instrument it and let it end the span.\n deferSpanEnd: ({ span, data }) => wrapStreamResult(span, data, options),\n },\n );\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Build the span for an instrumented `create` call.\n * Returning `undefined` opts the payload out so no span is opened.\n */\nfunction createGenAiSpan(data: OpenAiChatChannelContext, operation: string, options: OpenAiOptions): Span | undefined {\n // langchain drives the openai SDK itself and instruments at its own layer; skip here to avoid double spans.\n if (_INTERNAL_shouldSkipAiProviderWrapping(INTEGRATION_NAME)) {\n return undefined;\n }\n\n const args = data.arguments ?? [];\n const params = args[0] as Record<string, unknown> | undefined;\n\n const { recordInputs } = resolveAIRecordingOptions(options);\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n\n const attributes = extractOpenAiRequestAttributes(args, operation);\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN;\n const model = (params?.model as string) || 'unknown';\n\n const span = startInactiveSpan({\n name: `${operation} ${model}`,\n op: `gen_ai.${operation}`,\n attributes: attributes as Record<string, SpanAttributeValue>,\n });\n\n if (recordInputs && params) {\n addOpenAiRequestAttributes(span, params, operation, enableTruncation);\n }\n\n return span;\n}\n\ntype AsyncIterableStream = { [Symbol.asyncIterator]: () => AsyncIterator<unknown> };\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterableStream {\n return !!value && typeof (value as AsyncIterableStream)[Symbol.asyncIterator] === 'function';\n}\n\n/**\n * For a streaming `create({ stream: true })` the result is a `Stream` the caller consumes later. We can't\n * swap what `create` returns, but the `Stream` in `data.result` is the same instance the caller holds and\n * `asyncEnd` fires before the caller iterates — so we patch its async iterator in place to run through\n * `instrumentOpenAiStream`, which accumulates the streamed attributes and ends the span when iteration finishes.\n * Only a streaming call resolves to an async-iterable, so that check alone distinguishes it. Returns `true`\n * to hand span-ending ownership to `instrumentOpenAiStream`; `false` for non-streaming/errored results, which end\n * via the normal `beforeSpanEnd` path.\n */\nfunction wrapStreamResult(span: Span, data: OpenAiChatChannelContext, options: OpenAiOptions): boolean {\n const result = data.result;\n if (!isAsyncIterable(result)) {\n return false;\n }\n\n const { recordOutputs } = resolveAIRecordingOptions(options);\n const iterate = result[Symbol.asyncIterator].bind(result);\n const instrumented = instrumentOpenAiStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs ?? false);\n result[Symbol.asyncIterator] = () => instrumented;\n\n return true;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven OpenAI integration. Subscribes to the `orchestrion:openai:*`\n * diagnostics_channels injected into `openai`'s `create` methods (chat completions, responses, embeddings,\n * conversations), so it requires the orchestrion runtime hook or bundler plugin.\n */\nexport const openaiChannelIntegration = defineIntegration(_openaiChannelIntegration);\n"],"names":[],"mappings":"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"}
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { defineIntegration, waitForTracingChannelBinding, debug, getActiveSpan, getCurrentScope, startInactiveSpan, SPAN_KIND, bindScopeToEmitter, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { DEBUG_BUILD } from '../../debug-build.js';
import { CHANNELS } from '../../orchestrion/channels.js';
import { bindTracingChannelToSpan } from '../../tracing-channel.js';
const INTEGRATION_NAME = "Postgres";
const ORIGIN = "auto.db.orchestrion.postgres";
const ATTR_DB_SYSTEM = "db.system";
const ATTR_DB_NAME = "db.name";
const ATTR_DB_CONNECTION_STRING = "db.connection_string";
const ATTR_DB_USER = "db.user";
const ATTR_DB_STATEMENT = "db.statement";
const ATTR_NET_PEER_NAME = "net.peer.name";
const ATTR_NET_PEER_PORT = "net.peer.port";
const ATTR_PG_PLAN = "db.postgresql.plan";
const ATTR_PG_IDLE_TIMEOUT = "db.postgresql.idle.timeout.millis";
const ATTR_PG_MAX_CLIENT = "db.postgresql.max.client";
const DB_SYSTEM_POSTGRESQL = "postgresql";
const SPAN_QUERY_FALLBACK = "pg.query";
const SPAN_CONNECT = "pg.connect";
const SPAN_POOL_CONNECT = "pg-pool.connect";
const _postgresChannelIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
waitForTracingChannelBinding(() => {
subscribeQueryLikeChannel(CHANNELS.PG_QUERY, querySpanOptions, { deferStreamedResult: true });
if (!options.ignoreConnectSpans) {
subscribeQueryLikeChannel(CHANNELS.PG_CONNECT, connectSpanOptions);
subscribeQueryLikeChannel(CHANNELS.PGPOOL_CONNECT, poolConnectSpanOptions);
}
});
}
};
});
function subscribeQueryLikeChannel(channelName, getSpanOptions, { deferStreamedResult = false } = {}) {
DEBUG_BUILD && debug.log(`[orchestrion:pg] subscribing to channel "${channelName}"`);
bindTracingChannelToSpan(
diagnosticsChannel.tracingChannel(channelName),
(data) => {
if (!getActiveSpan()) {
return void 0;
}
data._sentryCallerScope = getCurrentScope();
return startInactiveSpan({ ...getSpanOptions(data), kind: SPAN_KIND.CLIENT });
},
// `connect`/`pool-connect` resolve with a persistent `Client` (itself an
// `EventEmitter`), which is NOT a streamed result. Deferring their span
// to that emitter's `'end'`/`'error'` would keep it open for the whole
// connection lifetime, so it never ends in time and is dropped. Only
// `query` can return a streamable `Submittable`, so only it defers.
deferStreamedResult ? {
// Streamable `Submittable` (e.g. `client.query(new Query())`)
// returns an emitter that orchestrion stores on `ctx.result` while
// firing no async events; the query isn't done until the emitter
// emits `'end'`/`'error'`. Defer ending to those events for that
// path; the callback, promise, and sync-throw paths carry no
// emitter, so the helper ends the span as usual.
deferSpanEnd({ data, end }) {
const result = data.result;
if (!result || typeof result !== "object" || !hasOnMethod(result)) {
return false;
}
const callerScope = data._sentryCallerScope;
if (callerScope) {
bindScopeToEmitter(result, callerScope);
}
result.on("error", (err) => end(err));
result.on("end", () => end());
return true;
}
} : void 0
);
}
function querySpanOptions(ctx) {
const params = ctx.self?.connectionParameters ?? {};
const queryConfig = extractQueryConfig(ctx.arguments);
return {
// The description is the SQL statement
name: queryConfig?.text ?? SPAN_QUERY_FALLBACK,
op: "db",
attributes: {
...getConnectionAttributes(params),
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[ATTR_DB_STATEMENT]: queryConfig?.text || void 0,
[ATTR_PG_PLAN]: typeof queryConfig?.name === "string" ? queryConfig.name : void 0
}
};
}
function connectSpanOptions(ctx) {
const params = ctx.self?.connectionParameters ?? {};
return { name: SPAN_CONNECT, op: "db", attributes: getConnectionAttributes(params) };
}
function poolConnectSpanOptions(ctx) {
const opts = ctx.self?.options ?? {};
return { name: SPAN_POOL_CONNECT, op: "db", attributes: getPoolConnectionAttributes(opts) };
}
function hasOnMethod(obj) {
return "on" in obj && typeof obj.on === "function";
}
function extractQueryConfig(args) {
const arg0 = args[0];
if (typeof arg0 === "string") {
return { text: arg0 };
}
if (arg0 && typeof arg0 === "object" && typeof arg0.text === "string") {
const obj = arg0;
return { text: obj.text, name: obj.name };
}
return void 0;
}
function getConnectionAttributes(params) {
return {
[ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,
[ATTR_DB_CONNECTION_STRING]: getConnectionString(params),
[ATTR_DB_NAME]: params.database,
[ATTR_DB_USER]: params.user,
[ATTR_NET_PEER_NAME]: params.host,
[ATTR_NET_PEER_PORT]: Number.isInteger(params.port) ? params.port : void 0
};
}
function getPoolConnectionAttributes(opts) {
let url;
try {
url = opts.connectionString ? new URL(opts.connectionString) : void 0;
} catch {
url = void 0;
}
const database = url?.pathname.slice(1) || opts.database;
const host = url?.hostname || opts.host;
const port = Number(url?.port) || (Number.isInteger(opts.port) ? opts.port : void 0);
const user = url?.username || opts.user;
return {
[ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,
[ATTR_DB_CONNECTION_STRING]: getConnectionString(opts),
[ATTR_PG_IDLE_TIMEOUT]: opts.idleTimeoutMillis,
[ATTR_PG_MAX_CLIENT]: opts.max,
[ATTR_DB_NAME]: database,
[ATTR_NET_PEER_PORT]: port,
// these two come from a url parse and slice, can be ''
[ATTR_NET_PEER_NAME]: host || void 0,
[ATTR_DB_USER]: user || void 0
};
}
function getConnectionString(params) {
if (params.connectionString) {
try {
const url = new URL(params.connectionString);
url.username = "";
url.password = "";
return url.toString();
} catch {
return "postgresql://localhost:5432/";
}
}
const host = params.host || "localhost";
const port = params.port || 5432;
const database = params.database || "";
return `postgresql://${host}:${port}/${database}`;
}
const postgresChannelIntegration = defineIntegration(_postgresChannelIntegration);
export { postgresChannelIntegration };
//# sourceMappingURL=postgres.js.map
{"version":3,"file":"postgres.js","sources":["../../../../src/integrations/tracing-channel/postgres.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, Scope, SpanAttributes } from '@sentry/core';\nimport {\n bindScopeToEmitter,\n debug,\n defineIntegration,\n getActiveSpan,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// NOTE: this uses the same name as the OTel integration by design.\n// When enabled, the OTel 'Postgres' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Postgres' as const;\n\n// Only the query span carries an origin (the connect/pool-connect spans don't,\n// so they default to 'manual').\nconst ORIGIN = 'auto.db.orchestrion.postgres';\n\n// OpenTelemetry \"OLD\" db/net semantic-conventions, inlined to keep this\n// integration free of `@opentelemetry/*` deps.\nconst ATTR_DB_SYSTEM = 'db.system';\nconst ATTR_DB_NAME = 'db.name';\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nconst ATTR_DB_USER = 'db.user';\nconst ATTR_DB_STATEMENT = 'db.statement';\nconst ATTR_NET_PEER_NAME = 'net.peer.name';\nconst ATTR_NET_PEER_PORT = 'net.peer.port';\nconst ATTR_PG_PLAN = 'db.postgresql.plan';\nconst ATTR_PG_IDLE_TIMEOUT = 'db.postgresql.idle.timeout.millis';\nconst ATTR_PG_MAX_CLIENT = 'db.postgresql.max.client';\nconst DB_SYSTEM_POSTGRESQL = 'postgresql';\n\n// We set `op: 'db'` and the SQL description directly here (same as mysql\n// orchestrion) rather than relying on the OTel pipeline's `inferDbSpanData`\n// processor, which only runs in the node SDK, so setting them here is what\n// makes the spans correct on the other runtimes\n//\n// The user-visible span is identical to OTel: query spans are named after\n// `db.statement`; connect/pool-connect spans keep these names.\nconst SPAN_QUERY_FALLBACK = 'pg.query';\nconst SPAN_CONNECT = 'pg.connect';\nconst SPAN_POOL_CONNECT = 'pg-pool.connect';\n\n/**\n * The shape orchestrion's transform attaches to the tracing-channel `context`. Documented here rather\n * than imported because orchestrion's runtime doesn't export it.\n */\ninterface PgChannelContext {\n // The live args array passed to the wrapped `query`/`connect` call.\n arguments: unknown[];\n self?: unknown;\n result?: unknown;\n error?: unknown;\n // The caller's scope, captured at `start` and replayed onto a streamed `Submittable` emitter (see below).\n _sentryCallerScope?: Scope;\n}\n\ninterface PgConnectionParams {\n database?: string;\n host?: string;\n port?: number;\n user?: string;\n connectionString?: string;\n}\n\ninterface PgPoolOptions extends PgConnectionParams {\n idleTimeoutMillis?: number;\n // pg-pool stores the max pool size as `max` (defaulting it to 10 in its\n // constructor). The OTel pg instrumentation reads a `maxClient` field that\n // pg-pool never sets, so its `db.postgresql.max.client` attribute is always\n // dropped; we read the real `max` so the attribute is actually populated.\n max?: number;\n}\n\nconst _postgresChannelIntegration = ((options: { ignoreConnectSpans?: boolean } = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19 so do nothing in that case.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n waitForTracingChannelBinding(() => {\n // Query spans: `pg`/native `Client.prototype.query`. Only this channel can return a streamable\n // `Submittable` result, so it's the only one that defers span-ending to the emitter (see below).\n subscribeQueryLikeChannel(CHANNELS.PG_QUERY, querySpanOptions, { deferStreamedResult: true });\n\n // Connect spans, gated by `ignoreConnectSpans` (same as OTel pg).\n // `Client.prototype.connect` (pg + native)\n // and `Pool.prototype.connect` (pg-pool).\n if (!options.ignoreConnectSpans) {\n subscribeQueryLikeChannel(CHANNELS.PG_CONNECT, connectSpanOptions);\n subscribeQueryLikeChannel(CHANNELS.PGPOOL_CONNECT, poolConnectSpanOptions);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Subscribe to a pg tracing-channel and manage a span across its lifecycle.\n * Shared by the query/connect/pool-connect channels. They differ only in how\n * the span's name + attributes are built (`getSpanOptions`), and whether the\n * result can be a streamable emitter (`deferStreamedResult`, query-only).\n */\nfunction subscribeQueryLikeChannel(\n channelName: string,\n getSpanOptions: (ctx: PgChannelContext) => { name: string; op: string; attributes: SpanAttributes },\n { deferStreamedResult = false }: { deferStreamedResult?: boolean } = {},\n): void {\n DEBUG_BUILD && debug.log(`[orchestrion:pg] subscribing to channel \"${channelName}\"`);\n\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<PgChannelContext>(channelName),\n data => {\n // Only instrument when there's an active span; returning `undefined` opts this call out entirely,\n // leaving the active context untouched (e.g. connects issued during app startup).\n if (!getActiveSpan()) {\n return undefined;\n }\n\n // Capture the caller's scope while still synchronously inside the call, for the streamed path:\n // pg dispatches a `Submittable` emitter's events outside the original async scope, so `deferSpanEnd`\n // replays this scope onto that emitter.\n data._sentryCallerScope = getCurrentScope();\n\n // `kind: CLIENT` mirrors the OTel pg instrumentation, so the emitted\n // `otel.kind` matches across the OTel and diagnostics-channel paths.\n return startInactiveSpan({ ...getSpanOptions(data), kind: SPAN_KIND.CLIENT });\n },\n // `connect`/`pool-connect` resolve with a persistent `Client` (itself an\n // `EventEmitter`), which is NOT a streamed result. Deferring their span\n // to that emitter's `'end'`/`'error'` would keep it open for the whole\n // connection lifetime, so it never ends in time and is dropped. Only\n // `query` can return a streamable `Submittable`, so only it defers.\n deferStreamedResult\n ? {\n // Streamable `Submittable` (e.g. `client.query(new Query())`)\n // returns an emitter that orchestrion stores on `ctx.result` while\n // firing no async events; the query isn't done until the emitter\n // emits `'end'`/`'error'`. Defer ending to those events for that\n // path; the callback, promise, and sync-throw paths carry no\n // emitter, so the helper ends the span as usual.\n deferSpanEnd({ data, end }) {\n const result = data.result;\n if (!result || typeof result !== 'object' || !hasOnMethod(result)) {\n return false;\n }\n\n // Replay the caller's scope onto the emitter so listeners theu\n // user attaches after the call returns (and any spans they start)\n // nest under the caller, not a fresh root trace.\n const callerScope = data._sentryCallerScope;\n if (callerScope) {\n bindScopeToEmitter(result, callerScope);\n }\n\n result.on('error', err => end(err));\n result.on('end', () => end());\n\n return true;\n },\n }\n : undefined,\n );\n}\n\nfunction querySpanOptions(ctx: PgChannelContext): { name: string; op: string; attributes: SpanAttributes } {\n const params = (ctx.self as { connectionParameters?: PgConnectionParams } | undefined)?.connectionParameters ?? {};\n const queryConfig = extractQueryConfig(ctx.arguments);\n return {\n // The description is the SQL statement\n name: queryConfig?.text ?? SPAN_QUERY_FALLBACK,\n op: 'db',\n attributes: {\n ...getConnectionAttributes(params),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [ATTR_DB_STATEMENT]: queryConfig?.text || undefined,\n [ATTR_PG_PLAN]: typeof queryConfig?.name === 'string' ? queryConfig.name : undefined,\n },\n };\n}\n\nfunction connectSpanOptions(ctx: PgChannelContext): { name: string; op: string; attributes: SpanAttributes } {\n const params = (ctx.self as { connectionParameters?: PgConnectionParams } | undefined)?.connectionParameters ?? {};\n // No origin set -> defaults to 'manual'\n return { name: SPAN_CONNECT, op: 'db', attributes: getConnectionAttributes(params) };\n}\n\nfunction poolConnectSpanOptions(ctx: PgChannelContext): { name: string; op: string; attributes: SpanAttributes } {\n const opts = (ctx.self as { options?: PgPoolOptions } | undefined)?.options ?? {};\n return { name: SPAN_POOL_CONNECT, op: 'db', attributes: getPoolConnectionAttributes(opts) };\n}\n\nfunction hasOnMethod(obj: object): obj is { on: (event: string, listener: (arg?: unknown) => void) => unknown } {\n return 'on' in obj && typeof (obj as { on?: unknown }).on === 'function';\n}\n\n// `client.query(text, cb?)`, `client.query(text, values, cb?)`, and\n// `client.query(configObj, cb?)` are all valid; normalize to `{ text, name }`\n// (the only fields the span needs). Returns undefined for invalid args.\nfunction extractQueryConfig(args: unknown[]): { text: string; name?: unknown } | undefined {\n const arg0 = args[0];\n if (typeof arg0 === 'string') {\n return { text: arg0 };\n }\n if (arg0 && typeof arg0 === 'object' && typeof (arg0 as { text?: unknown }).text === 'string') {\n const obj = arg0 as { text: string; name?: unknown };\n return { text: obj.text, name: obj.name };\n }\n return undefined;\n}\n\nfunction getConnectionAttributes(params: PgConnectionParams): SpanAttributes {\n return {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),\n [ATTR_DB_NAME]: params.database,\n [ATTR_DB_USER]: params.user,\n [ATTR_NET_PEER_NAME]: params.host,\n [ATTR_NET_PEER_PORT]: Number.isInteger(params.port) ? params.port : undefined,\n };\n}\n\nfunction getPoolConnectionAttributes(opts: PgPoolOptions): SpanAttributes {\n let url: URL | undefined;\n try {\n url = opts.connectionString ? new URL(opts.connectionString) : undefined;\n } catch {\n url = undefined;\n }\n const database = url?.pathname.slice(1) || opts.database;\n const host = url?.hostname || opts.host;\n // Mirror OTel's `getSemanticAttributesFromPoolConnection`: prefer the URL's\n // port, but fall back to an explicit `opts.port` when the connection string\n // omits it (`Number('')` / `Number(undefined)` -> falsy).\n const port = Number(url?.port) || (Number.isInteger(opts.port) ? opts.port : undefined);\n const user = url?.username || opts.user;\n return {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_POSTGRESQL,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(opts),\n [ATTR_PG_IDLE_TIMEOUT]: opts.idleTimeoutMillis,\n [ATTR_PG_MAX_CLIENT]: opts.max,\n [ATTR_DB_NAME]: database,\n [ATTR_NET_PEER_PORT]: port,\n // these two come from a url parse and slice, can be ''\n [ATTR_NET_PEER_NAME]: host || undefined,\n [ATTR_DB_USER]: user || undefined,\n };\n}\n\n// Builds `postgresql://host:port/database`, masking credentials when a raw\n// connection string was provided.\nfunction getConnectionString(params: PgConnectionParams): string {\n if (params.connectionString) {\n try {\n const url = new URL(params.connectionString);\n url.username = '';\n url.password = '';\n return url.toString();\n } catch {\n return 'postgresql://localhost:5432/';\n }\n }\n const host = params.host || 'localhost';\n const port = params.port || 5432;\n const database = params.database || '';\n return `postgresql://${host}:${port}/${database}`;\n}\n\n/**\n * EXPERIMENTAL: orchestrion-driven `pg` (node-postgres) integration.\n *\n * Subscribes to the `orchestrion:pg:query`/`:connect` and\n * `orchestrion:pg-pool:connect` diagnostics_channels that the orchestrion code\n * transform injects into `pg`'s `Client.prototype.query`/`connect`\n * and `pg-pool`'s `Pool.prototype.connect`. Requires the orchestrion runtime\n * hook or bundler plugin to be active.\n */\nexport const postgresChannelIntegration = defineIntegration(_postgresChannelIntegration);\n"],"names":[],"mappings":"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"}
import { defineIntegration, extendIntegration, waitForTracingChannelBinding } from '@sentry/core';
import { vercelAiIntegration } from '../../vercel-ai/index.js';
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { subscribeVercelAiOrchestrionChannels } from '../../vercel-ai/vercel-ai-orchestrion-v6-subscriber.js';
const _vercelAiChannelIntegration = ((options = {}) => {
const parentIntegration = vercelAiIntegration(options);
return extendIntegration(parentIntegration, {
options,
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
waitForTracingChannelBinding(() => {
subscribeVercelAiOrchestrionChannels(diagnosticsChannel.tracingChannel, options);
});
}
});
});
const vercelAiChannelIntegration = defineIntegration(_vercelAiChannelIntegration);
export { vercelAiChannelIntegration };
//# sourceMappingURL=vercel-ai.js.map
{"version":3,"file":"vercel-ai.js","sources":["../../../../src/integrations/tracing-channel/vercel-ai.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration, extendIntegration, waitForTracingChannelBinding } from '@sentry/core';\nimport { vercelAiIntegration as baseVercelAiIntegration } from '../../vercel-ai';\nimport * as dc from 'node:diagnostics_channel';\nimport { subscribeVercelAiOrchestrionChannels } from '../../vercel-ai/vercel-ai-orchestrion-v6-subscriber';\n\ntype VercelAiOptions = Parameters<typeof baseVercelAiIntegration>[0];\n\n// In channel-based (orchestrion) mode we emit our own `gen_ai.*` spans from the\n// diagnostics channels. The `ai` SDK would otherwise emit its own native\n// OpenTelemetry spans whenever the user enables `experimental_telemetry`, which\n// would be duplicates. Rather than dropping those after the fact, the v6\n// subscriber suppresses them at the source: it flips the wrapped call's\n// `experimental_telemetry.isEnabled` to `false`, so `ai` falls back to its\n// internal no-op tracer and never creates the native spans in the first place.\n// See `subscribeVercelAiOrchestrionChannels`.\nconst _vercelAiChannelIntegration = ((options: VercelAiOptions = {}) => {\n const parentIntegration = baseVercelAiIntegration(options);\n\n return extendIntegration(parentIntegration, {\n options,\n setupOnce() {\n // Bail if this is not available\n if (!dc.tracingChannel) {\n return;\n }\n\n waitForTracingChannelBinding(() => {\n subscribeVercelAiOrchestrionChannels(dc.tracingChannel, options);\n });\n },\n });\n}) satisfies IntegrationFn;\n\n/**\n * Auto-instrument the `ai` SDK. Supported are:\n * - v7 via native `ai:telemetry` tracing channel\n * - v6 via orchestrion `orchestrion:ai:*` channels\n */\nexport const vercelAiChannelIntegration = defineIntegration(_vercelAiChannelIntegration);\n"],"names":["baseVercelAiIntegration","dc"],"mappings":";;;;;AAgBA,MAAM,2BAAA,IAA+B,CAAC,OAAA,GAA2B,EAAC,KAAM;AACtE,EAAA,MAAM,iBAAA,GAAoBA,oBAAwB,OAAO,CAAA;AAEzD,EAAA,OAAO,kBAAkB,iBAAA,EAAmB;AAAA,IAC1C,OAAA;AAAA,IACA,SAAA,GAAY;AAEV,MAAA,IAAI,CAACC,mBAAG,cAAA,EAAgB;AACtB,QAAA;AAAA,MACF;AAEA,MAAA,4BAAA,CAA6B,MAAM;AACjC,QAAA,oCAAA,CAAqCA,kBAAA,CAAG,gBAAgB,OAAO,CAAA;AAAA,MACjE,CAAC,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH,CAAA,CAAA;AAOO,MAAM,0BAAA,GAA6B,kBAAkB,2BAA2B;;;;"}
import { defineIntegration, waitForTracingChannelBinding } from '@sentry/core';
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { subscribeMongooseDiagnosticChannels } from './mongoose-dc-subscriber.js';
const _mongooseIntegration = (() => {
return {
name: "Mongoose",
setupOnce() {
if (!diagnosticsChannel.tracingChannel) {
return;
}
waitForTracingChannelBinding(() => {
subscribeMongooseDiagnosticChannels(diagnosticsChannel.tracingChannel);
});
}
};
});
const mongooseIntegration = defineIntegration(_mongooseIntegration);
export { mongooseIntegration };
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../../src/mongoose/index.ts"],"sourcesContent":["import { defineIntegration, type IntegrationFn, waitForTracingChannelBinding } from '@sentry/core';\nimport * as dc from 'node:diagnostics_channel';\nimport { subscribeMongooseDiagnosticChannels } from './mongoose-dc-subscriber';\n\nconst _mongooseIntegration = (() => {\n return {\n name: 'Mongoose',\n setupOnce() {\n // Bail on Node <= 18.18.0, where `tracingChannel` does not exist.\n if (!dc.tracingChannel) {\n return;\n }\n\n // Subscribe to mongoose's native tracing channels (mongoose >= 9.7).\n // This is a no-op on versions that don't publish to the channels, so it is always safe to call.\n waitForTracingChannelBinding(() => {\n subscribeMongooseDiagnosticChannels(dc.tracingChannel);\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Auto-instrument the [mongoose](https://www.npmjs.com/package/mongoose) library via its native\n * `node:diagnostics_channel` tracing channels (mongoose >= 9.7).\n *\n * On older mongoose versions the channels are never published to, so this integration is inert and\n * the IITM-based patcher (gated to `< 9.7.0`) handles instrumentation instead.\n */\nexport const mongooseIntegration = defineIntegration(_mongooseIntegration);\n"],"names":["dc"],"mappings":";;;;AAIA,MAAM,wBAAwB,MAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,SAAA,GAAY;AAEV,MAAA,IAAI,CAACA,mBAAG,cAAA,EAAgB;AACtB,QAAA;AAAA,MACF;AAIA,MAAA,4BAAA,CAA6B,MAAM;AACjC,QAAA,mCAAA,CAAoCA,mBAAG,cAAc,CAAA;AAAA,MACvD,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAA,CAAA;AASO,MAAM,mBAAA,GAAsB,kBAAkB,oBAAoB;;;;"}
import { SERVER_PORT, SERVER_ADDRESS, DB_OPERATION_BATCH_SIZE, DB_QUERY_TEXT, DB_NAMESPACE, DB_COLLECTION_NAME, DB_OPERATION_NAME, DB_SYSTEM_NAME } from '@sentry/conventions/attributes';
import { debug, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { DEBUG_BUILD } from '../debug-build.js';
import { bindTracingChannelToSpan } from '../tracing-channel.js';
const MONGOOSE_DC_CHANNEL_QUERY = "mongoose:query";
const MONGOOSE_DC_CHANNEL_AGGREGATE = "mongoose:aggregate";
const MONGOOSE_DC_CHANNEL_MODEL_SAVE = "mongoose:model:save";
const MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = "mongoose:model:insertMany";
const MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = "mongoose:model:bulkWrite";
const MONGOOSE_DC_CHANNEL_CURSOR_NEXT = "mongoose:cursor:next";
const ORIGIN = "auto.db.mongoose.diagnostic_channel";
const DB_SYSTEM_NAME_VALUE_MONGODB = "mongodb";
const MAX_REDACTION_DEPTH = 10;
let subscribed = false;
function subscribeMongooseDiagnosticChannels(tracingChannel) {
if (subscribed) {
return;
}
subscribed = true;
try {
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_QUERY);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_AGGREGATE);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_SAVE);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE);
setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_CURSOR_NEXT);
} catch {
DEBUG_BUILD && debug.log("Mongoose node:diagnostics_channel subscription failed.");
}
}
function setupChannel(tracingChannel, channelName) {
bindTracingChannelToSpan(tracingChannel(channelName), (data) => {
const collection = data.collection;
const queryText = redactMongoQuery(data.args?.pipeline ?? data.args?.filter);
const batchSize = getBatchSize(data);
return startInactiveSpan({
name: collection ? `mongoose.${collection}.${data.operation}` : `mongoose.${data.operation}`,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "db",
[DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_MONGODB,
[DB_OPERATION_NAME]: data.operation,
[DB_COLLECTION_NAME]: collection ?? void 0,
[DB_NAMESPACE]: data.database ?? void 0,
[DB_QUERY_TEXT]: queryText ?? void 0,
[DB_OPERATION_BATCH_SIZE]: batchSize ?? void 0,
[SERVER_ADDRESS]: data.serverAddress ?? void 0,
[SERVER_PORT]: data.serverPort ?? void 0
}
});
});
}
function getBatchSize(data) {
const args = data.args;
const batch = data.operation === "insertMany" ? args?.docs : data.operation === "bulkWrite" ? args?.ops : void 0;
return Array.isArray(batch) && batch.length > 1 ? batch.length : void 0;
}
function redactMongoQuery(value) {
if (value == null) {
return void 0;
}
try {
const redacted = redactValue(value, 0);
const text = JSON.stringify(redacted);
return text == null || text === "{}" || text === "[]" ? void 0 : text;
} catch {
return void 0;
}
}
function redactValue(value, depth) {
if (depth > MAX_REDACTION_DEPTH) {
return "?";
}
if (Array.isArray(value)) {
return value.map((item) => redactValue(item, depth + 1));
}
if (value && typeof value === "object") {
const out = {};
for (const key of Object.keys(value)) {
out[key] = redactValue(value[key], depth + 1);
}
return out;
}
return "?";
}
export { MONGOOSE_DC_CHANNEL_AGGREGATE, MONGOOSE_DC_CHANNEL_CURSOR_NEXT, MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE, MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY, MONGOOSE_DC_CHANNEL_MODEL_SAVE, MONGOOSE_DC_CHANNEL_QUERY, subscribeMongooseDiagnosticChannels };
//# sourceMappingURL=mongoose-dc-subscriber.js.map
{"version":3,"file":"mongoose-dc-subscriber.js","sources":["../../../src/mongoose/mongoose-dc-subscriber.ts"],"sourcesContent":["import type { TracingChannel } from 'node:diagnostics_channel';\nimport {\n DB_COLLECTION_NAME,\n DB_NAMESPACE,\n DB_OPERATION_BATCH_SIZE,\n DB_OPERATION_NAME,\n DB_QUERY_TEXT,\n DB_SYSTEM_NAME,\n SERVER_ADDRESS,\n SERVER_PORT,\n} from '@sentry/conventions/attributes';\nimport { debug, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { bindTracingChannelToSpan } from '../tracing-channel';\n\n// Channel names published by mongoose >= 9.7.0 (see mongoose `lib/tracing.js`,\n// `lib/query.js`, `lib/aggregate.js`, `lib/model.js` and `lib/cursor/*`).\n// Hardcoded so the subscriber does not have to import mongoose — the channels\n// just have to be subscribed to before the user's mongoose code publishes.\nexport const MONGOOSE_DC_CHANNEL_QUERY = 'mongoose:query';\nexport const MONGOOSE_DC_CHANNEL_AGGREGATE = 'mongoose:aggregate';\nexport const MONGOOSE_DC_CHANNEL_MODEL_SAVE = 'mongoose:model:save';\nexport const MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = 'mongoose:model:insertMany';\nexport const MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = 'mongoose:model:bulkWrite';\nexport const MONGOOSE_DC_CHANNEL_CURSOR_NEXT = 'mongoose:cursor:next';\n\nconst ORIGIN = 'auto.db.mongoose.diagnostic_channel';\nconst DB_SYSTEM_NAME_VALUE_MONGODB = 'mongodb';\n\n// Cap recursion so a self-referential or pathologically deep query can never\n// stall (or blow the stack in) instrumentation.\nconst MAX_REDACTION_DEPTH = 10;\n\n/**\n * Shape of the context object mongoose >= 9.7.0 publishes on its tracing\n * channels (mongoose's `TracingContext`, see `types/tracing.d.ts`).\n *\n * Node's `tracePromise` mutates this same object with `result`/`error` once the\n * operation settles, which `bindTracingChannelToSpan` reads in its lifecycle\n * handlers — hence both are declared optional here.\n *\n * Unlike redis/ioredis, mongoose does NOT pre-sanitize the payload, so `args`\n * carries the raw user query. We redact it before emitting `db.query.text`.\n */\nexport interface MongooseTracingData {\n operation: string;\n /** Absent for connection-level `aggregate()` calls, which have no model/collection. */\n collection?: string;\n database?: string;\n serverAddress?: string;\n serverPort?: number;\n /** Cursor channels only: the cursor's fetch batch size and tailable flag. */\n batchSize?: number;\n tailable?: boolean;\n /**\n * Operation-specific arguments. `filter` (queries/cursors) and `pipeline`\n * (aggregations) carry the query shape; `docs`/`ops` carry batch payloads.\n */\n args?: {\n filter?: unknown;\n pipeline?: unknown;\n docs?: unknown;\n ops?: unknown;\n [key: string]: unknown;\n };\n result?: unknown;\n error?: Error;\n}\n\n/**\n * Platform-provided factory that creates a native tracing channel for the given name. The\n * subscriber binds the span and its lifecycle onto the channel via `bindTracingChannelToSpan`,\n * which propagates the active span through the runtime's async context.\n *\n * Node passes `node:diagnostics_channel`'s `tracingChannel` directly.\n */\nexport type MongooseTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;\n\nlet subscribed = false;\n\n/**\n * Subscribe Sentry span handlers to mongoose's diagnostics-channel events\n * (`mongoose:query`, `:aggregate`, `:model:save`, `:model:insertMany`,\n * `:model:bulkWrite`, `:cursor:next`), published by mongoose >= 9.7.0.\n *\n * On older mongoose versions the channels are never published to, so the\n * subscribers are inert — there is no double-instrumentation against the\n * IITM-based vendored patcher, which is gated to `< 9.7.0`.\n *\n * Idempotent: subsequent calls are a no-op.\n */\nexport function subscribeMongooseDiagnosticChannels(tracingChannel: MongooseTracingChannelFactory): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n try {\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_QUERY);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_AGGREGATE);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_SAVE);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE);\n setupChannel(tracingChannel, MONGOOSE_DC_CHANNEL_CURSOR_NEXT);\n } catch {\n // The factory relies on `node:diagnostics_channel`, which isn't always\n // available. Fail closed; the SDK simply won't emit mongoose spans here.\n DEBUG_BUILD && debug.log('Mongoose node:diagnostics_channel subscription failed.');\n }\n}\n\nfunction setupChannel(tracingChannel: MongooseTracingChannelFactory, channelName: string): void {\n bindTracingChannelToSpan(tracingChannel<MongooseTracingData>(channelName), data => {\n const collection = data.collection;\n const queryText = redactMongoQuery(data.args?.pipeline ?? data.args?.filter);\n const batchSize = getBatchSize(data);\n\n return startInactiveSpan({\n name: collection ? `mongoose.${collection}.${data.operation}` : `mongoose.${data.operation}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db',\n [DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_MONGODB,\n [DB_OPERATION_NAME]: data.operation,\n [DB_COLLECTION_NAME]: collection ?? undefined,\n [DB_NAMESPACE]: data.database ?? undefined,\n [DB_QUERY_TEXT]: queryText ?? undefined,\n [DB_OPERATION_BATCH_SIZE]: batchSize ?? undefined,\n [SERVER_ADDRESS]: data.serverAddress ?? undefined,\n [SERVER_PORT]: data.serverPort ?? undefined,\n },\n });\n });\n}\n\n/**\n * `db.operation.batch.size` is only meaningful for genuine batch operations.\n * Mongoose's cursor `batchSize` is a fetch-tuning option, not a batch operation\n * size, so it is intentionally excluded here.\n */\nfunction getBatchSize(data: MongooseTracingData): number | undefined {\n const args = data.args;\n const batch = data.operation === 'insertMany' ? args?.docs : data.operation === 'bulkWrite' ? args?.ops : undefined;\n\n return Array.isArray(batch) && batch.length > 1 ? batch.length : undefined;\n}\n\n/**\n * Serialize a mongoose filter/pipeline into `db.query.text` while stripping every\n * value: keys and Mongo operators (`$gt`, `$in`, …) are preserved, leaf values\n * become `'?'`. Mongoose does not sanitize its channel payload, so this prevents\n * raw user data (potential PII) from leaving the process. Returns `undefined`\n * (rather than throwing) on anything it cannot serialize.\n */\nfunction redactMongoQuery(value: unknown): string | undefined {\n if (value == null) {\n return undefined;\n }\n\n try {\n const redacted = redactValue(value, 0);\n const text = JSON.stringify(redacted);\n\n // Skip empty/uninformative shapes (e.g. a `findOne()` with no filter).\n return text == null || text === '{}' || text === '[]' ? undefined : text;\n } catch {\n return undefined;\n }\n}\n\nfunction redactValue(value: unknown, depth: number): unknown {\n if (depth > MAX_REDACTION_DEPTH) {\n return '?';\n }\n\n if (Array.isArray(value)) {\n return value.map(item => redactValue(item, depth + 1));\n }\n\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n out[key] = redactValue((value as Record<string, unknown>)[key], depth + 1);\n }\n\n return out;\n }\n\n return '?';\n}\n"],"names":[],"mappings":"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"}
const anthropicAiConfig = [
// One entry each for CJS/ESM
...["resources/messages/messages.js", "resources/messages/messages.mjs"].flatMap(
(filePath) => ["create", "countTokens"].map((methodName) => ({
channelName: "chat",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Messages", methodName, kind: "Auto" }
}))
),
...["resources/completions.js", "resources/completions.mjs"].map((filePath) => ({
channelName: "chat",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Completions", methodName: "create", kind: "Auto" }
})),
...["resources/beta/messages/messages.js", "resources/beta/messages/messages.mjs"].map((filePath) => ({
channelName: "chat",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Messages", methodName: "create", kind: "Auto" }
})),
...["resources/models.js", "resources/models.mjs"].map((filePath) => ({
channelName: "models",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Models", methodName: "retrieve", kind: "Auto" }
})),
// `messages.stream()` returns a synchronous emitter, not a promise, so `kind: 'Sync'` is required:
// `Auto`'s promise wrapper never publishes `end` for a non-thenable return, so the span would never end.
...["resources/messages/messages.js", "resources/messages/messages.mjs"].map((filePath) => ({
channelName: "messages-stream",
module: { name: "@anthropic-ai/sdk", versionRange: ">=0.19.2 <1", filePath },
functionQuery: { className: "Messages", methodName: "stream", kind: "Sync" }
}))
];
const anthropicAiChannels = {
ANTHROPIC_CHAT: "orchestrion:@anthropic-ai/sdk:chat",
ANTHROPIC_MODELS: "orchestrion:@anthropic-ai/sdk:models",
ANTHROPIC_MESSAGES_STREAM: "orchestrion:@anthropic-ai/sdk:messages-stream"
};
export { anthropicAiChannels, anthropicAiConfig };
//# sourceMappingURL=anthropic-ai.js.map
{"version":3,"file":"anthropic-ai.js","sources":["../../../../src/orchestrion/config/anthropic-ai.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const anthropicAiConfig = [\n // One entry each for CJS/ESM\n ...['resources/messages/messages.js', 'resources/messages/messages.mjs'].flatMap(filePath =>\n (['create', 'countTokens'] as const).map(methodName => ({\n channelName: 'chat',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Messages', methodName, kind: 'Auto' as const },\n })),\n ),\n ...['resources/completions.js', 'resources/completions.mjs'].map(filePath => ({\n channelName: 'chat',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Completions', methodName: 'create', kind: 'Auto' as const },\n })),\n ...['resources/beta/messages/messages.js', 'resources/beta/messages/messages.mjs'].map(filePath => ({\n channelName: 'chat',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Messages', methodName: 'create', kind: 'Auto' as const },\n })),\n ...['resources/models.js', 'resources/models.mjs'].map(filePath => ({\n channelName: 'models',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Models', methodName: 'retrieve', kind: 'Auto' as const },\n })),\n // `messages.stream()` returns a synchronous emitter, not a promise, so `kind: 'Sync'` is required:\n // `Auto`'s promise wrapper never publishes `end` for a non-thenable return, so the span would never end.\n ...['resources/messages/messages.js', 'resources/messages/messages.mjs'].map(filePath => ({\n channelName: 'messages-stream',\n module: { name: '@anthropic-ai/sdk', versionRange: '>=0.19.2 <1', filePath },\n functionQuery: { className: 'Messages', methodName: 'stream', kind: 'Sync' as const },\n })),\n] satisfies InstrumentationConfig[];\n\nexport const anthropicAiChannels = {\n ANTHROPIC_CHAT: 'orchestrion:@anthropic-ai/sdk:chat',\n ANTHROPIC_MODELS: 'orchestrion:@anthropic-ai/sdk:models',\n ANTHROPIC_MESSAGES_STREAM: 'orchestrion:@anthropic-ai/sdk:messages-stream',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,iBAAA,GAAoB;AAAA;AAAA,EAE/B,GAAG,CAAC,gCAAA,EAAkC,iCAAiC,CAAA,CAAE,OAAA;AAAA,IAAQ,cAC9E,CAAC,QAAA,EAAU,aAAa,CAAA,CAAY,IAAI,CAAA,UAAA,MAAe;AAAA,MACtD,WAAA,EAAa,MAAA;AAAA,MACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,MAC3E,eAAe,EAAE,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,MAAM,MAAA;AAAgB,KAC5E,CAAE;AAAA,GACJ;AAAA,EACA,GAAG,CAAC,0BAAA,EAA4B,2BAA2B,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC5E,WAAA,EAAa,MAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,eAAe,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACzF,CAAE,CAAA;AAAA,EACF,GAAG,CAAC,qCAAA,EAAuC,sCAAsC,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAClG,WAAA,EAAa,MAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,YAAY,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACtF,CAAE,CAAA;AAAA,EACF,GAAG,CAAC,qBAAA,EAAuB,sBAAsB,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAClE,WAAA,EAAa,QAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,UAAU,UAAA,EAAY,UAAA,EAAY,MAAM,MAAA;AAAgB,GACtF,CAAE,CAAA;AAAA;AAAA;AAAA,EAGF,GAAG,CAAC,gCAAA,EAAkC,iCAAiC,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IACxF,WAAA,EAAa,iBAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,mBAAA,EAAqB,YAAA,EAAc,eAAe,QAAA,EAAS;AAAA,IAC3E,eAAe,EAAE,SAAA,EAAW,YAAY,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACtF,CAAE;AACJ;AAEO,MAAM,mBAAA,GAAsB;AAAA,EACjC,cAAA,EAAgB,oCAAA;AAAA,EAChB,gBAAA,EAAkB,sCAAA;AAAA,EAClB,yBAAA,EAA2B;AAC7B;;;;"}
const hapiConfig = [
// hapi's `route`/`ext` live on an anonymous class (`internals.Server = class {}`),
// so `{className}` can't match — `{methodName}` targets them in lib/server.js. Both
// are synchronous void methods, so `Sync` suffices: we only use `start` to swap
// handlers in `ctx.arguments`. Shape verified across the whole range.
{
channelName: "route",
module: { name: "@hapi/hapi", versionRange: ">=17.0.0 <22.0.0", filePath: "lib/server.js" },
functionQuery: { methodName: "route", kind: "Sync" }
},
{
channelName: "ext",
module: { name: "@hapi/hapi", versionRange: ">=17.0.0 <22.0.0", filePath: "lib/server.js" },
functionQuery: { methodName: "ext", kind: "Sync" }
}
];
const hapiChannels = {
HAPI_ROUTE: "orchestrion:@hapi/hapi:route",
HAPI_EXT: "orchestrion:@hapi/hapi:ext"
};
export { hapiChannels, hapiConfig };
//# sourceMappingURL=hapi.js.map
{"version":3,"file":"hapi.js","sources":["../../../../src/orchestrion/config/hapi.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const hapiConfig = [\n // hapi's `route`/`ext` live on an anonymous class (`internals.Server = class {}`),\n // so `{className}` can't match — `{methodName}` targets them in lib/server.js. Both\n // are synchronous void methods, so `Sync` suffices: we only use `start` to swap\n // handlers in `ctx.arguments`. Shape verified across the whole range.\n {\n channelName: 'route',\n module: { name: '@hapi/hapi', versionRange: '>=17.0.0 <22.0.0', filePath: 'lib/server.js' },\n functionQuery: { methodName: 'route', kind: 'Sync' },\n },\n {\n channelName: 'ext',\n module: { name: '@hapi/hapi', versionRange: '>=17.0.0 <22.0.0', filePath: 'lib/server.js' },\n functionQuery: { methodName: 'ext', kind: 'Sync' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const hapiChannels = {\n HAPI_ROUTE: 'orchestrion:@hapi/hapi:route',\n HAPI_EXT: 'orchestrion:@hapi/hapi:ext',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,cAAc,YAAA,EAAc,kBAAA,EAAoB,UAAU,eAAA,EAAgB;AAAA,IAC1F,aAAA,EAAe,EAAE,UAAA,EAAY,OAAA,EAAS,MAAM,MAAA;AAAO,GACrD;AAAA,EACA;AAAA,IACE,WAAA,EAAa,KAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,cAAc,YAAA,EAAc,kBAAA,EAAoB,UAAU,eAAA,EAAgB;AAAA,IAC1F,aAAA,EAAe,EAAE,UAAA,EAAY,KAAA,EAAO,MAAM,MAAA;AAAO;AAErD;AAEO,MAAM,YAAA,GAAe;AAAA,EAC1B,UAAA,EAAY,8BAAA;AAAA,EACZ,QAAA,EAAU;AACZ;;;;"}
import { mysqlConfig } from './mysql.js';
import { lruMemoizerConfig } from './lru-memoizer.js';
import { ioredisConfig } from './ioredis.js';
import { openaiConfig } from './openai.js';
import { pgConfig } from './pg.js';
import { anthropicAiConfig } from './anthropic-ai.js';
import { vercelAiConfig } from './vercel-ai.js';
import { hapiConfig } from './hapi.js';
const SENTRY_INSTRUMENTATIONS = [
...mysqlConfig,
...lruMemoizerConfig,
...ioredisConfig,
...openaiConfig,
...pgConfig,
...anthropicAiConfig,
...vercelAiConfig,
...hapiConfig
];
const INSTRUMENTED_MODULE_NAMES = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map((i) => i.module.name)));
function withoutInstrumentedExternals(external) {
if (!external) {
return void 0;
}
return external.filter(
(entry) => !INSTRUMENTED_MODULE_NAMES.some((name) => entry === name || entry.startsWith(`${name}/`))
);
}
export { INSTRUMENTED_MODULE_NAMES, SENTRY_INSTRUMENTATIONS, withoutInstrumentedExternals };
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../../../src/orchestrion/config/index.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\nimport { mysqlConfig } from './mysql';\nimport { lruMemoizerConfig } from './lru-memoizer';\nimport { ioredisConfig } from './ioredis';\nimport { openaiConfig } from './openai';\nimport { pgConfig } from './pg';\nimport { anthropicAiConfig } from './anthropic-ai';\nimport { vercelAiConfig } from './vercel-ai';\nimport { hapiConfig } from './hapi';\n\nexport const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[] = [\n ...mysqlConfig,\n ...lruMemoizerConfig,\n ...ioredisConfig,\n ...openaiConfig,\n ...pgConfig,\n ...anthropicAiConfig,\n ...vercelAiConfig,\n ...hapiConfig,\n];\n\n/**\n * The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`\n * (e.g. `['mysql']`).\n *\n * Bundler plugins MUST ensure these are actually bundled rather than\n * externalized: an externalized dependency is resolved from `node_modules` at\n * runtime and never passes through the code transform's `onLoad`, so its\n * diagnostics_channel calls are silently never injected.\n */\nexport const INSTRUMENTED_MODULE_NAMES: string[] = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map(i => i.module.name)));\n\n/**\n * Returns `external` with any instrumented packages removed, so a bundler that\n * uses an \"external\" denylist (esbuild, Bun, Rollup) still bundles — and thus\n * transforms — them. Matches an exact package name (`'mysql'`) or a subpath\n * (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`\n * is returned unchanged.\n *\n * (Vite uses an `ssr.noExternal` allowlist instead, so it consumes\n * `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)\n */\nexport function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined {\n if (!external) {\n return undefined;\n }\n return external.filter(\n entry => !INSTRUMENTED_MODULE_NAMES.some(name => entry === name || entry.startsWith(`${name}/`)),\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAUO,MAAM,uBAAA,GAAmD;AAAA,EAC9D,GAAG,WAAA;AAAA,EACH,GAAG,iBAAA;AAAA,EACH,GAAG,aAAA;AAAA,EACH,GAAG,YAAA;AAAA,EACH,GAAG,QAAA;AAAA,EACH,GAAG,iBAAA;AAAA,EACH,GAAG,cAAA;AAAA,EACH,GAAG;AACL;AAWO,MAAM,yBAAA,GAAsC,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,uBAAA,CAAwB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,IAAI,CAAC,CAAC;AAY/G,SAAS,6BAA6B,QAAA,EAA+D;AAC1G,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,CAAS,MAAA;AAAA,IACd,CAAA,KAAA,KAAS,CAAC,yBAAA,CAA0B,IAAA,CAAK,CAAA,IAAA,KAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,CAAM,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAC;AAAA,GACjG;AACF;;;;"}
const ioredisConfig = [
// ioredis `<5.11.0` (>=5.11.0 publishes its own `ioredis:*` diagnostics_channel)
...["lib/redis.js", "built/redis.js", "built/redis/index.js"].flatMap((filePath) => [
{
channelName: "command",
module: { name: "ioredis", versionRange: ">=2.0.0 <5.0.0", filePath },
functionQuery: { expressionName: "sendCommand", kind: "Async" }
},
{
channelName: "connect",
module: { name: "ioredis", versionRange: ">=2.0.0 <5.0.0", filePath },
functionQuery: { expressionName: "connect", kind: "Async" }
}
]),
{
channelName: "command",
module: { name: "ioredis", versionRange: ">=5.0.0 <5.11.0", filePath: "built/Redis.js" },
functionQuery: { className: "Redis", methodName: "sendCommand", kind: "Async" }
},
{
channelName: "connect",
module: { name: "ioredis", versionRange: ">=5.0.0 <5.11.0", filePath: "built/Redis.js" },
functionQuery: { className: "Redis", methodName: "connect", kind: "Async" }
}
];
const ioredisChannels = {
IOREDIS_COMMAND: "orchestrion:ioredis:command",
IOREDIS_CONNECT: "orchestrion:ioredis:connect"
};
export { ioredisChannels, ioredisConfig };
//# sourceMappingURL=ioredis.js.map
{"version":3,"file":"ioredis.js","sources":["../../../../src/orchestrion/config/ioredis.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const ioredisConfig = [\n // ioredis `<5.11.0` (>=5.11.0 publishes its own `ioredis:*` diagnostics_channel)\n ...['lib/redis.js', 'built/redis.js', 'built/redis/index.js'].flatMap((filePath): InstrumentationConfig[] => [\n {\n channelName: 'command',\n module: { name: 'ioredis', versionRange: '>=2.0.0 <5.0.0', filePath },\n functionQuery: { expressionName: 'sendCommand', kind: 'Async' },\n },\n {\n channelName: 'connect',\n module: { name: 'ioredis', versionRange: '>=2.0.0 <5.0.0', filePath },\n functionQuery: { expressionName: 'connect', kind: 'Async' },\n },\n ]),\n {\n channelName: 'command',\n module: { name: 'ioredis', versionRange: '>=5.0.0 <5.11.0', filePath: 'built/Redis.js' },\n functionQuery: { className: 'Redis', methodName: 'sendCommand', kind: 'Async' },\n },\n {\n channelName: 'connect',\n module: { name: 'ioredis', versionRange: '>=5.0.0 <5.11.0', filePath: 'built/Redis.js' },\n functionQuery: { className: 'Redis', methodName: 'connect', kind: 'Async' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const ioredisChannels = {\n IOREDIS_COMMAND: 'orchestrion:ioredis:command',\n IOREDIS_CONNECT: 'orchestrion:ioredis:connect',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,GAAG,CAAC,cAAA,EAAgB,gBAAA,EAAkB,sBAAsB,CAAA,CAAE,OAAA,CAAQ,CAAC,QAAA,KAAsC;AAAA,IAC3G;AAAA,MACE,WAAA,EAAa,SAAA;AAAA,MACb,QAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,YAAA,EAAc,kBAAkB,QAAA,EAAS;AAAA,MACpE,aAAA,EAAe,EAAE,cAAA,EAAgB,aAAA,EAAe,MAAM,OAAA;AAAQ,KAChE;AAAA,IACA;AAAA,MACE,WAAA,EAAa,SAAA;AAAA,MACb,QAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,YAAA,EAAc,kBAAkB,QAAA,EAAS;AAAA,MACpE,aAAA,EAAe,EAAE,cAAA,EAAgB,SAAA,EAAW,MAAM,OAAA;AAAQ;AAC5D,GACD,CAAA;AAAA,EACD;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,WAAW,YAAA,EAAc,iBAAA,EAAmB,UAAU,gBAAA,EAAiB;AAAA,IACvF,eAAe,EAAE,SAAA,EAAW,SAAS,UAAA,EAAY,aAAA,EAAe,MAAM,OAAA;AAAQ,GAChF;AAAA,EACA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,WAAW,YAAA,EAAc,iBAAA,EAAmB,UAAU,gBAAA,EAAiB;AAAA,IACvF,eAAe,EAAE,SAAA,EAAW,SAAS,UAAA,EAAY,SAAA,EAAW,MAAM,OAAA;AAAQ;AAE9E;AAEO,MAAM,eAAA,GAAkB;AAAA,EAC7B,eAAA,EAAiB,6BAAA;AAAA,EACjB,eAAA,EAAiB;AACnB;;;;"}
const lruMemoizerConfig = [
{
channelName: "load",
// `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0
module: { name: "lru-memoizer", versionRange: ">=2.1.0 <4", filePath: "lib/async.js" },
functionQuery: { functionName: "memoizedFunction", kind: "Callback" }
}
];
const lruMemoizerChannels = {
LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load"
};
export { lruMemoizerChannels, lruMemoizerConfig };
//# sourceMappingURL=lru-memoizer.js.map
{"version":3,"file":"lru-memoizer.js","sources":["../../../../src/orchestrion/config/lru-memoizer.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const lruMemoizerConfig = [\n {\n channelName: 'load',\n // `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0\n module: { name: 'lru-memoizer', versionRange: '>=2.1.0 <4', filePath: 'lib/async.js' },\n functionQuery: { functionName: 'memoizedFunction', kind: 'Callback' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const lruMemoizerChannels = {\n LRU_MEMOIZER_LOAD: 'orchestrion:lru-memoizer:load',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,iBAAA,GAAoB;AAAA,EAC/B;AAAA,IACE,WAAA,EAAa,MAAA;AAAA;AAAA,IAEb,QAAQ,EAAE,IAAA,EAAM,gBAAgB,YAAA,EAAc,YAAA,EAAc,UAAU,cAAA,EAAe;AAAA,IACrF,aAAA,EAAe,EAAE,YAAA,EAAc,kBAAA,EAAoB,MAAM,UAAA;AAAW;AAExE;AAEO,MAAM,mBAAA,GAAsB;AAAA,EACjC,iBAAA,EAAmB;AACrB;;;;"}
const mysqlConfig = [
{
channelName: "query",
module: { name: "mysql", versionRange: ">=2.0.0 <3", filePath: "lib/Connection.js" },
functionQuery: { expressionName: "query", kind: "Auto" }
}
];
const mysqlChannels = {
MYSQL_QUERY: "orchestrion:mysql:query"
};
export { mysqlChannels, mysqlConfig };
//# sourceMappingURL=mysql.js.map
{"version":3,"file":"mysql.js","sources":["../../../../src/orchestrion/config/mysql.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const mysqlConfig = [\n {\n channelName: 'query',\n module: { name: 'mysql', versionRange: '>=2.0.0 <3', filePath: 'lib/Connection.js' },\n functionQuery: { expressionName: 'query', kind: 'Auto' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const mysqlChannels = {\n MYSQL_QUERY: 'orchestrion:mysql:query',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,WAAA,GAAc;AAAA,EACzB;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,SAAS,YAAA,EAAc,YAAA,EAAc,UAAU,mBAAA,EAAoB;AAAA,IACnF,aAAA,EAAe,EAAE,cAAA,EAAgB,OAAA,EAAS,MAAM,MAAA;AAAO;AAE3D;AAEO,MAAM,aAAA,GAAgB;AAAA,EAC3B,WAAA,EAAa;AACf;;;;"}
const openaiConfig = [
// OpenAI chat completions. `Completions.create` returns a thenable `APIPromise` with no callback arg,
// so `kind: 'Auto'` resolves to `wrapPromise`. openai ships dual CJS/ESM and the matcher compares
// `filePath` exactly, hence one entry per built file (`.js` for `require`, `.mjs` for `import`).
...["resources/chat/completions/completions.js", "resources/chat/completions/completions.mjs"].map((filePath) => ({
channelName: "chat",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Completions", methodName: "create", kind: "Auto" }
})),
// OpenAI responses API — same `create(body, options)` shape as chat completions.
...["resources/responses/responses.js", "resources/responses/responses.mjs"].map((filePath) => ({
channelName: "responses",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Responses", methodName: "create", kind: "Auto" }
})),
// OpenAI embeddings API — same `create(body, options)` shape as chat completions.
...["resources/embeddings.js", "resources/embeddings.mjs"].map((filePath) => ({
channelName: "embeddings",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Embeddings", methodName: "create", kind: "Auto" }
})),
// OpenAI conversations API — same `create(body, options)` shape as chat completions.
...["resources/conversations/conversations.js", "resources/conversations/conversations.mjs"].map((filePath) => ({
channelName: "conversations",
module: { name: "openai", versionRange: ">=4.0.0 <7", filePath },
functionQuery: { className: "Conversations", methodName: "create", kind: "Auto" }
}))
];
const openaiChannels = {
OPENAI_CHAT: "orchestrion:openai:chat",
OPENAI_RESPONSES: "orchestrion:openai:responses",
OPENAI_EMBEDDINGS: "orchestrion:openai:embeddings",
OPENAI_CONVERSATIONS: "orchestrion:openai:conversations"
};
export { openaiChannels, openaiConfig };
//# sourceMappingURL=openai.js.map
{"version":3,"file":"openai.js","sources":["../../../../src/orchestrion/config/openai.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const openaiConfig = [\n // OpenAI chat completions. `Completions.create` returns a thenable `APIPromise` with no callback arg,\n // so `kind: 'Auto'` resolves to `wrapPromise`. openai ships dual CJS/ESM and the matcher compares\n // `filePath` exactly, hence one entry per built file (`.js` for `require`, `.mjs` for `import`).\n ...['resources/chat/completions/completions.js', 'resources/chat/completions/completions.mjs'].map(filePath => ({\n channelName: 'chat',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Completions', methodName: 'create', kind: 'Auto' as const },\n })),\n // OpenAI responses API — same `create(body, options)` shape as chat completions.\n ...['resources/responses/responses.js', 'resources/responses/responses.mjs'].map(filePath => ({\n channelName: 'responses',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Responses', methodName: 'create', kind: 'Auto' as const },\n })),\n // OpenAI embeddings API — same `create(body, options)` shape as chat completions.\n ...['resources/embeddings.js', 'resources/embeddings.mjs'].map(filePath => ({\n channelName: 'embeddings',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Embeddings', methodName: 'create', kind: 'Auto' as const },\n })),\n // OpenAI conversations API — same `create(body, options)` shape as chat completions.\n ...['resources/conversations/conversations.js', 'resources/conversations/conversations.mjs'].map(filePath => ({\n channelName: 'conversations',\n module: { name: 'openai', versionRange: '>=4.0.0 <7', filePath },\n functionQuery: { className: 'Conversations', methodName: 'create', kind: 'Auto' as const },\n })),\n] satisfies InstrumentationConfig[];\n\nexport const openaiChannels = {\n OPENAI_CHAT: 'orchestrion:openai:chat',\n OPENAI_RESPONSES: 'orchestrion:openai:responses',\n OPENAI_EMBEDDINGS: 'orchestrion:openai:embeddings',\n OPENAI_CONVERSATIONS: 'orchestrion:openai:conversations',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,YAAA,GAAe;AAAA;AAAA;AAAA;AAAA,EAI1B,GAAG,CAAC,2CAAA,EAA6C,4CAA4C,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC9G,WAAA,EAAa,MAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,eAAe,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACzF,CAAE,CAAA;AAAA;AAAA,EAEF,GAAG,CAAC,kCAAA,EAAoC,mCAAmC,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC5F,WAAA,EAAa,WAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,aAAa,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACvF,CAAE,CAAA;AAAA;AAAA,EAEF,GAAG,CAAC,yBAAA,EAA2B,0BAA0B,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC1E,WAAA,EAAa,YAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,cAAc,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GACxF,CAAE,CAAA;AAAA;AAAA,EAEF,GAAG,CAAC,0CAAA,EAA4C,2CAA2C,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC5G,WAAA,EAAa,eAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,cAAc,QAAA,EAAS;AAAA,IAC/D,eAAe,EAAE,SAAA,EAAW,iBAAiB,UAAA,EAAY,QAAA,EAAU,MAAM,MAAA;AAAgB,GAC3F,CAAE;AACJ;AAEO,MAAM,cAAA,GAAiB;AAAA,EAC5B,WAAA,EAAa,yBAAA;AAAA,EACb,gBAAA,EAAkB,8BAAA;AAAA,EAClB,iBAAA,EAAmB,+BAAA;AAAA,EACnB,oBAAA,EAAsB;AACxB;;;;"}
const pgConfig = [
// `pg` (node-postgres).
// instruments `Client.prototype.query`/`connect` (both the JS and native
// clients) plus `pg-pool`'s `Pool.prototype.connect`.
// `Auto` covers the callback, promise, and streamable-`Submittable`
// call shapes (like mysql).
// `pg/lib/client.js` is `class Client { query() {...} connect() {...} }`,
// so `className`+`methodName` matches directly.
{
channelName: "query",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/client.js" },
functionQuery: { className: "Client", methodName: "query", kind: "Auto" }
},
{
channelName: "connect",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/client.js" },
functionQuery: { className: "Client", methodName: "connect", kind: "Auto" }
},
// The native client (`pg/lib/native/client.js`) is a constructor function,
// not a class.
// `Client.prototype.query = function (config, values, callback) {...}`
// so it needs `expressionName` (the mysql shape), publishing to the SAME
// `orchestrion:pg:query`/`:connect` channels as the JS client.
{
channelName: "query",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/native/client.js" },
functionQuery: { expressionName: "query", kind: "Auto" }
},
{
channelName: "connect",
module: { name: "pg", versionRange: ">=8.0.3 <9", filePath: "lib/native/client.js" },
functionQuery: { expressionName: "connect", kind: "Auto" }
},
// `pg-pool` is `class Pool extends EventEmitter { connect(cb) {...} }`.
{
channelName: "connect",
module: { name: "pg-pool", versionRange: ">=2.0.0 <4", filePath: "index.js" },
functionQuery: { className: "Pool", methodName: "connect", kind: "Auto" }
}
];
const pgChannels = {
PG_QUERY: "orchestrion:pg:query",
PG_CONNECT: "orchestrion:pg:connect",
PGPOOL_CONNECT: "orchestrion:pg-pool:connect"
};
export { pgChannels, pgConfig };
//# sourceMappingURL=pg.js.map
{"version":3,"file":"pg.js","sources":["../../../../src/orchestrion/config/pg.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const pgConfig = [\n // `pg` (node-postgres).\n // instruments `Client.prototype.query`/`connect` (both the JS and native\n // clients) plus `pg-pool`'s `Pool.prototype.connect`.\n // `Auto` covers the callback, promise, and streamable-`Submittable`\n // call shapes (like mysql).\n // `pg/lib/client.js` is `class Client { query() {...} connect() {...} }`,\n // so `className`+`methodName` matches directly.\n {\n channelName: 'query',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/client.js' },\n functionQuery: { className: 'Client', methodName: 'query', kind: 'Auto' },\n },\n {\n channelName: 'connect',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/client.js' },\n functionQuery: { className: 'Client', methodName: 'connect', kind: 'Auto' },\n },\n // The native client (`pg/lib/native/client.js`) is a constructor function,\n // not a class.\n // `Client.prototype.query = function (config, values, callback) {...}`\n // so it needs `expressionName` (the mysql shape), publishing to the SAME\n // `orchestrion:pg:query`/`:connect` channels as the JS client.\n {\n channelName: 'query',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/native/client.js' },\n functionQuery: { expressionName: 'query', kind: 'Auto' },\n },\n {\n channelName: 'connect',\n module: { name: 'pg', versionRange: '>=8.0.3 <9', filePath: 'lib/native/client.js' },\n functionQuery: { expressionName: 'connect', kind: 'Auto' },\n },\n // `pg-pool` is `class Pool extends EventEmitter { connect(cb) {...} }`.\n {\n channelName: 'connect',\n module: { name: 'pg-pool', versionRange: '>=2.0.0 <4', filePath: 'index.js' },\n functionQuery: { className: 'Pool', methodName: 'connect', kind: 'Auto' },\n },\n] satisfies InstrumentationConfig[];\n\nexport const pgChannels = {\n PG_QUERY: 'orchestrion:pg:query',\n PG_CONNECT: 'orchestrion:pg:connect',\n PGPOOL_CONNECT: 'orchestrion:pg-pool:connect',\n} as const;\n"],"names":[],"mappings":"AAEO,MAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,eAAA,EAAgB;AAAA,IAC5E,eAAe,EAAE,SAAA,EAAW,UAAU,UAAA,EAAY,OAAA,EAAS,MAAM,MAAA;AAAO,GAC1E;AAAA,EACA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,eAAA,EAAgB;AAAA,IAC5E,eAAe,EAAE,SAAA,EAAW,UAAU,UAAA,EAAY,SAAA,EAAW,MAAM,MAAA;AAAO,GAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,sBAAA,EAAuB;AAAA,IACnF,aAAA,EAAe,EAAE,cAAA,EAAgB,OAAA,EAAS,MAAM,MAAA;AAAO,GACzD;AAAA,EACA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,MAAM,YAAA,EAAc,YAAA,EAAc,UAAU,sBAAA,EAAuB;AAAA,IACnF,aAAA,EAAe,EAAE,cAAA,EAAgB,SAAA,EAAW,MAAM,MAAA;AAAO,GAC3D;AAAA;AAAA,EAEA;AAAA,IACE,WAAA,EAAa,SAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,WAAW,YAAA,EAAc,YAAA,EAAc,UAAU,UAAA,EAAW;AAAA,IAC5E,eAAe,EAAE,SAAA,EAAW,QAAQ,UAAA,EAAY,SAAA,EAAW,MAAM,MAAA;AAAO;AAE5E;AAEO,MAAM,UAAA,GAAa;AAAA,EACxB,QAAA,EAAU,sBAAA;AAAA,EACV,UAAA,EAAY,wBAAA;AAAA,EACZ,cAAA,EAAgB;AAClB;;;;"}
const vercelAiConfig = [
// Vercel AI v6: mirror the v7 native `ai:telemetry` channel by injecting
// channels into the top-level entry points. `resolveLanguageModel` is wrapped
// not to span it, but so the subscriber can monkey-patch `doGenerate`/
// `doStream` on the returned model (the only way to span the model call,
// which is an inline call with no injectable definition in `ai`).
// `streamText` returns its result synchronously (streaming is lazy), so it's
// `Sync`; the subscriber binds the span via `bindTracingChannelToSpan`, which
// ends it when the (synchronous) call returns.
...vercelAiV6Entries("generateText", "generateText", "Async"),
...vercelAiV6Entries("streamText", "streamText", "Sync"),
...vercelAiV6Entries("embed", "embed", "Async"),
...vercelAiV6Entries("embedMany", "embedMany", "Async"),
...vercelAiV6Entries("executeToolCall", "executeToolCall", "Async"),
...vercelAiV6Entries("resolveLanguageModel", "resolveLanguageModel", "Sync")
];
const vercelAiChannels = {
// Vercel AI (`ai`) v6: orchestrion injects these so the same channel-based
// integration that consumes `ai`'s native `ai:telemetry` channel (v7) can
// also instrument v6. Each maps to a top-level function in `ai`'s bundle.
VERCEL_AI_GENERATE_TEXT: "orchestrion:ai:generateText",
VERCEL_AI_STREAM_TEXT: "orchestrion:ai:streamText",
VERCEL_AI_EMBED: "orchestrion:ai:embed",
VERCEL_AI_EMBED_MANY: "orchestrion:ai:embedMany",
VERCEL_AI_EXECUTE_TOOL_CALL: "orchestrion:ai:executeToolCall",
// `resolveLanguageModel` is the single chokepoint every model call flows
// through; we wrap it to monkey-patch `doGenerate`/`doStream` on the returned
// model (the model-call site itself is an inline call with no injectable
// definition).
VERCEL_AI_RESOLVE_LANGUAGE_MODEL: "orchestrion:ai:resolveLanguageModel"
};
function vercelAiV6Entries(channelName, functionName, kind) {
return ["dist/index.js", "dist/index.mjs"].map((filePath) => ({
channelName,
module: { name: "ai", versionRange: ">=6.0.0 <7.0.0", filePath },
functionQuery: { functionName, kind }
}));
}
export { vercelAiChannels, vercelAiConfig };
//# sourceMappingURL=vercel-ai.js.map
{"version":3,"file":"vercel-ai.js","sources":["../../../../src/orchestrion/config/vercel-ai.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\nexport const vercelAiConfig = [\n // Vercel AI v6: mirror the v7 native `ai:telemetry` channel by injecting\n // channels into the top-level entry points. `resolveLanguageModel` is wrapped\n // not to span it, but so the subscriber can monkey-patch `doGenerate`/\n // `doStream` on the returned model (the only way to span the model call,\n // which is an inline call with no injectable definition in `ai`).\n // `streamText` returns its result synchronously (streaming is lazy), so it's\n // `Sync`; the subscriber binds the span via `bindTracingChannelToSpan`, which\n // ends it when the (synchronous) call returns.\n ...vercelAiV6Entries('generateText', 'generateText', 'Async'),\n ...vercelAiV6Entries('streamText', 'streamText', 'Sync'),\n ...vercelAiV6Entries('embed', 'embed', 'Async'),\n ...vercelAiV6Entries('embedMany', 'embedMany', 'Async'),\n ...vercelAiV6Entries('executeToolCall', 'executeToolCall', 'Async'),\n ...vercelAiV6Entries('resolveLanguageModel', 'resolveLanguageModel', 'Sync'),\n] satisfies InstrumentationConfig[];\n\nexport const vercelAiChannels = {\n // Vercel AI (`ai`) v6: orchestrion injects these so the same channel-based\n // integration that consumes `ai`'s native `ai:telemetry` channel (v7) can\n // also instrument v6. Each maps to a top-level function in `ai`'s bundle.\n VERCEL_AI_GENERATE_TEXT: 'orchestrion:ai:generateText',\n VERCEL_AI_STREAM_TEXT: 'orchestrion:ai:streamText',\n VERCEL_AI_EMBED: 'orchestrion:ai:embed',\n VERCEL_AI_EMBED_MANY: 'orchestrion:ai:embedMany',\n VERCEL_AI_EXECUTE_TOOL_CALL: 'orchestrion:ai:executeToolCall',\n // `resolveLanguageModel` is the single chokepoint every model call flows\n // through; we wrap it to monkey-patch `doGenerate`/`doStream` on the returned\n // model (the model-call site itself is an inline call with no injectable\n // definition).\n VERCEL_AI_RESOLVE_LANGUAGE_MODEL: 'orchestrion:ai:resolveLanguageModel',\n} as const;\n\n/**\n * The central list of channel injections orchestrion should perform.\n *\n * This module has NO side effects — it's the only thing both the runtime hook\n * (`runtime/import-hook.mjs`) and the bundler plugins (`bundler/vite.ts`, …)\n * import from. Adding a new instrumented method is one entry here plus one\n * subscriber in `integrations/<lib>/tracing-channel.ts`.\n *\n * `channelName` here is the unprefixed suffix; the actual diagnostics_channel\n * name is `orchestrion:${module.name}:${channelName}` (see `channels.ts`).\n */\n/**\n * `ai` ships a single bundled entry per module system, so each instrumented\n * function needs one config entry per file (the app loads whichever matches its\n * module system). This expands a single target into both.\n */\nfunction vercelAiV6Entries(channelName: string, functionName: string, kind: 'Async' | 'Sync'): InstrumentationConfig[] {\n return ['dist/index.js', 'dist/index.mjs'].map(filePath => ({\n channelName,\n module: { name: 'ai', versionRange: '>=6.0.0 <7.0.0', filePath },\n functionQuery: { functionName, kind },\n }));\n}\n"],"names":[],"mappings":"AAEO,MAAM,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS5B,GAAG,iBAAA,CAAkB,cAAA,EAAgB,cAAA,EAAgB,OAAO,CAAA;AAAA,EAC5D,GAAG,iBAAA,CAAkB,YAAA,EAAc,YAAA,EAAc,MAAM,CAAA;AAAA,EACvD,GAAG,iBAAA,CAAkB,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA;AAAA,EAC9C,GAAG,iBAAA,CAAkB,WAAA,EAAa,WAAA,EAAa,OAAO,CAAA;AAAA,EACtD,GAAG,iBAAA,CAAkB,iBAAA,EAAmB,iBAAA,EAAmB,OAAO,CAAA;AAAA,EAClE,GAAG,iBAAA,CAAkB,sBAAA,EAAwB,sBAAA,EAAwB,MAAM;AAC7E;AAEO,MAAM,gBAAA,GAAmB;AAAA;AAAA;AAAA;AAAA,EAI9B,uBAAA,EAAyB,6BAAA;AAAA,EACzB,qBAAA,EAAuB,2BAAA;AAAA,EACvB,eAAA,EAAiB,sBAAA;AAAA,EACjB,oBAAA,EAAsB,0BAAA;AAAA,EACtB,2BAAA,EAA6B,gCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,gCAAA,EAAkC;AACpC;AAkBA,SAAS,iBAAA,CAAkB,WAAA,EAAqB,YAAA,EAAsB,IAAA,EAAiD;AACrH,EAAA,OAAO,CAAC,eAAA,EAAiB,gBAAgB,CAAA,CAAE,IAAI,CAAA,QAAA,MAAa;AAAA,IAC1D,WAAA;AAAA,IACA,QAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,YAAA,EAAc,kBAAkB,QAAA,EAAS;AAAA,IAC/D,aAAA,EAAe,EAAE,YAAA,EAAc,IAAA;AAAK,GACtC,CAAE,CAAA;AACJ;;;;"}
const serializationSubsets = [
{
regex: /^ECHO/i,
args: 0
},
{
regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,
args: 1
},
{
regex: /^(HSET|HMSET|LSET|LINSERT)/i,
args: 2
},
{
regex: /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,
args: -1
}
];
const defaultDbStatementSerializer = (cmdName, cmdArgs) => {
if (Array.isArray(cmdArgs) && cmdArgs.length) {
const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;
const argsToSerialize = nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();
if (cmdArgs.length > argsToSerialize.length) {
argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);
}
return `${cmdName} ${argsToSerialize.join(" ")}`;
}
return cmdName;
};
export { defaultDbStatementSerializer };
//# sourceMappingURL=redis-statement-serializer.js.map
{"version":3,"file":"redis-statement-serializer.js","sources":["../../../src/redis/redis-statement-serializer.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/redis-common\n * - Upstream version: @opentelemetry/redis-common@0.38.2\n *\n * Single canonical copy, shared by the orchestrion ioredis subscriber here and\n * the node SDK's vendored redis/ioredis instrumentations (which re-export it via\n * `packages/node/src/integrations/tracing/redis/vendored/redis-common.ts`).\n */\n/* eslint-disable -- vendored @opentelemetry/redis-common */\n\n/**\n * List of regexes and the number of arguments that should be serialized for matching commands.\n * For example, HSET should serialize which key and field it's operating on, but not its value.\n * Setting the subset to -1 will serialize all arguments.\n * Commands without a match will have their first argument serialized.\n *\n * Refer to https://redis.io/commands/ for the full list.\n */\nconst serializationSubsets = [\n {\n regex: /^ECHO/i,\n args: 0,\n },\n {\n regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,\n args: 1,\n },\n {\n regex: /^(HSET|HMSET|LSET|LINSERT)/i,\n args: 2,\n },\n {\n regex:\n /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,\n args: -1,\n },\n];\n\n/**\n * Given the redis command name and arguments, return a combination of the\n * command name + the allowed arguments according to `serializationSubsets`.\n */\nexport const defaultDbStatementSerializer = (\n cmdName: string,\n cmdArgs: Array<string | Buffer | number | unknown[]>,\n): string => {\n if (Array.isArray(cmdArgs) && cmdArgs.length) {\n const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;\n const argsToSerialize: Array<string | Buffer | number | unknown[]> =\n nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();\n if (cmdArgs.length > argsToSerialize.length) {\n argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);\n }\n return `${cmdName} ${argsToSerialize.join(' ')}`;\n }\n return cmdName;\n};\n"],"names":[],"mappings":"AAsBA,MAAM,oBAAA,GAAuB;AAAA,EAC3B;AAAA,IACE,KAAA,EAAO,QAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAA,EAAO,8DAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAA,EAAO,6BAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAA,EACE,kLAAA;AAAA,IACF,IAAA,EAAM;AAAA;AAEV,CAAA;AAMO,MAAM,4BAAA,GAA+B,CAC1C,OAAA,EACA,OAAA,KACW;AACX,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,IAAK,QAAQ,MAAA,EAAQ;AAC5C,IAAA,MAAM,gBAAA,GAAmB,oBAAA,CAAqB,IAAA,CAAK,CAAC,EAAE,KAAA,EAAM,KAAM,KAAA,CAAM,IAAA,CAAK,OAAO,CAAC,CAAA,EAAG,IAAA,IAAQ,CAAA;AAChG,IAAA,MAAM,eAAA,GACJ,oBAAoB,CAAA,GAAI,OAAA,CAAQ,MAAM,CAAA,EAAG,gBAAgB,CAAA,GAAI,OAAA,CAAQ,KAAA,EAAM;AAC7E,IAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,eAAA,CAAgB,MAAA,EAAQ;AAC3C,MAAA,eAAA,CAAgB,IAAA,CAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,MAAA,GAAS,gBAAgB,CAAA,iBAAA,CAAmB,CAAA;AAAA,IAC/E;AACA,IAAA,OAAO,GAAG,OAAO,CAAA,CAAA,EAAI,eAAA,CAAgB,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,OAAA;AACT;;;;"}
import { debug, withActiveSpan, getActiveSpan, SPAN_STATUS_ERROR } from '@sentry/core';
import { DEBUG_BUILD } from '../debug-build.js';
import { CHANNELS } from '../orchestrion/channels.js';
import { bindTracingChannelToSpan } from '../tracing-channel.js';
import { createSpanFromMessage, enrichSpanOnEnd, clearOperationCallId, clearOperationId } from './vercel-ai-dc-subscriber.js';
const PATCHED = /* @__PURE__ */ Symbol("SentryVercelAiModelPatched");
let callIdCounter = 0;
function nextCallId() {
return `v6-${++callIdCounter}`;
}
const messages = /* @__PURE__ */ new WeakMap();
const operationSpans = /* @__PURE__ */ new WeakSet();
const callIdBySpan = /* @__PURE__ */ new WeakMap();
const recordingBySpan = /* @__PURE__ */ new WeakMap();
const suppressedTelemetry = /* @__PURE__ */ new WeakSet();
let subscribed = false;
function subscribeVercelAiOrchestrionChannels(tracingChannel, options = {}) {
if (subscribed) {
return;
}
subscribed = true;
try {
bindOperation(tracingChannel, CHANNELS.VERCEL_AI_GENERATE_TEXT, buildTextMessage("generateText"), options);
bindOperation(tracingChannel, CHANNELS.VERCEL_AI_STREAM_TEXT, buildTextMessage("streamText"), options);
bindOperation(
tracingChannel,
CHANNELS.VERCEL_AI_EMBED,
(callOptions, telemetry) => ({
type: "embed",
event: {
callId: nextCallId(),
...modelFields(callOptions.model),
maxRetries: callOptions.maxRetries,
value: callOptions.value,
...recording(telemetry)
}
}),
options
);
bindOperation(
tracingChannel,
CHANNELS.VERCEL_AI_EMBED_MANY,
// `embedMany` takes a `values` array (vs `embed`'s single `value`); the shared core reads it as the
// embeddings input, matching the OTel path's batch `ai.embedMany` span.
(callOptions, telemetry) => ({
type: "embedMany",
event: {
callId: nextCallId(),
...modelFields(callOptions.model),
maxRetries: callOptions.maxRetries,
values: callOptions.values,
...recording(telemetry)
}
}),
options
);
bindOperation(
tracingChannel,
CHANNELS.VERCEL_AI_EXECUTE_TOOL_CALL,
(callOptions, telemetry) => ({
type: "executeTool",
// v6 carries the tool definitions on the executeToolCall args (a record keyed by name);
// the shared core reads the matching tool's `description` for the span.
event: {
callId: nextCallId(),
toolCall: callOptions.toolCall,
tools: callOptions.tools,
...recording(telemetry)
}
}),
options
);
subscribeResolveLanguageModel(tracingChannel, CHANNELS.VERCEL_AI_RESOLVE_LANGUAGE_MODEL, options);
} catch {
DEBUG_BUILD && debug.log("Vercel AI orchestrion channel subscription failed.");
}
}
function bindOperation(tracingChannel, channelName, build, options) {
const channel = tracingChannel(channelName);
const buildOperationSpan = (data) => {
const callOptions = isRecord(data.arguments[0]) ? data.arguments[0] : {};
const telemetry = isRecord(callOptions.experimental_telemetry) ? callOptions.experimental_telemetry : {};
if (telemetry.isEnabled === false && !suppressedTelemetry.has(telemetry)) {
return void 0;
}
const message = build(callOptions, telemetry);
suppressNativeTelemetry(callOptions, telemetry);
const span = createSpanFromMessage(message, options);
if (span) {
messages.set(data, message);
operationSpans.add(span);
const callId = asString(message.event.callId);
if (callId) {
callIdBySpan.set(span, callId);
}
recordingBySpan.set(span, recording(telemetry));
}
return span;
};
bindTracingChannelToSpan(
channel,
(data) => buildOperationSpan(data),
{
beforeSpanEnd: (span, data) => {
const message = messages.get(data);
if (!message) {
return;
}
if (!("error" in data)) {
message.result = message.type === "executeTool" ? { output: data.result } : data.result;
enrichSpanOnEnd(span, message, options);
}
if (message.type !== "streamText") {
clearOperationId(message);
}
messages.delete(data);
}
}
);
}
function suppressNativeTelemetry(callOptions, telemetry) {
if (telemetry.isEnabled !== true) {
return;
}
const suppressed = { ...telemetry, isEnabled: false };
suppressedTelemetry.add(suppressed);
callOptions.experimental_telemetry = suppressed;
}
function subscribeResolveLanguageModel(tracingChannel, channelName, options) {
tracingChannel(channelName).subscribe({
end(rawCtx) {
const ctx = rawCtx;
if (!isRecord(ctx.result)) {
return;
}
const model = ctx.result;
if (!model[PATCHED]) {
model[PATCHED] = true;
patchModelMethod(model, "doGenerate", options);
patchModelMethod(model, "doStream", options);
}
},
start() {
},
asyncStart() {
},
asyncEnd() {
},
error() {
}
});
}
function resolveModelCallParent() {
const active = getActiveSpan();
return active && operationSpans.has(active) ? active : void 0;
}
function patchModelMethod(model, method, options) {
const original = model[method];
if (typeof original !== "function") {
return;
}
model[method] = function(...args) {
const parent = resolveModelCallParent();
if (!parent) {
return Promise.resolve(original.apply(this, args));
}
const callArgs = isRecord(args[0]) ? args[0] : {};
const callId = callIdBySpan.get(parent);
const message = {
type: "languageModelCall",
event: {
callId,
provider: model.provider,
modelId: model.modelId,
tools: callArgs.tools,
messages: callArgs.prompt,
// Inherit the enclosing operation's per-call recording flags so inputs/tools/outputs are recorded on
// the model-call span whenever they are on the parent `invoke_agent` span.
...recordingBySpan.get(parent)
}
};
const span = withActiveSpan(parent, () => createSpanFromMessage(message, options));
if (!span) {
return Promise.resolve(original.apply(this, args));
}
const clearStreamCallId = () => {
if (method === "doStream" && callId) {
clearOperationCallId(callId);
}
};
const failSpan = (error) => {
span.setStatus({ code: SPAN_STATUS_ERROR, message: error instanceof Error ? error.message : "unknown_error" });
span.end();
clearStreamCallId();
throw error;
};
try {
const result = Promise.resolve(original.apply(this, args));
return result.then((value) => {
message.result = value;
enrichSpanOnEnd(span, message, options);
span.end();
clearStreamCallId();
return value;
}, failSpan);
} catch (error) {
return failSpan(error);
}
};
}
function buildTextMessage(type) {
return (options, telemetry) => ({
type,
event: {
callId: nextCallId(),
operationId: `ai.${type}`,
functionId: asString(telemetry.functionId),
...modelFields(options.model),
maxRetries: options.maxRetries,
// Normalize to the message-array shape the shared core (and v7's channel) expects: a bare string
// `prompt` becomes a single user message, matching the SDK's own normalization.
messages: normalizePromptMessages(options),
...recording(telemetry)
}
});
}
function normalizePromptMessages(options) {
if (Array.isArray(options.messages)) {
return options.messages;
}
if (typeof options.prompt === "string") {
return [{ role: "user", content: options.prompt }];
}
return options.messages ?? options.prompt;
}
function recording(telemetry) {
return { recordInputs: telemetry.recordInputs, recordOutputs: telemetry.recordOutputs };
}
function modelFields(model) {
return { provider: modelField(model, "provider"), modelId: modelField(model, "modelId") };
}
function modelField(model, field) {
return isRecord(model) ? asString(model[field]) : void 0;
}
function asString(value) {
return typeof value === "string" ? value : void 0;
}
function isRecord(value) {
return typeof value === "object" && value !== null;
}
export { subscribeVercelAiOrchestrionChannels };
//# sourceMappingURL=vercel-ai-orchestrion-v6-subscriber.js.map
{"version":3,"file":"vercel-ai-orchestrion-v6-subscriber.js","sources":["../../../src/vercel-ai/vercel-ai-orchestrion-v6-subscriber.ts"],"sourcesContent":["import type { Span } from '@sentry/core';\nimport { debug, getActiveSpan, SPAN_STATUS_ERROR, withActiveSpan } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { CHANNELS } from '../orchestrion/channels';\nimport { bindTracingChannelToSpan, type TracingChannelPayloadWithSpan } from '../tracing-channel';\nimport {\n clearOperationCallId,\n clearOperationId,\n createSpanFromMessage,\n enrichSpanOnEnd,\n type VercelAiChannelMessage,\n type VercelAiChannelOptions,\n type VercelAiTracingChannelFactory,\n} from './vercel-ai-dc-subscriber';\n\n/**\n * v6 channel adapter for the Vercel AI (`ai`) SDK.\n *\n * `ai` >= 7 publishes a normalized `ai:telemetry` tracing channel natively\n * (consumed by `subscribeVercelAiTracingChannel`). v6 has no such channel, so\n * orchestrion injects `orchestrion:ai:*` channels around the top-level\n * functions (see `orchestrion/config/index.ts`). The injected channels carry only the\n * wrapped call's `{ arguments, result, error }` — NOT v7's normalized `event`\n * object — so this adapter reconstructs an equivalent {@link VercelAiChannelMessage}\n * from v6's argument/result shapes and delegates to the SAME span-building core\n * (`createSpanFromMessage` / `enrichSpanOnEnd`) the v7 subscriber uses, so the\n * emitted spans are identical between v6 and v7.\n *\n * The model call (`languageModelCall` / `generate_content` span) has no\n * injectable definition in `ai`, so we instead wrap `resolveLanguageModel` (the\n * single chokepoint every model call flows through) and monkey-patch\n * `doGenerate`/`doStream` on the returned model.\n */\n\n/** Shape orchestrion's transform attaches to the tracing-channel context. */\ninterface OrchestrionContext {\n arguments: unknown[];\n result?: unknown;\n error?: unknown;\n}\n\n/** Builds the normalized message for a channel from the wrapped call's first-arg options. */\ntype MessageBuilder = (options: Record<string, unknown>, telemetry: Record<string, unknown>) => VercelAiChannelMessage;\n\n/** A resolved `ai` language model — has `doGenerate`/`doStream` and identity fields. */\ninterface ResolvedModel {\n modelId?: string;\n provider?: string;\n doGenerate?: (...args: unknown[]) => Promise<unknown>;\n doStream?: (...args: unknown[]) => Promise<unknown>;\n}\n\nconst PATCHED = Symbol('SentryVercelAiModelPatched');\n\n/** A resolved model with our patch bookkeeping (idempotency flag). */\ntype PatchableModel = ResolvedModel & { [PATCHED]?: boolean };\n\n// Per-operation correlation id. No Date/random (unavailable / non-deterministic) — a counter is enough.\nlet callIdCounter = 0;\nfunction nextCallId(): string {\n return `v6-${++callIdCounter}`;\n}\n\n// The message built on `start` for each operation, keyed by the (stable-identity) channel context, so\n// the `beforeSpanEnd` handler can enrich the span from the settled result and clear the `callId` maps.\nconst messages = new WeakMap<object, VercelAiChannelMessage>();\n// The spans we opened for top-level operations, and each one's `callId`. A model call resolves its\n// parent against this set (so it never mis-attributes to the enclosing `main`/user span) and reads the\n// parent's `callId` so its span can be named after the operation (e.g. `ai.streamText.doStream`).\nconst operationSpans = new WeakSet<Span>();\nconst callIdBySpan = new WeakMap<Span, string>();\n// The operation's per-call recording flags (`experimental_telemetry.recordInputs/recordOutputs`), keyed by\n// its span. A model call carries no telemetry of its own, so it inherits the enclosing operation's flags —\n// otherwise a per-call `recordInputs: true` would record inputs on the `invoke_agent` span but not on the\n// child `generate_content` span (whose event would fall back to the global default). v7's channel forwards\n// these flags on every event, so this keeps v6 identical.\nconst recordingBySpan = new WeakMap<Span, ReturnType<typeof recording>>();\n\n// The `experimental_telemetry` objects we swapped in to suppress `ai`'s native OTel spans (see\n// `suppressNativeTelemetry`). Our skip logic treats `isEnabled === false` as \"user disabled telemetry,\n// emit no span\"; without this set, a call whose options object we already neutralized — or a user-shared\n// telemetry object we replaced on a prior call — would be misread as user-disabled and lose its span.\nconst suppressedTelemetry = new WeakSet<object>();\n\nlet subscribed = false;\n\n/**\n * Subscribe the v6 orchestrion channel adapter. Safe to always call: inert on\n * `ai` >= 7 (those channels are never published) and when orchestrion injection\n * isn't active. Idempotent.\n *\n * `tracingChannel` is the platform-provided factory (the same one passed to\n * `subscribeVercelAiTracingChannel`); `options` pins the recording settings at\n * subscribe time so we never look the integration up per event.\n */\nexport function subscribeVercelAiOrchestrionChannels(\n tracingChannel: VercelAiTracingChannelFactory,\n options: VercelAiChannelOptions = {},\n): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n try {\n bindOperation(tracingChannel, CHANNELS.VERCEL_AI_GENERATE_TEXT, buildTextMessage('generateText'), options);\n bindOperation(tracingChannel, CHANNELS.VERCEL_AI_STREAM_TEXT, buildTextMessage('streamText'), options);\n bindOperation(\n tracingChannel,\n CHANNELS.VERCEL_AI_EMBED,\n (callOptions, telemetry) => ({\n type: 'embed',\n event: {\n callId: nextCallId(),\n ...modelFields(callOptions.model),\n maxRetries: callOptions.maxRetries,\n value: callOptions.value,\n ...recording(telemetry),\n },\n }),\n options,\n );\n bindOperation(\n tracingChannel,\n CHANNELS.VERCEL_AI_EMBED_MANY,\n // `embedMany` takes a `values` array (vs `embed`'s single `value`); the shared core reads it as the\n // embeddings input, matching the OTel path's batch `ai.embedMany` span.\n (callOptions, telemetry) => ({\n type: 'embedMany',\n event: {\n callId: nextCallId(),\n ...modelFields(callOptions.model),\n maxRetries: callOptions.maxRetries,\n values: callOptions.values,\n ...recording(telemetry),\n },\n }),\n options,\n );\n bindOperation(\n tracingChannel,\n CHANNELS.VERCEL_AI_EXECUTE_TOOL_CALL,\n (callOptions, telemetry) => ({\n type: 'executeTool',\n // v6 carries the tool definitions on the executeToolCall args (a record keyed by name);\n // the shared core reads the matching tool's `description` for the span.\n event: {\n callId: nextCallId(),\n toolCall: callOptions.toolCall,\n tools: callOptions.tools,\n ...recording(telemetry),\n },\n }),\n options,\n );\n subscribeResolveLanguageModel(tracingChannel, CHANNELS.VERCEL_AI_RESOLVE_LANGUAGE_MODEL, options);\n } catch {\n DEBUG_BUILD && debug.log('Vercel AI orchestrion channel subscription failed.');\n }\n}\n\n/**\n * Bind one operation channel: `getSpan` opens a span from the message reconstructed out of the wrapped\n * call's first argument; `beforeSpanEnd` enriches it from the settled result (tokens, output messages,\n * finish reasons, …) before the helper ends the span.\n *\n * An operation whose `experimental_telemetry.isEnabled` is explicitly `false` is skipped entirely (no\n * span): the orchestrion channel fires regardless of that flag, whereas v7's native `ai:telemetry`\n * channel is simply not published in that case — so we reproduce v7's \"no telemetry → no span\".\n */\nfunction bindOperation(\n tracingChannel: VercelAiTracingChannelFactory,\n channelName: string,\n build: MessageBuilder,\n options: VercelAiChannelOptions,\n): void {\n const channel = tracingChannel<OrchestrionContext>(channelName);\n\n // Build the operation span from the wrapped call's first argument and track it (so a model call can\n // resolve it as its parent). `bindTracingChannelToSpan` calls this once at channel `start` and makes\n // the returned span the active async context for the operation's duration — that active span is what\n // `resolveModelCallParent` reads. It also sets `data._sentrySpan`, so we don't here.\n const buildOperationSpan = (data: TracingChannelPayloadWithSpan<OrchestrionContext>): Span | undefined => {\n const callOptions = isRecord(data.arguments[0]) ? data.arguments[0] : {};\n const telemetry = isRecord(callOptions.experimental_telemetry) ? callOptions.experimental_telemetry : {};\n // `isEnabled === false` means the user opted out — emit no span. But `isEnabled` is also `false` on\n // the telemetry object we swap in to suppress native spans, so don't mistake our own object for a\n // user opt-out (which would drop the span on a call whose options we already neutralized).\n if (telemetry.isEnabled === false && !suppressedTelemetry.has(telemetry)) {\n return undefined;\n }\n const message = build(callOptions, telemetry);\n // Stop `ai` from emitting its own native OTel spans for this call — we build the equivalent spans\n // from the channels, so the SDK's would be duplicates. Reads above have already captured everything\n // we need off `telemetry`.\n suppressNativeTelemetry(callOptions, telemetry);\n const span = createSpanFromMessage(message, options);\n if (span) {\n messages.set(data, message);\n operationSpans.add(span);\n const callId = asString(message.event.callId);\n if (callId) {\n callIdBySpan.set(span, callId);\n }\n recordingBySpan.set(span, recording(telemetry));\n }\n return span;\n };\n\n bindTracingChannelToSpan(\n channel,\n (data: TracingChannelPayloadWithSpan<OrchestrionContext>) => buildOperationSpan(data),\n {\n beforeSpanEnd: (span, data) => {\n const message = messages.get(data);\n if (!message) {\n return;\n }\n // The helper's `error` handler already set the span status; only enrich from a successful result.\n if (!('error' in data)) {\n // v6's `executeToolCall` returns the tool result/error object directly, whereas the shared core\n // (matching v7) expects it nested under `output`; wrap it so tool-error detection works.\n message.result = message.type === 'executeTool' ? { output: data.result } : data.result;\n enrichSpanOnEnd(span, message, options);\n }\n // A `streamText` model call runs after this (synchronously-returning) operation's span has\n // already ended, so its `callId` entry must outlive the operation — it's cleared once the model\n // call settles (see `patchModelMethod`). Every other operation can clear here.\n if (message.type !== 'streamText') {\n clearOperationId(message);\n }\n messages.delete(data);\n },\n },\n );\n}\n\n/**\n * Neutralize `ai`'s native OpenTelemetry instrumentation for this call by pointing\n * `experimental_telemetry` at a copy with `isEnabled: false`. `ai`'s `getTracer` then returns its\n * internal no-op tracer, so it never creates (nor sets active) the duplicate `ai.*` spans we'd\n * otherwise have to drop.\n *\n * Only a call that explicitly enabled telemetry emits native spans — otherwise `ai` already uses its\n * no-op tracer, so there's nothing to suppress and we leave the user's options untouched. When\n * `isEnabled === true`, `telemetry` is `callOptions.experimental_telemetry` and `callOptions` is the\n * real first argument the SDK will read, so the reassignment takes effect for the wrapped call. We\n * replace rather than mutate in place, so a telemetry object the user shares across calls keeps its own\n * `isEnabled: true`; the replacement is tracked in `suppressedTelemetry` so our skip logic doesn't\n * later read it back as a user opt-out.\n */\nfunction suppressNativeTelemetry(callOptions: Record<string, unknown>, telemetry: Record<string, unknown>): void {\n if (telemetry.isEnabled !== true) {\n return;\n }\n const suppressed = { ...telemetry, isEnabled: false };\n suppressedTelemetry.add(suppressed);\n callOptions.experimental_telemetry = suppressed;\n}\n\n/**\n * `resolveLanguageModel` returns the model every call flows through. We don't span it — on `end` we\n * monkey-patch `doGenerate`/`doStream` on the returned model so each invocation produces a\n * `languageModelCall` span parented to the enclosing invoke_agent span.\n */\nfunction subscribeResolveLanguageModel(\n tracingChannel: VercelAiTracingChannelFactory,\n channelName: string,\n options: VercelAiChannelOptions,\n): void {\n tracingChannel<OrchestrionContext>(channelName).subscribe({\n end(rawCtx) {\n const ctx = rawCtx as OrchestrionContext;\n if (!isRecord(ctx.result)) {\n return;\n }\n const model = ctx.result as PatchableModel;\n // Patch the model's `doGenerate`/`doStream` once. The model call recovers its parent from the\n // active async context at call time (the operation span `bindTracingChannelToSpan` bound), which\n // propagates into the model call for `streamText` too, so there is nothing to capture on the model here.\n if (!model[PATCHED]) {\n model[PATCHED] = true;\n patchModelMethod(model, 'doGenerate', options);\n patchModelMethod(model, 'doStream', options);\n }\n },\n start() {\n /* no-op */\n },\n asyncStart() {\n /* no-op */\n },\n asyncEnd() {\n /* no-op */\n },\n error() {\n /* no-op */\n },\n });\n}\n\n/**\n * Pick the invoke_agent span a model call should hang under: the operation span that\n * `bindTracingChannelToSpan` planted as the active async context for the enclosing operation.\n *\n * Because we suppress `ai`'s native telemetry (so it never installs its own span as active), the active\n * span inside `doGenerate`/`doStream` is our operation span. The `operationSpans` gate makes this return\n * `undefined` when the active span isn't one of ours — e.g. telemetry was disabled for the call so we\n * opened no operation span and the active span is the user's enclosing span — so the model call is\n * skipped rather than mis-parented.\n *\n * This covers `generateText`/`embed` (whose model call is awaited inside the operation body) and\n * `streamText` alike — `ai` initiates the stream synchronously within the operation's bound context, so\n * the later `doStream` continuation restores the same active span even though the operation's span has\n * already ended. The per-operation binding also disambiguates concurrent calls that share one model\n * instance (a single mutable slot on the shared model could not — it would hold whichever operation\n * resolved the model last).\n */\nfunction resolveModelCallParent(): Span | undefined {\n const active = getActiveSpan();\n return active && operationSpans.has(active) ? active : undefined;\n}\n\nfunction patchModelMethod(\n model: PatchableModel,\n method: 'doGenerate' | 'doStream',\n options: VercelAiChannelOptions,\n): void {\n const original = model[method];\n if (typeof original !== 'function') {\n return;\n }\n model[method] = function (this: unknown, ...args: unknown[]): Promise<unknown> {\n const parent = resolveModelCallParent();\n // No enclosing operation span (e.g. telemetry disabled for the call) → don't open a model-call span.\n if (!parent) {\n return Promise.resolve(original.apply(this, args));\n }\n\n const callArgs = isRecord(args[0]) ? args[0] : {};\n // Carry the operation's `callId` so the shared core can name the span after it\n // (`ai.generateText.doGenerate` / `ai.streamText.doStream`).\n const callId = callIdBySpan.get(parent);\n const message: VercelAiChannelMessage = {\n type: 'languageModelCall',\n event: {\n callId,\n provider: model.provider,\n modelId: model.modelId,\n tools: callArgs.tools,\n messages: callArgs.prompt,\n // Inherit the enclosing operation's per-call recording flags so inputs/tools/outputs are recorded on\n // the model-call span whenever they are on the parent `invoke_agent` span.\n ...recordingBySpan.get(parent),\n },\n };\n const span = withActiveSpan(parent, () => createSpanFromMessage(message, options));\n // `languageModelCall` always opens a span; the guard just keeps the wrapper safe if that changes.\n if (!span) {\n return Promise.resolve(original.apply(this, args));\n }\n\n // `streamText` ends its operation span synchronously, so its `callId` entry was deliberately left in\n // place for this later model call; drop it now that we've used it.\n const clearStreamCallId = (): void => {\n if (method === 'doStream' && callId) {\n clearOperationCallId(callId);\n }\n };\n\n // Both the synchronous throw and the async rejection of the model call must end the span with an\n // error status (an `async` `doGenerate`/`doStream` that throws rejects rather than throwing here).\n const failSpan = (error: unknown): never => {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: error instanceof Error ? error.message : 'unknown_error' });\n span.end();\n clearStreamCallId();\n throw error;\n };\n\n try {\n const result = Promise.resolve(original.apply(this, args));\n // `doStream` resolves to `{ stream, ... }` before the stream is consumed; we end here (start/end\n // bracket the call) to match the channel timing.\n return result.then(value => {\n message.result = value;\n enrichSpanOnEnd(span, message, options);\n span.end();\n clearStreamCallId();\n return value;\n }, failSpan);\n } catch (error) {\n return failSpan(error);\n }\n };\n}\n\nfunction buildTextMessage(type: 'generateText' | 'streamText'): MessageBuilder {\n return (options, telemetry) => ({\n type,\n event: {\n callId: nextCallId(),\n operationId: `ai.${type}`,\n functionId: asString(telemetry.functionId),\n ...modelFields(options.model),\n maxRetries: options.maxRetries,\n // Normalize to the message-array shape the shared core (and v7's channel) expects: a bare string\n // `prompt` becomes a single user message, matching the SDK's own normalization.\n messages: normalizePromptMessages(options),\n ...recording(telemetry),\n },\n });\n}\n\nfunction normalizePromptMessages(options: Record<string, unknown>): unknown {\n if (Array.isArray(options.messages)) {\n return options.messages;\n }\n if (typeof options.prompt === 'string') {\n return [{ role: 'user', content: options.prompt }];\n }\n return options.messages ?? options.prompt;\n}\n\nfunction recording(telemetry: Record<string, unknown>): { recordInputs: unknown; recordOutputs: unknown } {\n return { recordInputs: telemetry.recordInputs, recordOutputs: telemetry.recordOutputs };\n}\n\nfunction modelFields(model: unknown): { provider?: string; modelId?: string } {\n return { provider: modelField(model, 'provider'), modelId: modelField(model, 'modelId') };\n}\n\nfunction modelField(model: unknown, field: 'modelId' | 'provider'): string | undefined {\n return isRecord(model) ? asString(model[field]) : undefined;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n"],"names":[],"mappings":"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"}
import { AnthropicAiOptions } from '@sentry/core';
/**
* EXPERIMENTAL — orchestrion-driven Anthropic integration. Subscribes to the `orchestrion:@anthropic-ai/sdk:*`
* diagnostics_channels injected into the SDK's chat (`messages`/`completions`/beta `messages`), `models`, and
* `messages.stream()` methods, so it requires the orchestrion runtime hook or bundler plugin.
*/
export declare const anthropicChannelIntegration: (options?: AnthropicAiOptions | undefined) => import("@sentry/core").Integration & {
name: "Anthropic_AI";
};
//# sourceMappingURL=anthropic.d.ts.map
declare const LIFECYCLE_EXT_POINTS: readonly [
"onPreAuth",
"onCredentials",
"onPostAuth",
"onPreHandler",
"onPostHandler",
"onPreResponse",
"onRequest"
];
export type ServerRequestExtType = (typeof LIFECYCLE_EXT_POINTS)[number];
export type LifecycleMethod = (request: unknown, h: unknown, err?: Error) => unknown;
export interface ServerRouteOptions {
handler?: LifecycleMethod | unknown;
[key: string]: unknown;
}
export interface ServerRoute {
path: string;
method: string;
handler?: LifecycleMethod | unknown;
options?: ((server: unknown) => ServerRouteOptions) | ServerRouteOptions;
[key: string]: unknown;
}
export interface ServerExtEventsObject {
type: string;
[key: string]: unknown;
}
export interface ServerExtEventsRequestObject {
type: ServerRequestExtType;
method: LifecycleMethod;
[key: string]: unknown;
}
export interface ServerExtOptions {
[key: string]: unknown;
}
/**
* This symbol is used to mark a Hapi route handler or server extension handler as
* already patched, since it's possible to use these handlers multiple times
* i.e. when allowing multiple versions of one plugin, or when registering a plugin
* multiple times on different servers.
*/
export declare const handlerPatched: unique symbol;
export type PatchableServerRoute = ServerRoute & {
[handlerPatched]?: boolean;
};
export type PatchableExtMethod = LifecycleMethod & {
[handlerPatched]?: boolean;
};
export type ServerExtDirectInput = [
ServerRequestExtType,
LifecycleMethod,
(ServerExtOptions | undefined)?
];
export declare const HapiLayerType: {
readonly ROUTER: "router";
readonly PLUGIN: "plugin";
readonly EXT: "server.ext";
};
export declare const HapiLifecycleMethodNames: Set<string>;
export declare enum AttributeNames {
HAPI_TYPE = "hapi.type",
PLUGIN_NAME = "hapi.plugin.name",
EXT_TYPE = "server.ext.type"
}
export {};
//# sourceMappingURL=hapi-types.d.ts.map
import { ServerRequestExtType, ServerRoute } from './hapi-types';
type SpanAttributes = Record<string, string | undefined>;
interface SpanMetadata {
attributes: SpanAttributes;
name: string;
}
/** Build the span name and attributes for a Hapi route. */
export declare const getRouteMetadata: (route: ServerRoute, pluginName?: string) => SpanMetadata;
/** Build the span name and attributes for a Hapi server extension. */
export declare const getExtMetadata: (extPoint: ServerRequestExtType, pluginName?: string, methodName?: string) => SpanMetadata;
/**
* Wrap the route handler(s) in the live `server.route` arguments array, mutating
* `args[0]` in place. `args[0]` is either a single route options object or an
* array of them. Idempotent via the `handlerPatched` marker.
*/
export declare function wrapRouteArguments(args: unknown[], pluginName?: string): void;
/**
* Wrap the extension method(s) in the live `server.ext` arguments array,
* mutating `args` in place. Handles the three accepted input shapes:
* `(eventsArray)`, `(lifecycleEventObject)`, and `(extTypeString, method, options)`.
* Idempotent via the `handlerPatched` marker.
*/
export declare function wrapExtArguments(args: unknown[], pluginName?: string): void;
export {};
//# sourceMappingURL=hapi-utils.d.ts.map
/**
* EXPERIMENTAL — orchestrion-driven hapi integration. Subscribes to the
* `orchestrion:@hapi/hapi:route` / `:ext` channels injected into `@hapi/hapi`'s
* `lib/server.js`. Requires the orchestrion runtime hook or bundler plugin.
*/
export declare const hapiChannelIntegration: () => import("@sentry/core").Integration & {
name: "Hapi";
};
//# sourceMappingURL=hapi.d.ts.map
import { Span } from '@sentry/core';
/** Mirrors `@opentelemetry/instrumentation-ioredis`' response hook. Not called for failed commands. */
export type IORedisResponseHook = (span: Span, command: string, args: Array<string | Buffer>, result: unknown) => void;
export interface IORedisChannelIntegrationOptions {
responseHook?: IORedisResponseHook;
}
/**
* EXPERIMENTAL — orchestrion-driven ioredis integration. Subscribes to
* `orchestrion:ioredis:command` / `:connect` (injected into ioredis' `<5.11.0`
* `sendCommand`/`connect`) and creates db spans matching
* `@opentelemetry/instrumentation-ioredis`. Requires the orchestrion runtime hook
* or bundler plugin.
*/
export declare const ioredisChannelIntegration: (options?: IORedisChannelIntegrationOptions | undefined) => import("@sentry/core").Integration & {
name: "IORedis";
};
//# sourceMappingURL=ioredis.d.ts.map
import { OpenAiOptions } from '@sentry/core';
/**
* EXPERIMENTAL — orchestrion-driven OpenAI integration. Subscribes to the `orchestrion:openai:*`
* diagnostics_channels injected into `openai`'s `create` methods (chat completions, responses, embeddings,
* conversations), so it requires the orchestrion runtime hook or bundler plugin.
*/
export declare const openaiChannelIntegration: (options?: OpenAiOptions | undefined) => import("@sentry/core").Integration & {
name: "OpenAI";
};
//# sourceMappingURL=openai.d.ts.map
/**
* EXPERIMENTAL: orchestrion-driven `pg` (node-postgres) integration.
*
* Subscribes to the `orchestrion:pg:query`/`:connect` and
* `orchestrion:pg-pool:connect` diagnostics_channels that the orchestrion code
* transform injects into `pg`'s `Client.prototype.query`/`connect`
* and `pg-pool`'s `Pool.prototype.connect`. Requires the orchestrion runtime
* hook or bundler plugin to be active.
*/
export declare const postgresChannelIntegration: (options?: {
ignoreConnectSpans?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "Postgres";
};
//# sourceMappingURL=postgres.d.ts.map
/**
* Auto-instrument the `ai` SDK. Supported are:
* - v7 via native `ai:telemetry` tracing channel
* - v6 via orchestrion `orchestrion:ai:*` channels
*/
export declare const vercelAiChannelIntegration: (options?: {
recordInputs?: boolean;
recordOutputs?: boolean;
enableTruncation?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "VercelAI";
};
//# sourceMappingURL=vercel-ai.d.ts.map
/**
* Auto-instrument the [mongoose](https://www.npmjs.com/package/mongoose) library via its native
* `node:diagnostics_channel` tracing channels (mongoose >= 9.7).
*
* On older mongoose versions the channels are never published to, so this integration is inert and
* the IITM-based patcher (gated to `< 9.7.0`) handles instrumentation instead.
*/
export declare const mongooseIntegration: () => import("@sentry/core").Integration & {
name: string;
};
//# sourceMappingURL=index.d.ts.map
import { TracingChannel } from 'node:diagnostics_channel';
export declare const MONGOOSE_DC_CHANNEL_QUERY = "mongoose:query";
export declare const MONGOOSE_DC_CHANNEL_AGGREGATE = "mongoose:aggregate";
export declare const MONGOOSE_DC_CHANNEL_MODEL_SAVE = "mongoose:model:save";
export declare const MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = "mongoose:model:insertMany";
export declare const MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = "mongoose:model:bulkWrite";
export declare const MONGOOSE_DC_CHANNEL_CURSOR_NEXT = "mongoose:cursor:next";
/**
* Shape of the context object mongoose >= 9.7.0 publishes on its tracing
* channels (mongoose's `TracingContext`, see `types/tracing.d.ts`).
*
* Node's `tracePromise` mutates this same object with `result`/`error` once the
* operation settles, which `bindTracingChannelToSpan` reads in its lifecycle
* handlers — hence both are declared optional here.
*
* Unlike redis/ioredis, mongoose does NOT pre-sanitize the payload, so `args`
* carries the raw user query. We redact it before emitting `db.query.text`.
*/
export interface MongooseTracingData {
operation: string;
/** Absent for connection-level `aggregate()` calls, which have no model/collection. */
collection?: string;
database?: string;
serverAddress?: string;
serverPort?: number;
/** Cursor channels only: the cursor's fetch batch size and tailable flag. */
batchSize?: number;
tailable?: boolean;
/**
* Operation-specific arguments. `filter` (queries/cursors) and `pipeline`
* (aggregations) carry the query shape; `docs`/`ops` carry batch payloads.
*/
args?: {
filter?: unknown;
pipeline?: unknown;
docs?: unknown;
ops?: unknown;
[key: string]: unknown;
};
result?: unknown;
error?: Error;
}
/**
* Platform-provided factory that creates a native tracing channel for the given name. The
* subscriber binds the span and its lifecycle onto the channel via `bindTracingChannelToSpan`,
* which propagates the active span through the runtime's async context.
*
* Node passes `node:diagnostics_channel`'s `tracingChannel` directly.
*/
export type MongooseTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;
/**
* Subscribe Sentry span handlers to mongoose's diagnostics-channel events
* (`mongoose:query`, `:aggregate`, `:model:save`, `:model:insertMany`,
* `:model:bulkWrite`, `:cursor:next`), published by mongoose >= 9.7.0.
*
* On older mongoose versions the channels are never published to, so the
* subscribers are inert — there is no double-instrumentation against the
* IITM-based vendored patcher, which is gated to `< 9.7.0`.
*
* Idempotent: subsequent calls are a no-op.
*/
export declare function subscribeMongooseDiagnosticChannels(tracingChannel: MongooseTracingChannelFactory): void;
//# sourceMappingURL=mongoose-dc-subscriber.d.ts.map
export declare const anthropicAiConfig: ({
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Auto";
};
} | {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Sync";
};
})[];
export declare const anthropicAiChannels: {
readonly ANTHROPIC_CHAT: "orchestrion:@anthropic-ai/sdk:chat";
readonly ANTHROPIC_MODELS: "orchestrion:@anthropic-ai/sdk:models";
readonly ANTHROPIC_MESSAGES_STREAM: "orchestrion:@anthropic-ai/sdk:messages-stream";
};
//# sourceMappingURL=anthropic-ai.d.ts.map
export declare const hapiConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
methodName: string;
kind: "Sync";
};
}[];
export declare const hapiChannels: {
readonly HAPI_ROUTE: "orchestrion:@hapi/hapi:route";
readonly HAPI_EXT: "orchestrion:@hapi/hapi:ext";
};
//# sourceMappingURL=hapi.d.ts.map
import { InstrumentationConfig } from '@apm-js-collab/code-transformer';
export declare const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[];
/**
* The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`
* (e.g. `['mysql']`).
*
* Bundler plugins MUST ensure these are actually bundled rather than
* externalized: an externalized dependency is resolved from `node_modules` at
* runtime and never passes through the code transform's `onLoad`, so its
* diagnostics_channel calls are silently never injected.
*/
export declare const INSTRUMENTED_MODULE_NAMES: string[];
/**
* Returns `external` with any instrumented packages removed, so a bundler that
* uses an "external" denylist (esbuild, Bun, Rollup) still bundles — and thus
* transforms — them. Matches an exact package name (`'mysql'`) or a subpath
* (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`
* is returned unchanged.
*
* (Vite uses an `ssr.noExternal` allowlist instead, so it consumes
* `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)
*/
export declare function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined;
//# sourceMappingURL=index.d.ts.map
import { InstrumentationConfig } from '@apm-js-collab/code-transformer';
export declare const ioredisConfig: InstrumentationConfig[];
export declare const ioredisChannels: {
readonly IOREDIS_COMMAND: "orchestrion:ioredis:command";
readonly IOREDIS_CONNECT: "orchestrion:ioredis:connect";
};
//# sourceMappingURL=ioredis.d.ts.map
export declare const lruMemoizerConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
functionName: string;
kind: "Callback";
};
}[];
export declare const lruMemoizerChannels: {
readonly LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load";
};
//# sourceMappingURL=lru-memoizer.d.ts.map
export declare const mysqlConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
expressionName: string;
kind: "Auto";
};
}[];
export declare const mysqlChannels: {
readonly MYSQL_QUERY: "orchestrion:mysql:query";
};
//# sourceMappingURL=mysql.d.ts.map
export declare const openaiConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Auto";
};
}[];
export declare const openaiChannels: {
readonly OPENAI_CHAT: "orchestrion:openai:chat";
readonly OPENAI_RESPONSES: "orchestrion:openai:responses";
readonly OPENAI_EMBEDDINGS: "orchestrion:openai:embeddings";
readonly OPENAI_CONVERSATIONS: "orchestrion:openai:conversations";
};
//# sourceMappingURL=openai.d.ts.map
export declare const pgConfig: ({
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Auto";
expressionName?: undefined;
};
} | {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
expressionName: string;
kind: "Auto";
className?: undefined;
methodName?: undefined;
};
})[];
export declare const pgChannels: {
readonly PG_QUERY: "orchestrion:pg:query";
readonly PG_CONNECT: "orchestrion:pg:connect";
readonly PGPOOL_CONNECT: "orchestrion:pg-pool:connect";
};
//# sourceMappingURL=pg.d.ts.map
import { InstrumentationConfig } from '@apm-js-collab/code-transformer';
export declare const vercelAiConfig: InstrumentationConfig[];
export declare const vercelAiChannels: {
readonly VERCEL_AI_GENERATE_TEXT: "orchestrion:ai:generateText";
readonly VERCEL_AI_STREAM_TEXT: "orchestrion:ai:streamText";
readonly VERCEL_AI_EMBED: "orchestrion:ai:embed";
readonly VERCEL_AI_EMBED_MANY: "orchestrion:ai:embedMany";
readonly VERCEL_AI_EXECUTE_TOOL_CALL: "orchestrion:ai:executeToolCall";
readonly VERCEL_AI_RESOLVE_LANGUAGE_MODEL: "orchestrion:ai:resolveLanguageModel";
};
//# sourceMappingURL=vercel-ai.d.ts.map
/**
* Given the redis command name and arguments, return a combination of the
* command name + the allowed arguments according to `serializationSubsets`.
*/
export declare const defaultDbStatementSerializer: (cmdName: string, cmdArgs: Array<string | Buffer | number | unknown[]>) => string;
//# sourceMappingURL=redis-statement-serializer.d.ts.map
import { VercelAiChannelOptions, VercelAiTracingChannelFactory } from './vercel-ai-dc-subscriber';
/**
* Subscribe the v6 orchestrion channel adapter. Safe to always call: inert on
* `ai` >= 7 (those channels are never published) and when orchestrion injection
* isn't active. Idempotent.
*
* `tracingChannel` is the platform-provided factory (the same one passed to
* `subscribeVercelAiTracingChannel`); `options` pins the recording settings at
* subscribe time so we never look the integration up per event.
*/
export declare function subscribeVercelAiOrchestrionChannels(tracingChannel: VercelAiTracingChannelFactory, options?: VercelAiChannelOptions): void;
//# sourceMappingURL=vercel-ai-orchestrion-v6-subscriber.d.ts.map
import type { AnthropicAiOptions } from '@sentry/core';
/**
* EXPERIMENTAL — orchestrion-driven Anthropic integration. Subscribes to the `orchestrion:@anthropic-ai/sdk:*`
* diagnostics_channels injected into the SDK's chat (`messages`/`completions`/beta `messages`), `models`, and
* `messages.stream()` methods, so it requires the orchestrion runtime hook or bundler plugin.
*/
export declare const anthropicChannelIntegration: (options?: AnthropicAiOptions | undefined) => import("@sentry/core").Integration & {
name: "Anthropic_AI";
};
//# sourceMappingURL=anthropic.d.ts.map
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAgE,MAAM,cAAc,CAAC;AAgLrH;;;;GAIG;AACH,eAAO,MAAM,2BAA2B;;CAAkD,CAAC"}
declare const LIFECYCLE_EXT_POINTS: readonly ["onPreAuth", "onCredentials", "onPostAuth", "onPreHandler", "onPostHandler", "onPreResponse", "onRequest"];
export type ServerRequestExtType = (typeof LIFECYCLE_EXT_POINTS)[number];
export type LifecycleMethod = (request: unknown, h: unknown, err?: Error) => unknown;
export interface ServerRouteOptions {
handler?: LifecycleMethod | unknown;
[key: string]: unknown;
}
export interface ServerRoute {
path: string;
method: string;
handler?: LifecycleMethod | unknown;
options?: ((server: unknown) => ServerRouteOptions) | ServerRouteOptions;
[key: string]: unknown;
}
export interface ServerExtEventsObject {
type: string;
[key: string]: unknown;
}
export interface ServerExtEventsRequestObject {
type: ServerRequestExtType;
method: LifecycleMethod;
[key: string]: unknown;
}
export interface ServerExtOptions {
[key: string]: unknown;
}
/**
* This symbol is used to mark a Hapi route handler or server extension handler as
* already patched, since it's possible to use these handlers multiple times
* i.e. when allowing multiple versions of one plugin, or when registering a plugin
* multiple times on different servers.
*/
export declare const handlerPatched: unique symbol;
export type PatchableServerRoute = ServerRoute & {
[handlerPatched]?: boolean;
};
export type PatchableExtMethod = LifecycleMethod & {
[handlerPatched]?: boolean;
};
export type ServerExtDirectInput = [ServerRequestExtType, LifecycleMethod, (ServerExtOptions | undefined)?];
export declare const HapiLayerType: {
readonly ROUTER: "router";
readonly PLUGIN: "plugin";
readonly EXT: "server.ext";
};
export declare const HapiLifecycleMethodNames: Set<string>;
export declare enum AttributeNames {
HAPI_TYPE = "hapi.type",
PLUGIN_NAME = "hapi.plugin.name",
EXT_TYPE = "server.ext.type"
}
export {};
//# sourceMappingURL=hapi-types.d.ts.map
{"version":3,"file":"hapi-types.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/hapi-types.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,oBAAoB,sHAQhB,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,KAAK,OAAO,CAAC;AAErF,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,kBAAkB,CAAC,GAAG,kBAAkB,CAAC;IACzE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,EAAE,eAAe,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,MAAuC,CAAC;AAE5E,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG;IAC/C,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG;IACjD,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,oBAAoB,EAAE,eAAe,EAAE,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAE5G,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAEX,eAAO,MAAM,wBAAwB,aAAwC,CAAC;AAE9E,oBAAY,cAAc;IACxB,SAAS,cAAc;IACvB,WAAW,qBAAqB;IAChC,QAAQ,oBAAoB;CAC7B"}
import type { ServerRequestExtType, ServerRoute } from './hapi-types';
type SpanAttributes = Record<string, string | undefined>;
interface SpanMetadata {
attributes: SpanAttributes;
name: string;
}
/** Build the span name and attributes for a Hapi route. */
export declare const getRouteMetadata: (route: ServerRoute, pluginName?: string) => SpanMetadata;
/** Build the span name and attributes for a Hapi server extension. */
export declare const getExtMetadata: (extPoint: ServerRequestExtType, pluginName?: string, methodName?: string) => SpanMetadata;
/**
* Wrap the route handler(s) in the live `server.route` arguments array, mutating
* `args[0]` in place. `args[0]` is either a single route options object or an
* array of them. Idempotent via the `handlerPatched` marker.
*/
export declare function wrapRouteArguments(args: unknown[], pluginName?: string): void;
/**
* Wrap the extension method(s) in the live `server.ext` arguments array,
* mutating `args` in place. Handles the three accepted input shapes:
* `(eventsArray)`, `(lifecycleEventObject)`, and `(extTypeString, method, options)`.
* Idempotent via the `handlerPatched` marker.
*/
export declare function wrapExtArguments(args: unknown[], pluginName?: string): void;
export {};
//# sourceMappingURL=hapi-utils.d.ts.map
{"version":3,"file":"hapi-utils.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/hapi-utils.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAOV,oBAAoB,EACpB,WAAW,EAEZ,MAAM,cAAc,CAAC;AAKtB,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEzD,UAAU,YAAY;IACpB,UAAU,EAAE,cAAc,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAgDD,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,GAAI,OAAO,WAAW,EAAE,aAAa,MAAM,KAAG,YAkB1E,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,cAAc,GACzB,UAAU,oBAAoB,EAC9B,aAAa,MAAM,EACnB,aAAa,MAAM,KAClB,YAuBF,CAAC;AAoFF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAS7E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAwB3E"}
/**
* EXPERIMENTAL — orchestrion-driven hapi integration. Subscribes to the
* `orchestrion:@hapi/hapi:route` / `:ext` channels injected into `@hapi/hapi`'s
* `lib/server.js`. Requires the orchestrion runtime hook or bundler plugin.
*/
export declare const hapiChannelIntegration: () => import("@sentry/core").Integration & {
name: "Hapi";
};
//# sourceMappingURL=hapi.d.ts.map
{"version":3,"file":"hapi.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/hapi.ts"],"names":[],"mappings":"AAgEA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;CAA6C,CAAC"}
import type { Span } from '@sentry/core';
/** Mirrors `@opentelemetry/instrumentation-ioredis`' response hook. Not called for failed commands. */
export type IORedisResponseHook = (span: Span, command: string, args: Array<string | Buffer>, result: unknown) => void;
export interface IORedisChannelIntegrationOptions {
responseHook?: IORedisResponseHook;
}
/**
* EXPERIMENTAL — orchestrion-driven ioredis integration. Subscribes to
* `orchestrion:ioredis:command` / `:connect` (injected into ioredis' `<5.11.0`
* `sendCommand`/`connect`) and creates db spans matching
* `@opentelemetry/instrumentation-ioredis`. Requires the orchestrion runtime hook
* or bundler plugin.
*/
export declare const ioredisChannelIntegration: (options?: IORedisChannelIntegrationOptions | undefined) => import("@sentry/core").Integration & {
name: "IORedis";
};
//# sourceMappingURL=ioredis.d.ts.map
{"version":3,"file":"ioredis.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/ioredis.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAiB,IAAI,EAAE,MAAM,cAAc,CAAC;AAwBxD,uGAAuG;AACvG,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;AAEvH,MAAM,WAAW,gCAAgC;IAC/C,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAoHD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB;;CAAgD,CAAC"}
import type { OpenAiOptions } from '@sentry/core';
/**
* EXPERIMENTAL — orchestrion-driven OpenAI integration. Subscribes to the `orchestrion:openai:*`
* diagnostics_channels injected into `openai`'s `create` methods (chat completions, responses, embeddings,
* conversations), so it requires the orchestrion runtime hook or bundler plugin.
*/
export declare const openaiChannelIntegration: (options?: OpenAiOptions | undefined) => import("@sentry/core").Integration & {
name: "OpenAI";
};
//# sourceMappingURL=openai.d.ts.map
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,aAAa,EAA4B,MAAM,cAAc,CAAC;AA6I3F;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;CAA+C,CAAC"}
/**
* EXPERIMENTAL: orchestrion-driven `pg` (node-postgres) integration.
*
* Subscribes to the `orchestrion:pg:query`/`:connect` and
* `orchestrion:pg-pool:connect` diagnostics_channels that the orchestrion code
* transform injects into `pg`'s `Client.prototype.query`/`connect`
* and `pg-pool`'s `Pool.prototype.connect`. Requires the orchestrion runtime
* hook or bundler plugin to be active.
*/
export declare const postgresChannelIntegration: (options?: {
ignoreConnectSpans?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "Postgres";
};
//# sourceMappingURL=postgres.d.ts.map
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/postgres.ts"],"names":[],"mappings":"AAsRA;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B;yBA9M+B,OAAO;;;CA8MW,CAAC"}
/**
* Auto-instrument the `ai` SDK. Supported are:
* - v7 via native `ai:telemetry` tracing channel
* - v6 via orchestrion `orchestrion:ai:*` channels
*/
export declare const vercelAiChannelIntegration: (options?: {
recordInputs?: boolean;
recordOutputs?: boolean;
enableTruncation?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "VercelAI";
};
//# sourceMappingURL=vercel-ai.d.ts.map
{"version":3,"file":"vercel-ai.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/vercel-ai.ts"],"names":[],"mappings":"AAkCA;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;;;CAAiD,CAAC"}
/**
* Auto-instrument the [mongoose](https://www.npmjs.com/package/mongoose) library via its native
* `node:diagnostics_channel` tracing channels (mongoose >= 9.7).
*
* On older mongoose versions the channels are never published to, so this integration is inert and
* the IITM-based patcher (gated to `< 9.7.0`) handles instrumentation instead.
*/
export declare const mongooseIntegration: () => import("@sentry/core").Integration & {
name: string;
};
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mongoose/index.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;CAA0C,CAAC"}
import type { TracingChannel } from 'node:diagnostics_channel';
export declare const MONGOOSE_DC_CHANNEL_QUERY = "mongoose:query";
export declare const MONGOOSE_DC_CHANNEL_AGGREGATE = "mongoose:aggregate";
export declare const MONGOOSE_DC_CHANNEL_MODEL_SAVE = "mongoose:model:save";
export declare const MONGOOSE_DC_CHANNEL_MODEL_INSERT_MANY = "mongoose:model:insertMany";
export declare const MONGOOSE_DC_CHANNEL_MODEL_BULK_WRITE = "mongoose:model:bulkWrite";
export declare const MONGOOSE_DC_CHANNEL_CURSOR_NEXT = "mongoose:cursor:next";
/**
* Shape of the context object mongoose >= 9.7.0 publishes on its tracing
* channels (mongoose's `TracingContext`, see `types/tracing.d.ts`).
*
* Node's `tracePromise` mutates this same object with `result`/`error` once the
* operation settles, which `bindTracingChannelToSpan` reads in its lifecycle
* handlers — hence both are declared optional here.
*
* Unlike redis/ioredis, mongoose does NOT pre-sanitize the payload, so `args`
* carries the raw user query. We redact it before emitting `db.query.text`.
*/
export interface MongooseTracingData {
operation: string;
/** Absent for connection-level `aggregate()` calls, which have no model/collection. */
collection?: string;
database?: string;
serverAddress?: string;
serverPort?: number;
/** Cursor channels only: the cursor's fetch batch size and tailable flag. */
batchSize?: number;
tailable?: boolean;
/**
* Operation-specific arguments. `filter` (queries/cursors) and `pipeline`
* (aggregations) carry the query shape; `docs`/`ops` carry batch payloads.
*/
args?: {
filter?: unknown;
pipeline?: unknown;
docs?: unknown;
ops?: unknown;
[key: string]: unknown;
};
result?: unknown;
error?: Error;
}
/**
* Platform-provided factory that creates a native tracing channel for the given name. The
* subscriber binds the span and its lifecycle onto the channel via `bindTracingChannelToSpan`,
* which propagates the active span through the runtime's async context.
*
* Node passes `node:diagnostics_channel`'s `tracingChannel` directly.
*/
export type MongooseTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;
/**
* Subscribe Sentry span handlers to mongoose's diagnostics-channel events
* (`mongoose:query`, `:aggregate`, `:model:save`, `:model:insertMany`,
* `:model:bulkWrite`, `:cursor:next`), published by mongoose >= 9.7.0.
*
* On older mongoose versions the channels are never published to, so the
* subscribers are inert — there is no double-instrumentation against the
* IITM-based vendored patcher, which is gated to `< 9.7.0`.
*
* Idempotent: subsequent calls are a no-op.
*/
export declare function subscribeMongooseDiagnosticChannels(tracingChannel: MongooseTracingChannelFactory): void;
//# sourceMappingURL=mongoose-dc-subscriber.d.ts.map
{"version":3,"file":"mongoose-dc-subscriber.d.ts","sourceRoot":"","sources":["../../../src/mongoose/mongoose-dc-subscriber.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAmB/D,eAAO,MAAM,yBAAyB,mBAAmB,CAAC;AAC1D,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAClE,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AACpE,eAAO,MAAM,qCAAqC,8BAA8B,CAAC;AACjF,eAAO,MAAM,oCAAoC,6BAA6B,CAAC;AAC/E,eAAO,MAAM,+BAA+B,yBAAyB,CAAC;AAStE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAIrG;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CAAC,cAAc,EAAE,6BAA6B,GAAG,IAAI,CAkBvG"}
export declare const anthropicAiConfig: ({
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Auto";
};
} | {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Sync";
};
})[];
export declare const anthropicAiChannels: {
readonly ANTHROPIC_CHAT: "orchestrion:@anthropic-ai/sdk:chat";
readonly ANTHROPIC_MODELS: "orchestrion:@anthropic-ai/sdk:models";
readonly ANTHROPIC_MESSAGES_STREAM: "orchestrion:@anthropic-ai/sdk:messages-stream";
};
//# sourceMappingURL=anthropic-ai.d.ts.map
{"version":3,"file":"anthropic-ai.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/anthropic-ai.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;IA+BK,CAAC;AAEpC,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC"}
export declare const hapiConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
methodName: string;
kind: "Sync";
};
}[];
export declare const hapiChannels: {
readonly HAPI_ROUTE: "orchestrion:@hapi/hapi:route";
readonly HAPI_EXT: "orchestrion:@hapi/hapi:ext";
};
//# sourceMappingURL=hapi.d.ts.map
{"version":3,"file":"hapi.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/hapi.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU;;;;;;;;;;;GAeY,CAAC;AAEpC,eAAO,MAAM,YAAY;;;CAGf,CAAC"}
import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';
export declare const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[];
/**
* The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`
* (e.g. `['mysql']`).
*
* Bundler plugins MUST ensure these are actually bundled rather than
* externalized: an externalized dependency is resolved from `node_modules` at
* runtime and never passes through the code transform's `onLoad`, so its
* diagnostics_channel calls are silently never injected.
*/
export declare const INSTRUMENTED_MODULE_NAMES: string[];
/**
* Returns `external` with any instrumented packages removed, so a bundler that
* uses an "external" denylist (esbuild, Bun, Rollup) still bundles — and thus
* transforms — them. Matches an exact package name (`'mysql'`) or a subpath
* (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`
* is returned unchanged.
*
* (Vite uses an `ssr.noExternal` allowlist instead, so it consumes
* `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)
*/
export declare function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined;
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAU7E,eAAO,MAAM,uBAAuB,EAAE,qBAAqB,EAS1D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,EAAyE,CAAC;AAExH;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAO1G"}
import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';
export declare const ioredisConfig: InstrumentationConfig[];
export declare const ioredisChannels: {
readonly IOREDIS_COMMAND: "orchestrion:ioredis:command";
readonly IOREDIS_CONNECT: "orchestrion:ioredis:connect";
};
//# sourceMappingURL=ioredis.d.ts.map
{"version":3,"file":"ioredis.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/ioredis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,eAAO,MAAM,aAAa,yBAwBS,CAAC;AAEpC,eAAO,MAAM,eAAe;;;CAGlB,CAAC"}
export declare const lruMemoizerConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
functionName: string;
kind: "Callback";
};
}[];
export declare const lruMemoizerChannels: {
readonly LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load";
};
//# sourceMappingURL=lru-memoizer.d.ts.map
{"version":3,"file":"lru-memoizer.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/lru-memoizer.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAOK,CAAC;AAEpC,eAAO,MAAM,mBAAmB;;CAEtB,CAAC"}
export declare const mysqlConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
expressionName: string;
kind: "Auto";
};
}[];
export declare const mysqlChannels: {
readonly MYSQL_QUERY: "orchestrion:mysql:query";
};
//# sourceMappingURL=mysql.d.ts.map
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/mysql.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW;;;;;;;;;;;GAMW,CAAC;AAEpC,eAAO,MAAM,aAAa;;CAEhB,CAAC"}
export declare const openaiConfig: {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Auto";
};
}[];
export declare const openaiChannels: {
readonly OPENAI_CHAT: "orchestrion:openai:chat";
readonly OPENAI_RESPONSES: "orchestrion:openai:responses";
readonly OPENAI_EMBEDDINGS: "orchestrion:openai:embeddings";
readonly OPENAI_CONVERSATIONS: "orchestrion:openai:conversations";
};
//# sourceMappingURL=openai.d.ts.map
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/openai.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;;;;;;;;;GA2BU,CAAC;AAEpC,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC"}
export declare const pgConfig: ({
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
className: string;
methodName: string;
kind: "Auto";
expressionName?: undefined;
};
} | {
channelName: string;
module: {
name: string;
versionRange: string;
filePath: string;
};
functionQuery: {
expressionName: string;
kind: "Auto";
className?: undefined;
methodName?: undefined;
};
})[];
export declare const pgChannels: {
readonly PG_QUERY: "orchestrion:pg:query";
readonly PG_CONNECT: "orchestrion:pg:connect";
readonly PGPOOL_CONNECT: "orchestrion:pg-pool:connect";
};
//# sourceMappingURL=pg.d.ts.map
{"version":3,"file":"pg.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/pg.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;IAuCc,CAAC;AAEpC,eAAO,MAAM,UAAU;;;;CAIb,CAAC"}
import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';
export declare const vercelAiConfig: InstrumentationConfig[];
export declare const vercelAiChannels: {
readonly VERCEL_AI_GENERATE_TEXT: "orchestrion:ai:generateText";
readonly VERCEL_AI_STREAM_TEXT: "orchestrion:ai:streamText";
readonly VERCEL_AI_EMBED: "orchestrion:ai:embed";
readonly VERCEL_AI_EMBED_MANY: "orchestrion:ai:embedMany";
readonly VERCEL_AI_EXECUTE_TOOL_CALL: "orchestrion:ai:executeToolCall";
readonly VERCEL_AI_RESOLVE_LANGUAGE_MODEL: "orchestrion:ai:resolveLanguageModel";
};
//# sourceMappingURL=vercel-ai.d.ts.map
{"version":3,"file":"vercel-ai.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/config/vercel-ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,eAAO,MAAM,cAAc,yBAeQ,CAAC;AAEpC,eAAO,MAAM,gBAAgB;;;;;;;CAcnB,CAAC"}
/**
* Given the redis command name and arguments, return a combination of the
* command name + the allowed arguments according to `serializationSubsets`.
*/
export declare const defaultDbStatementSerializer: (cmdName: string, cmdArgs: Array<string | Buffer | number | unknown[]>) => string;
//# sourceMappingURL=redis-statement-serializer.d.ts.map
{"version":3,"file":"redis-statement-serializer.d.ts","sourceRoot":"","sources":["../../../src/redis/redis-statement-serializer.ts"],"names":[],"mappings":"AA0CA;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACvC,SAAS,MAAM,EACf,SAAS,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,CAAC,KACnD,MAWF,CAAC"}
import { type VercelAiChannelOptions, type VercelAiTracingChannelFactory } from './vercel-ai-dc-subscriber';
/**
* Subscribe the v6 orchestrion channel adapter. Safe to always call: inert on
* `ai` >= 7 (those channels are never published) and when orchestrion injection
* isn't active. Idempotent.
*
* `tracingChannel` is the platform-provided factory (the same one passed to
* `subscribeVercelAiTracingChannel`); `options` pins the recording settings at
* subscribe time so we never look the integration up per event.
*/
export declare function subscribeVercelAiOrchestrionChannels(tracingChannel: VercelAiTracingChannelFactory, options?: VercelAiChannelOptions): void;
//# sourceMappingURL=vercel-ai-orchestrion-v6-subscriber.d.ts.map
{"version":3,"file":"vercel-ai-orchestrion-v6-subscriber.d.ts","sourceRoot":"","sources":["../../../src/vercel-ai/vercel-ai-orchestrion-v6-subscriber.ts"],"names":[],"mappings":"AAKA,OAAO,EAML,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,EACnC,MAAM,2BAA2B,CAAC;AAyEnC;;;;;;;;GAQG;AACH,wBAAgB,oCAAoC,CAClD,cAAc,EAAE,6BAA6B,EAC7C,OAAO,GAAE,sBAA2B,GACnC,IAAI,CA6DN"}
+6
-2
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const index$1 = require('./mongoose/index.js');
const redisDcSubscriber = require('./redis/redis-dc-subscriber.js');
const redisStatementSerializer = require('./redis/redis-statement-serializer.js');
const tracingChannel = require('./tracing-channel.js');
const index$1 = require('./vercel-ai/index.js');
const index$2 = require('./vercel-ai/index.js');
const index = require('./integrations/tracing-channel/fastify/index.js');

@@ -10,2 +12,3 @@

exports.mongooseIntegration = index$1.mongooseIntegration;
exports.IOREDIS_DC_CHANNEL_COMMAND = redisDcSubscriber.IOREDIS_DC_CHANNEL_COMMAND;

@@ -17,4 +20,5 @@ exports.IOREDIS_DC_CHANNEL_CONNECT = redisDcSubscriber.IOREDIS_DC_CHANNEL_CONNECT;

exports.subscribeRedisDiagnosticChannels = redisDcSubscriber.subscribeRedisDiagnosticChannels;
exports.defaultDbStatementSerializer = redisStatementSerializer.defaultDbStatementSerializer;
exports.bindTracingChannelToSpan = tracingChannel.bindTracingChannelToSpan;
exports.vercelAiIntegration = index$1.vercelAiIntegration;
exports.vercelAiIntegration = index$2.vercelAiIntegration;
exports.fastifyIntegration = index.fastifyIntegration;

@@ -21,0 +25,0 @@ exports.handleFastifyError = index.handleFastifyError;

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}

@@ -36,2 +36,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

name: sql ?? "mysql.query",
kind: core.SPAN_KIND.CLIENT,
op: "db",

@@ -38,0 +39,0 @@ attributes: {

@@ -1,1 +0,1 @@

{"version":3,"file":"mysql.js","sources":["../../../../src/integrations/tracing-channel/mysql.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, Scope } from '@sentry/core';\nimport {\n bindScopeToEmitter,\n debug,\n defineIntegration,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// NOTE: this uses the same name as the OTel integration by design.\n// When enabled, OTel 'Mysql' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Mysql' as const;\n\n// OTel \"OLD\" db/net semantic-conventions, inlined to keep this integration free of OTel deps. Matches\n// `@opentelemetry/instrumentation-mysql`'s default and the SDK's `inferDbSpanData` (which renames spans\n// off `db.statement`).\nconst ATTR_DB_SYSTEM = 'db.system';\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nconst ATTR_DB_NAME = 'db.name';\nconst ATTR_DB_USER = 'db.user';\nconst ATTR_DB_STATEMENT = 'db.statement';\nconst ATTR_NET_PEER_NAME = 'net.peer.name';\nconst ATTR_NET_PEER_PORT = 'net.peer.port';\n\n/**\n * The shape orchestrion's transform attaches to the tracing-channel `context` object. Documented here\n * rather than imported because orchestrion's runtime doesn't export it.\n */\ninterface MysqlQueryChannelContext {\n // The live args array passed to the wrapped `connection.query` call; `arguments[0]` is the SQL.\n arguments: unknown[];\n self?: MysqlConnection;\n moduleVersion?: string;\n result?: unknown;\n error?: unknown;\n // The caller's scope, captured at `start` and replayed onto the streamed `Query` emitter (see below).\n _sentryCallerScope?: Scope;\n}\n\ninterface MysqlConnectionConfig {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n // Pool connections nest the real config one level deeper.\n connectionConfig?: MysqlConnectionConfig;\n}\n\ninterface MysqlConnection {\n config?: MysqlConnectionConfig;\n}\n\nconst _mysqlChannelIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19 so do nothing in that case.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`[orchestrion:mysql] subscribing to channel \"${CHANNELS.MYSQL_QUERY}\"`);\n\n waitForTracingChannelBinding(() => {\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<MysqlQueryChannelContext>(CHANNELS.MYSQL_QUERY),\n data => {\n const sql = extractSql(data.arguments[0]);\n const { host, port, database, user } = getConnectionConfig(data.self);\n const portNumber = typeof port === 'string' ? parseInt(port, 10) : port;\n const portIsNumber = typeof portNumber === 'number' && !isNaN(portNumber);\n\n // For the streamed path: mysql emits the `Query` emitter's events from its socket data\n // handler with the caller's context lost. `deferSpanEnd` replays this scope onto the emitter.\n data._sentryCallerScope = getCurrentScope();\n\n return startInactiveSpan({\n name: sql ?? 'mysql.query',\n op: 'db',\n attributes: {\n [ATTR_DB_SYSTEM]: 'mysql',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.orchestrion.mysql',\n [ATTR_DB_CONNECTION_STRING]: getJDBCString(host, portIsNumber ? portNumber : undefined, database),\n ...(database ? { [ATTR_DB_NAME]: database } : {}),\n ...(user ? { [ATTR_DB_USER]: user } : {}),\n ...(sql ? { [ATTR_DB_STATEMENT]: sql } : {}),\n ...(host ? { [ATTR_NET_PEER_NAME]: host } : {}),\n ...(portIsNumber ? { [ATTR_NET_PEER_PORT]: portNumber } : {}),\n },\n });\n },\n {\n // No-callback `query(sql)` returns a streamable `Query` emitter as `result`; it settles on the\n // emitter's `'end'`/`'error'`, not the channel, so defer ending to those.\n deferSpanEnd({ data, end }) {\n const result = data.result;\n if (!result || typeof result !== 'object' || !hasOnMethod(result)) {\n return false;\n }\n\n // Replay the caller's scope so user listeners on the emitter nest under it, not a new trace.\n const callerScope = data._sentryCallerScope;\n if (callerScope) {\n bindScopeToEmitter(result, callerScope);\n }\n\n result.on('error', err => end(err));\n result.on('end', () => end());\n\n return true;\n },\n },\n );\n });\n },\n };\n}) satisfies IntegrationFn;\n\nfunction hasOnMethod(obj: object): obj is { on: (event: string, listener: (arg?: unknown) => void) => unknown } {\n return 'on' in obj && typeof (obj as { on?: unknown }).on === 'function';\n}\n\nfunction extractSql(firstArg: unknown): string | undefined {\n if (typeof firstArg === 'string') {\n return firstArg;\n }\n if (firstArg && typeof firstArg === 'object' && 'sql' in firstArg) {\n const sql = (firstArg as { sql?: unknown }).sql;\n return typeof sql === 'string' ? sql : undefined;\n }\n return undefined;\n}\n\nfunction getConnectionConfig(connection: MysqlConnection | undefined): {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n} {\n // Pool connections nest the real config under `.connectionConfig`; single\n // connections expose it directly. Matches `@opentelemetry/instrumentation-mysql`.\n const config = connection?.config?.connectionConfig ?? connection?.config ?? {};\n return {\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n };\n}\n\nfunction getJDBCString(host: string | undefined, port: number | undefined, database: string | undefined): string {\n let s = `jdbc:mysql://${host || 'localhost'}`;\n if (typeof port === 'number') {\n s += `:${port}`;\n }\n if (database) {\n s += `/${database}`;\n }\n return s;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven mysql integration.\n *\n * Subscribes to the `orchestrion:mysql:query` diagnostics_channel that the\n * orchestrion code transform injects into `mysql/lib/Connection.js`'s\n * `Connection.prototype.query`. Requires the orchestrion runtime hook or\n * bundler plugin to be active — wire that up via `_experimentalSetupOrchestrion`.\n */\nexport const mysqlChannelIntegration = defineIntegration(_mysqlChannelIntegration);\n"],"names":["DEBUG_BUILD","debug","CHANNELS","waitForTracingChannelBinding","bindTracingChannelToSpan","getCurrentScope","startInactiveSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","bindScopeToEmitter","defineIntegration"],"mappings":"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"}
{"version":3,"file":"mysql.js","sources":["../../../../src/integrations/tracing-channel/mysql.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, Scope } from '@sentry/core';\nimport {\n bindScopeToEmitter,\n debug,\n defineIntegration,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// NOTE: this uses the same name as the OTel integration by design.\n// When enabled, OTel 'Mysql' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Mysql' as const;\n\n// OTel \"OLD\" db/net semantic-conventions, inlined to keep this integration free of OTel deps. Matches\n// `@opentelemetry/instrumentation-mysql`'s default and the SDK's `inferDbSpanData` (which renames spans\n// off `db.statement`).\nconst ATTR_DB_SYSTEM = 'db.system';\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nconst ATTR_DB_NAME = 'db.name';\nconst ATTR_DB_USER = 'db.user';\nconst ATTR_DB_STATEMENT = 'db.statement';\nconst ATTR_NET_PEER_NAME = 'net.peer.name';\nconst ATTR_NET_PEER_PORT = 'net.peer.port';\n\n/**\n * The shape orchestrion's transform attaches to the tracing-channel `context` object. Documented here\n * rather than imported because orchestrion's runtime doesn't export it.\n */\ninterface MysqlQueryChannelContext {\n // The live args array passed to the wrapped `connection.query` call; `arguments[0]` is the SQL.\n arguments: unknown[];\n self?: MysqlConnection;\n moduleVersion?: string;\n result?: unknown;\n error?: unknown;\n // The caller's scope, captured at `start` and replayed onto the streamed `Query` emitter (see below).\n _sentryCallerScope?: Scope;\n}\n\ninterface MysqlConnectionConfig {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n // Pool connections nest the real config one level deeper.\n connectionConfig?: MysqlConnectionConfig;\n}\n\ninterface MysqlConnection {\n config?: MysqlConnectionConfig;\n}\n\nconst _mysqlChannelIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19 so do nothing in that case.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`[orchestrion:mysql] subscribing to channel \"${CHANNELS.MYSQL_QUERY}\"`);\n\n waitForTracingChannelBinding(() => {\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<MysqlQueryChannelContext>(CHANNELS.MYSQL_QUERY),\n data => {\n const sql = extractSql(data.arguments[0]);\n const { host, port, database, user } = getConnectionConfig(data.self);\n const portNumber = typeof port === 'string' ? parseInt(port, 10) : port;\n const portIsNumber = typeof portNumber === 'number' && !isNaN(portNumber);\n\n // For the streamed path: mysql emits the `Query` emitter's events from its socket data\n // handler with the caller's context lost. `deferSpanEnd` replays this scope onto the emitter.\n data._sentryCallerScope = getCurrentScope();\n\n return startInactiveSpan({\n name: sql ?? 'mysql.query',\n kind: SPAN_KIND.CLIENT,\n op: 'db',\n attributes: {\n [ATTR_DB_SYSTEM]: 'mysql',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.orchestrion.mysql',\n [ATTR_DB_CONNECTION_STRING]: getJDBCString(host, portIsNumber ? portNumber : undefined, database),\n ...(database ? { [ATTR_DB_NAME]: database } : {}),\n ...(user ? { [ATTR_DB_USER]: user } : {}),\n ...(sql ? { [ATTR_DB_STATEMENT]: sql } : {}),\n ...(host ? { [ATTR_NET_PEER_NAME]: host } : {}),\n ...(portIsNumber ? { [ATTR_NET_PEER_PORT]: portNumber } : {}),\n },\n });\n },\n {\n // No-callback `query(sql)` returns a streamable `Query` emitter as `result`; it settles on the\n // emitter's `'end'`/`'error'`, not the channel, so defer ending to those.\n deferSpanEnd({ data, end }) {\n const result = data.result;\n if (!result || typeof result !== 'object' || !hasOnMethod(result)) {\n return false;\n }\n\n // Replay the caller's scope so user listeners on the emitter nest under it, not a new trace.\n const callerScope = data._sentryCallerScope;\n if (callerScope) {\n bindScopeToEmitter(result, callerScope);\n }\n\n result.on('error', err => end(err));\n result.on('end', () => end());\n\n return true;\n },\n },\n );\n });\n },\n };\n}) satisfies IntegrationFn;\n\nfunction hasOnMethod(obj: object): obj is { on: (event: string, listener: (arg?: unknown) => void) => unknown } {\n return 'on' in obj && typeof (obj as { on?: unknown }).on === 'function';\n}\n\nfunction extractSql(firstArg: unknown): string | undefined {\n if (typeof firstArg === 'string') {\n return firstArg;\n }\n if (firstArg && typeof firstArg === 'object' && 'sql' in firstArg) {\n const sql = (firstArg as { sql?: unknown }).sql;\n return typeof sql === 'string' ? sql : undefined;\n }\n return undefined;\n}\n\nfunction getConnectionConfig(connection: MysqlConnection | undefined): {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n} {\n // Pool connections nest the real config under `.connectionConfig`; single\n // connections expose it directly. Matches `@opentelemetry/instrumentation-mysql`.\n const config = connection?.config?.connectionConfig ?? connection?.config ?? {};\n return {\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n };\n}\n\nfunction getJDBCString(host: string | undefined, port: number | undefined, database: string | undefined): string {\n let s = `jdbc:mysql://${host || 'localhost'}`;\n if (typeof port === 'number') {\n s += `:${port}`;\n }\n if (database) {\n s += `/${database}`;\n }\n return s;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven mysql integration.\n *\n * Subscribes to the `orchestrion:mysql:query` diagnostics_channel that the\n * orchestrion code transform injects into `mysql/lib/Connection.js`'s\n * `Connection.prototype.query`. Requires the orchestrion runtime hook or\n * bundler plugin to be active — wire that up via `_experimentalSetupOrchestrion`.\n */\nexport const mysqlChannelIntegration = defineIntegration(_mysqlChannelIntegration);\n"],"names":["DEBUG_BUILD","debug","CHANNELS","waitForTracingChannelBinding","bindTracingChannelToSpan","getCurrentScope","startInactiveSpan","SPAN_KIND","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","bindScopeToEmitter","defineIntegration"],"mappings":"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"}

@@ -5,6 +5,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const MagicString = require('magic-string');
const config = require('../config.js');
const index = require('../config/index.js');
function sentryOrchestrionPlugin() {
const codeTransformerPlugins = codeTransformer.default({ instrumentations: config.SENTRY_INSTRUMENTATIONS });
const codeTransformerPlugins = codeTransformer.default({ instrumentations: index.SENTRY_INSTRUMENTATIONS });
const codeTransformerArray = Array.isArray(codeTransformerPlugins) ? codeTransformerPlugins : [codeTransformerPlugins];

@@ -23,3 +23,3 @@ return [bundlerMarkerPlugin(), ...codeTransformerArray];

config() {
return { ssr: { noExternal: config.INSTRUMENTED_MODULE_NAMES } };
return { ssr: { noExternal: index.INSTRUMENTED_MODULE_NAMES } };
},

@@ -26,0 +26,0 @@ renderChunk(code, chunk) {

@@ -1,1 +0,1 @@

{"version":3,"file":"vite.js","sources":["../../../../src/orchestrion/bundler/vite.ts"],"sourcesContent":["// EXPERIMENTAL — Vite plugin that runs the orchestrion code transform at build\n// time, injecting `diagnostics_channel.tracingChannel` calls into the libraries\n// listed in `SENTRY_INSTRUMENTATIONS`.\n//\n// This file is published ESM-only via the `@sentry/server-utils/orchestrion/vite`\n// subpath export. `@apm-js-collab/code-transformer-bundler-plugins` is\n// `\"type\": \"module\"`, so consuming it from a CJS build is intentionally\n// unsupported — vite.config.ts is almost always ESM in practice. The CJS\n// rollup variant still emits this file, but `package.json` only exposes the\n// ESM entry, so attempts to `require('@sentry/server-utils/orchestrion/vite')` will\n// fail at resolution time rather than producing a half-broken plugin.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype UnknownPlugin = any;\n\nimport codeTransformer from '@apm-js-collab/code-transformer-bundler-plugins/vite';\nimport MagicString from 'magic-string';\nimport { INSTRUMENTED_MODULE_NAMES, SENTRY_INSTRUMENTATIONS } from '../config';\n\n// `vite` types live in the package's ESM-only subpath; under Node16 module\n// resolution with TS treating @sentry/server-utils as CJS, importing them produces a\n// false positive. We don't need the runtime value for typing — `UnknownPlugin`\n// is sufficient — so we omit the import entirely.\n\n/**\n * Vite plugin that runs the orchestrion code transform on the bundled output.\n *\n * Use when bundling a Node app with Vite (e.g. Vite SSR builds, Nuxt's Nitro\n * pipeline, SvelteKit). For unbundled Node processes use the runtime hook\n * instead (`node --import @sentry/node/orchestrion app.js`).\n *\n * Returns two plugins:\n * 1. `sentry-orchestrion-marker` — a `renderChunk` hook that prepends a\n * single-line banner to entry chunks. The banner sets\n * `globalThis.__SENTRY_ORCHESTRION__.bundler = true` at app boot, so the\n * `_experimentalSetupOrchestrion()` detector can confirm the bundler path\n * ran (rather than relying on a build-time flag that wouldn't be visible\n * to the runtime).\n * Also injects every instrumented package name into `ssr.noExternal` via\n * the `config` hook, since externalized deps are `require()`d at runtime\n * from `node_modules` and never pass through the transform.\n * 2. The upstream `@apm-js-collab/code-transformer-bundler-plugins/vite`\n * plugin, fed our central `SENTRY_INSTRUMENTATIONS` config.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { sentryOrchestrionPlugin } from '@sentry/node/orchestrion/vite';\n * export default { plugins: [sentryOrchestrionPlugin()] };\n * ```\n */\nexport function sentryOrchestrionPlugin(): UnknownPlugin[] {\n const codeTransformerPlugins = codeTransformer({ instrumentations: SENTRY_INSTRUMENTATIONS });\n const codeTransformerArray: UnknownPlugin[] = Array.isArray(codeTransformerPlugins)\n ? codeTransformerPlugins\n : [codeTransformerPlugins];\n return [bundlerMarkerPlugin(), ...codeTransformerArray];\n}\n\nfunction bundlerMarkerPlugin(): UnknownPlugin {\n const banner = [\n 'globalThis.__SENTRY_ORCHESTRION__ = (globalThis.__SENTRY_ORCHESTRION__ || {});',\n 'globalThis.__SENTRY_ORCHESTRION__.bundler = true;',\n '',\n ].join('\\n');\n\n return {\n name: 'sentry-orchestrion-marker',\n enforce: 'pre' as const,\n config(): { ssr: { noExternal: string[] } } {\n // Force-bundle every instrumented package so the code transform actually\n // sees its source. Vite externalizes dependencies in SSR builds by\n // default, leaving them as bare `require()`/`import` calls resolved from\n // `node_modules` at runtime — those copies are untouched and the\n // diagnostics_channel calls never get injected. Vite merges array\n // `noExternal` entries with the user's config, so we don't overwrite\n // their additions.\n return { ssr: { noExternal: INSTRUMENTED_MODULE_NAMES } };\n },\n renderChunk(code: string, chunk: { isEntry: boolean }): { code: string; map: unknown } | null {\n if (!chunk.isEntry) return null;\n // Prepend via magic-string so the entry chunk's sourcemap stays aligned —\n // returning `map: null` here would shift every mapping by the banner's\n // line count and misattribute server stack traces.\n const ms = new MagicString(code);\n ms.prepend(banner);\n return { code: ms.toString(), map: ms.generateMap({ hires: true }) };\n },\n };\n}\n"],"names":["codeTransformer","SENTRY_INSTRUMENTATIONS","INSTRUMENTED_MODULE_NAMES","MagicString"],"mappings":";;;;;;AAmDO,SAAS,uBAAA,GAA2C;AACzD,EAAA,MAAM,sBAAA,GAAyBA,uBAAA,CAAgB,EAAE,gBAAA,EAAkBC,gCAAyB,CAAA;AAC5F,EAAA,MAAM,uBAAwC,KAAA,CAAM,OAAA,CAAQ,sBAAsB,CAAA,GAC9E,sBAAA,GACA,CAAC,sBAAsB,CAAA;AAC3B,EAAA,OAAO,CAAC,mBAAA,EAAoB,EAAG,GAAG,oBAAoB,CAAA;AACxD;AAEA,SAAS,mBAAA,GAAqC;AAC5C,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,gFAAA;AAAA,IACA,mDAAA;AAAA,IACA;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AAEX,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,2BAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,MAAA,GAA4C;AAQ1C,MAAA,OAAO,EAAE,GAAA,EAAK,EAAE,UAAA,EAAYC,kCAA0B,EAAE;AAAA,IAC1D,CAAA;AAAA,IACA,WAAA,CAAY,MAAc,KAAA,EAAoE;AAC5F,MAAA,IAAI,CAAC,KAAA,CAAM,OAAA,EAAS,OAAO,IAAA;AAI3B,MAAA,MAAM,EAAA,GAAK,IAAIC,mBAAA,CAAY,IAAI,CAAA;AAC/B,MAAA,EAAA,CAAG,QAAQ,MAAM,CAAA;AACjB,MAAA,OAAO,EAAE,IAAA,EAAM,EAAA,CAAG,QAAA,EAAS,EAAG,GAAA,EAAK,EAAA,CAAG,WAAA,CAAY,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA,EAAE;AAAA,IACrE;AAAA,GACF;AACF;;;;"}
{"version":3,"file":"vite.js","sources":["../../../../src/orchestrion/bundler/vite.ts"],"sourcesContent":["// EXPERIMENTAL — Vite plugin that runs the orchestrion code transform at build\n// time, injecting `diagnostics_channel.tracingChannel` calls into the libraries\n// listed in `SENTRY_INSTRUMENTATIONS`.\n//\n// This file is published ESM-only via the `@sentry/server-utils/orchestrion/vite`\n// subpath export. `@apm-js-collab/code-transformer-bundler-plugins` is\n// `\"type\": \"module\"`, so consuming it from a CJS build is intentionally\n// unsupported — vite.config.ts is almost always ESM in practice. The CJS\n// rollup variant still emits this file, but `package.json` only exposes the\n// ESM entry, so attempts to `require('@sentry/server-utils/orchestrion/vite')` will\n// fail at resolution time rather than producing a half-broken plugin.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype UnknownPlugin = any;\n\nimport codeTransformer from '@apm-js-collab/code-transformer-bundler-plugins/vite';\nimport MagicString from 'magic-string';\nimport { INSTRUMENTED_MODULE_NAMES, SENTRY_INSTRUMENTATIONS } from '../config';\n\n// `vite` types live in the package's ESM-only subpath; under Node16 module\n// resolution with TS treating @sentry/server-utils as CJS, importing them produces a\n// false positive. We don't need the runtime value for typing — `UnknownPlugin`\n// is sufficient — so we omit the import entirely.\n\n/**\n * Vite plugin that runs the orchestrion code transform on the bundled output.\n *\n * Use when bundling a Node app with Vite (e.g. Vite SSR builds, Nuxt's Nitro\n * pipeline, SvelteKit). For unbundled Node processes use the runtime hook\n * instead (`node --import @sentry/node/orchestrion app.js`).\n *\n * Returns two plugins:\n * 1. `sentry-orchestrion-marker` — a `renderChunk` hook that prepends a\n * single-line banner to entry chunks. The banner sets\n * `globalThis.__SENTRY_ORCHESTRION__.bundler = true` at app boot, so the\n * `_experimentalSetupOrchestrion()` detector can confirm the bundler path\n * ran (rather than relying on a build-time flag that wouldn't be visible\n * to the runtime).\n * Also injects every instrumented package name into `ssr.noExternal` via\n * the `config` hook, since externalized deps are `require()`d at runtime\n * from `node_modules` and never pass through the transform.\n * 2. The upstream `@apm-js-collab/code-transformer-bundler-plugins/vite`\n * plugin, fed our central `SENTRY_INSTRUMENTATIONS` config.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { sentryOrchestrionPlugin } from '@sentry/node/orchestrion/vite';\n * export default { plugins: [sentryOrchestrionPlugin()] };\n * ```\n */\nexport function sentryOrchestrionPlugin(): UnknownPlugin[] {\n const codeTransformerPlugins = codeTransformer({ instrumentations: SENTRY_INSTRUMENTATIONS });\n const codeTransformerArray: UnknownPlugin[] = Array.isArray(codeTransformerPlugins)\n ? codeTransformerPlugins\n : [codeTransformerPlugins];\n return [bundlerMarkerPlugin(), ...codeTransformerArray];\n}\n\nfunction bundlerMarkerPlugin(): UnknownPlugin {\n const banner = [\n 'globalThis.__SENTRY_ORCHESTRION__ = (globalThis.__SENTRY_ORCHESTRION__ || {});',\n 'globalThis.__SENTRY_ORCHESTRION__.bundler = true;',\n '',\n ].join('\\n');\n\n return {\n name: 'sentry-orchestrion-marker',\n enforce: 'pre' as const,\n config(): { ssr: { noExternal: string[] } } {\n // Force-bundle every instrumented package so the code transform actually\n // sees its source. Vite externalizes dependencies in SSR builds by\n // default, leaving them as bare `require()`/`import` calls resolved from\n // `node_modules` at runtime — those copies are untouched and the\n // diagnostics_channel calls never get injected. Vite merges array\n // `noExternal` entries with the user's config, so we don't overwrite\n // their additions.\n return { ssr: { noExternal: INSTRUMENTED_MODULE_NAMES } };\n },\n renderChunk(code: string, chunk: { isEntry: boolean }): { code: string; map: unknown } | null {\n if (!chunk.isEntry) return null;\n // Prepend via magic-string so the entry chunk's sourcemap stays aligned —\n // returning `map: null` here would shift every mapping by the banner's\n // line count and misattribute server stack traces.\n const ms = new MagicString(code);\n ms.prepend(banner);\n return { code: ms.toString(), map: ms.generateMap({ hires: true }) };\n },\n };\n}\n"],"names":["codeTransformer","SENTRY_INSTRUMENTATIONS","INSTRUMENTED_MODULE_NAMES","MagicString"],"mappings":";;;;;;AAmDO,SAAS,uBAAA,GAA2C;AACzD,EAAA,MAAM,sBAAA,GAAyBA,uBAAA,CAAgB,EAAE,gBAAA,EAAkBC,+BAAyB,CAAA;AAC5F,EAAA,MAAM,uBAAwC,KAAA,CAAM,OAAA,CAAQ,sBAAsB,CAAA,GAC9E,sBAAA,GACA,CAAC,sBAAsB,CAAA;AAC3B,EAAA,OAAO,CAAC,mBAAA,EAAoB,EAAG,GAAG,oBAAoB,CAAA;AACxD;AAEA,SAAS,mBAAA,GAAqC;AAC5C,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,gFAAA;AAAA,IACA,mDAAA;AAAA,IACA;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AAEX,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,2BAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,MAAA,GAA4C;AAQ1C,MAAA,OAAO,EAAE,GAAA,EAAK,EAAE,UAAA,EAAYC,iCAA0B,EAAE;AAAA,IAC1D,CAAA;AAAA,IACA,WAAA,CAAY,MAAc,KAAA,EAAoE;AAC5F,MAAA,IAAI,CAAC,KAAA,CAAM,OAAA,EAAS,OAAO,IAAA;AAI3B,MAAA,MAAM,EAAA,GAAK,IAAIC,mBAAA,CAAY,IAAI,CAAA;AAC/B,MAAA,EAAA,CAAG,QAAQ,MAAM,CAAA;AACjB,MAAA,OAAO,EAAE,IAAA,EAAM,EAAA,CAAG,QAAA,EAAS,EAAG,GAAA,EAAK,EAAA,CAAG,WAAA,CAAY,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA,EAAE;AAAA,IACrE;AAAA,GACF;AACF;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const mysql = require('./config/mysql.js');
const lruMemoizer = require('./config/lru-memoizer.js');
const ioredis = require('./config/ioredis.js');
const pg = require('./config/pg.js');
const openai = require('./config/openai.js');
const anthropicAi = require('./config/anthropic-ai.js');
const vercelAi = require('./config/vercel-ai.js');
const hapi = require('./config/hapi.js');
const CHANNELS = {
MYSQL_QUERY: "orchestrion:mysql:query",
LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load"
...mysql.mysqlChannels,
...lruMemoizer.lruMemoizerChannels,
...ioredis.ioredisChannels,
...pg.pgChannels,
...openai.openaiChannels,
...anthropicAi.anthropicAiChannels,
...vercelAi.vercelAiChannels,
...hapi.hapiChannels
};

@@ -7,0 +22,0 @@

@@ -1,1 +0,1 @@

{"version":3,"file":"channels.js","sources":["../../../src/orchestrion/channels.ts"],"sourcesContent":["/**\n * Fully-qualified `diagnostics_channel` names that orchestrion publishes to.\n *\n * Orchestrion's transform always prefixes the configured `channelName` with\n * `orchestrion:${module.name}:`. So a config of\n * `{ channelName: 'query', module: { name: 'mysql' } }`\n * publishes to `orchestrion:mysql:query`.\n *\n * Subscribers (`integrations/<lib>/tracing-channel.ts`) consume the full\n * prefixed string from this map; the config files set only the unprefixed\n * suffix in `channelName`. Keeping both pieces in one file is what guarantees\n * they don't drift apart and silently stop firing.\n */\nexport const CHANNELS = {\n MYSQL_QUERY: 'orchestrion:mysql:query',\n LRU_MEMOIZER_LOAD: 'orchestrion:lru-memoizer:load',\n} as const;\n\nexport type ChannelName = (typeof CHANNELS)[keyof typeof CHANNELS];\n"],"names":[],"mappings":";;AAaO,MAAM,QAAA,GAAW;AAAA,EACtB,WAAA,EAAa,yBAAA;AAAA,EACb,iBAAA,EAAmB;AACrB;;;;"}
{"version":3,"file":"channels.js","sources":["../../../src/orchestrion/channels.ts"],"sourcesContent":["import { mysqlChannels } from './config/mysql';\nimport { lruMemoizerChannels } from './config/lru-memoizer';\nimport { ioredisChannels } from './config/ioredis';\nimport { pgChannels } from './config/pg';\nimport { openaiChannels } from './config/openai';\nimport { anthropicAiChannels } from './config/anthropic-ai';\nimport { vercelAiChannels } from './config/vercel-ai';\nimport { hapiChannels } from './config/hapi';\n\n/**\n * Fully-qualified `diagnostics_channel` names that orchestrion publishes to.\n *\n * Orchestrion's transform always prefixes the configured `channelName` with\n * `orchestrion:${module.name}:`. So a config of\n * `{ channelName: 'query', module: { name: 'mysql' } }`\n * publishes to `orchestrion:mysql:query`.\n *\n * Subscribers (`integrations/<lib>/tracing-channel.ts`) consume the full\n * prefixed string from this map; the config files set only the unprefixed\n * suffix in `channelName`. Keeping both pieces in one file is what guarantees\n * they don't drift apart and silently stop firing.\n */\nexport const CHANNELS = {\n ...mysqlChannels,\n ...lruMemoizerChannels,\n ...ioredisChannels,\n ...pgChannels,\n ...openaiChannels,\n ...anthropicAiChannels,\n ...vercelAiChannels,\n ...hapiChannels,\n} as const;\n\nexport type ChannelName = (typeof CHANNELS)[keyof typeof CHANNELS];\n"],"names":["mysqlChannels","lruMemoizerChannels","ioredisChannels","pgChannels","openaiChannels","anthropicAiChannels","vercelAiChannels","hapiChannels"],"mappings":";;;;;;;;;;;AAsBO,MAAM,QAAA,GAAW;AAAA,EACtB,GAAGA,mBAAA;AAAA,EACH,GAAGC,+BAAA;AAAA,EACH,GAAGC,uBAAA;AAAA,EACH,GAAGC,aAAA;AAAA,EACH,GAAGC,qBAAA;AAAA,EACH,GAAGC,+BAAA;AAAA,EACH,GAAGC,yBAAA;AAAA,EACH,GAAGC;AACL;;;;"}

@@ -6,2 +6,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

function isOrchestrionInjected() {
const marker = globalThis.__SENTRY_ORCHESTRION__;
return !!(marker?.runtime || marker?.bundler);
}
function detectOrchestrionSetup() {

@@ -13,3 +17,3 @@ if (!debugBuild.DEBUG_BUILD) return;

debugBuild.DEBUG_BUILD && core.debug.log(`[orchestrion] detect: runtime=${runtime} bundler=${bundler}`);
if (!runtime && !bundler) {
if (!isOrchestrionInjected()) {
debugBuild.DEBUG_BUILD && core.debug.warn(

@@ -22,2 +26,3 @@ "[Sentry] No diagnostics-channel injection detected. Channel-based integrations (mysql, \u2026) will not record spans. Make sure the diagnostics channels are injected via the runtime `--import` hook or a bundler plugin before the instrumented modules load."

exports.detectOrchestrionSetup = detectOrchestrionSetup;
exports.isOrchestrionInjected = isOrchestrionInjected;
//# sourceMappingURL=detect.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"detect.js","sources":["../../../src/orchestrion/detect.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Verifies that the diagnostics channels have been injected either by the\n * runtime `--import` hook (or init-time registration), a bundler plugin, or\n * both, and warns if not.\n *\n * Both injectors being active at once is fine: they operate on disjoint module\n * sets (a module is either loaded through Node's loader and transformed by the\n * runtime hook, or inlined by the bundler and transformed by the plugin), so\n * a single module can't be double-wrapped. A hybrid setup, with some deps\n * external and runtime-instrumented, others bundled and plugin-instrumented,\n * is fine.\n *\n * Note: intentionally does NOT warn in production, only in debug builds,\n * because production warnings are reserved for truly critical issues.\n */\nexport function detectOrchestrionSetup(): void {\n if (!DEBUG_BUILD) return;\n\n const marker = globalThis.__SENTRY_ORCHESTRION__;\n const runtime = !!marker?.runtime;\n const bundler = !!marker?.bundler;\n\n DEBUG_BUILD && debug.log(`[orchestrion] detect: runtime=${runtime} bundler=${bundler}`);\n\n if (!runtime && !bundler) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] No diagnostics-channel injection detected. Channel-based integrations ' +\n '(mysql, …) will not record spans. Make sure the diagnostics channels are injected ' +\n 'via the runtime `--import` hook or a bundler plugin before the instrumented modules load.',\n );\n }\n}\n"],"names":["DEBUG_BUILD","debug"],"mappings":";;;;;AAuBO,SAAS,sBAAA,GAA+B;AAC7C,EAAA,IAAI,CAACA,sBAAA,EAAa;AAElB,EAAA,MAAM,SAAS,UAAA,CAAW,sBAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAE1B,EAAAA,sBAAA,IAAeC,WAAM,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAEtF,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,EAAS;AACxB,IAAAD,sBAAA,IACEC,UAAA,CAAM,IAAA;AAAA,MACJ;AAAA,KAGF;AAAA,EACJ;AACF;;;;"}
{"version":3,"file":"detect.js","sources":["../../../src/orchestrion/detect.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Whether orchestrion has injected the diagnostics channels into this process,\n * either by the runtime `--import` hook / init-time registration (`runtime`)\n * or a bundler plugin (`bundler`). Both injectors set a flag on the\n * `globalThis.__SENTRY_ORCHESTRION__` marker.\n *\n * Use this to avoid wiring up channel-subscriber integrations when nothing\n * will ever publish to those channels.\n */\nexport function isOrchestrionInjected(): boolean {\n const marker = globalThis.__SENTRY_ORCHESTRION__;\n return !!(marker?.runtime || marker?.bundler);\n}\n\n/**\n * Verifies that the diagnostics channels have been injected either by the\n * runtime `--import` hook (or init-time registration), a bundler plugin, or\n * both, and warns if not.\n *\n * Both injectors being active at once is fine: they operate on disjoint module\n * sets (a module is either loaded through Node's loader and transformed by the\n * runtime hook, or inlined by the bundler and transformed by the plugin), so\n * a single module can't be double-wrapped. A hybrid setup, with some deps\n * external and runtime-instrumented, others bundled and plugin-instrumented,\n * is fine.\n *\n * Note: intentionally does NOT warn in production, only in debug builds,\n * because production warnings are reserved for truly critical issues.\n */\nexport function detectOrchestrionSetup(): void {\n if (!DEBUG_BUILD) return;\n\n const marker = globalThis.__SENTRY_ORCHESTRION__;\n const runtime = !!marker?.runtime;\n const bundler = !!marker?.bundler;\n\n DEBUG_BUILD && debug.log(`[orchestrion] detect: runtime=${runtime} bundler=${bundler}`);\n\n if (!isOrchestrionInjected()) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] No diagnostics-channel injection detected. Channel-based integrations ' +\n '(mysql, …) will not record spans. Make sure the diagnostics channels are injected ' +\n 'via the runtime `--import` hook or a bundler plugin before the instrumented modules load.',\n );\n }\n}\n"],"names":["DEBUG_BUILD","debug"],"mappings":";;;;;AAiBO,SAAS,qBAAA,GAAiC;AAC/C,EAAA,MAAM,SAAS,UAAA,CAAW,sBAAA;AAC1B,EAAA,OAAO,CAAC,EAAE,MAAA,EAAQ,OAAA,IAAW,MAAA,EAAQ,OAAA,CAAA;AACvC;AAiBO,SAAS,sBAAA,GAA+B;AAC7C,EAAA,IAAI,CAACA,sBAAA,EAAa;AAElB,EAAA,MAAM,SAAS,UAAA,CAAW,sBAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAE1B,EAAAA,sBAAA,IAAeC,WAAM,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAEtF,EAAA,IAAI,CAAC,uBAAsB,EAAG;AAC5B,IAAAD,sBAAA,IACEC,UAAA,CAAM,IAAA;AAAA,MACJ;AAAA,KAGF;AAAA,EACJ;AACF;;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const anthropic = require('../integrations/tracing-channel/anthropic.js');
const hapi = require('../integrations/tracing-channel/hapi.js');
const ioredis = require('../integrations/tracing-channel/ioredis.js');
const lruMemoizer = require('../integrations/tracing-channel/lru-memoizer.js');
const mysql = require('../integrations/tracing-channel/mysql.js');
const openai = require('../integrations/tracing-channel/openai.js');
const postgres = require('../integrations/tracing-channel/postgres.js');
const vercelAi = require('../integrations/tracing-channel/vercel-ai.js');
const detect = require('./detect.js');
const mysql = require('../integrations/tracing-channel/mysql.js');
const lruMemoizer = require('../integrations/tracing-channel/lru-memoizer.js');
const channelIntegrations = {
postgresIntegration: postgres.postgresChannelIntegration,
mysqlIntegration: mysql.mysqlChannelIntegration,
lruMemoizerIntegration: lruMemoizer.lruMemoizerChannelIntegration,
openaiIntegration: openai.openaiChannelIntegration,
anthropicIntegration: anthropic.anthropicChannelIntegration,
vercelAiIntegration: vercelAi.vercelAiChannelIntegration,
hapiIntegration: hapi.hapiChannelIntegration
};
exports.anthropicChannelIntegration = anthropic.anthropicChannelIntegration;
exports.hapiChannelIntegration = hapi.hapiChannelIntegration;
exports.ioredisChannelIntegration = ioredis.ioredisChannelIntegration;
exports.lruMemoizerChannelIntegration = lruMemoizer.lruMemoizerChannelIntegration;
exports.mysqlChannelIntegration = mysql.mysqlChannelIntegration;
exports.openaiChannelIntegration = openai.openaiChannelIntegration;
exports.postgresChannelIntegration = postgres.postgresChannelIntegration;
exports.vercelAiChannelIntegration = vercelAi.vercelAiChannelIntegration;
exports.detectOrchestrionSetup = detect.detectOrchestrionSetup;
exports.mysqlChannelIntegration = mysql.mysqlChannelIntegration;
exports.lruMemoizerChannelIntegration = lruMemoizer.lruMemoizerChannelIntegration;
exports.isOrchestrionInjected = detect.isOrchestrionInjected;
exports.channelIntegrations = channelIntegrations;
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
{"version":3,"file":"index.js","sources":["../../../src/orchestrion/index.ts"],"sourcesContent":["import { anthropicChannelIntegration } from '../integrations/tracing-channel/anthropic';\nimport { hapiChannelIntegration } from '../integrations/tracing-channel/hapi';\nimport { ioredisChannelIntegration } from '../integrations/tracing-channel/ioredis';\nimport { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer';\nimport { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql';\nimport { openaiChannelIntegration } from '../integrations/tracing-channel/openai';\nimport { postgresChannelIntegration } from '../integrations/tracing-channel/postgres';\nimport { vercelAiChannelIntegration } from '../integrations/tracing-channel/vercel-ai';\n\nexport { detectOrchestrionSetup, isOrchestrionInjected } from './detect';\nexport {\n anthropicChannelIntegration,\n hapiChannelIntegration,\n ioredisChannelIntegration,\n lruMemoizerChannelIntegration,\n mysqlChannelIntegration,\n openaiChannelIntegration,\n postgresChannelIntegration,\n vercelAiChannelIntegration,\n};\nexport type { IORedisChannelIntegrationOptions, IORedisResponseHook } from '../integrations/tracing-channel/ioredis';\n\n/**\n * The canonical set of orchestrion diagnostics-channel integrations, keyed by their public\n * (OTel-parity) factory name.\n *\n * Single source of truth: add a new channel integration here and every consumer — the `@sentry/node`\n * opt-in helper (`experimentalUseDiagnosticsChannelInjection`) and its public\n * `diagnosticsChannelInjectionIntegrations()` map — picks it up automatically, so there's no separate\n * list to keep in sync.\n *\n * NOTE: `ioredisChannelIntegration` is intentionally NOT here. It only partially replaces the\n * composite OTel `Redis` integration and needs the node SDK's redis cache `responseHook` (which\n * can't live in `server-utils`), so `@sentry/node` wires it up separately.\n */\nexport const channelIntegrations = {\n postgresIntegration: postgresChannelIntegration,\n mysqlIntegration: mysqlChannelIntegration,\n lruMemoizerIntegration: lruMemoizerChannelIntegration,\n openaiIntegration: openaiChannelIntegration,\n anthropicIntegration: anthropicChannelIntegration,\n vercelAiIntegration: vercelAiChannelIntegration,\n hapiIntegration: hapiChannelIntegration,\n} as const;\n"],"names":["postgresChannelIntegration","mysqlChannelIntegration","lruMemoizerChannelIntegration","openaiChannelIntegration","anthropicChannelIntegration","vercelAiChannelIntegration","hapiChannelIntegration"],"mappings":";;;;;;;;;;;;AAmCO,MAAM,mBAAA,GAAsB;AAAA,EACjC,mBAAA,EAAqBA,mCAAA;AAAA,EACrB,gBAAA,EAAkBC,6BAAA;AAAA,EAClB,sBAAA,EAAwBC,yCAAA;AAAA,EACxB,iBAAA,EAAmBC,+BAAA;AAAA,EACnB,oBAAA,EAAsBC,qCAAA;AAAA,EACtB,mBAAA,EAAqBC,mCAAA;AAAA,EACrB,eAAA,EAAiBC;AACnB;;;;;;;;;;;;;;"}

@@ -7,5 +7,4 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const debugBuild = require('../../debug-build.js');
const config = require('../config.js');
const index = require('../config/index.js');
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
function registerDiagnosticsChannelInjection() {

@@ -21,3 +20,4 @@ const g = globalThis.__SENTRY_ORCHESTRION__ ?? (globalThis.__SENTRY_ORCHESTRION__ = {});

const stableSyncHooks = (nodeVersion[0] ?? 0) > 25 || nodeVersion[0] === 25 && (nodeVersion[1] ?? 0) >= 1 || nodeVersion[0] === 24 && (nodeVersion[1] ?? 0) >= 13 || (denoVersion[0] ?? 0) > 2 || denoVersion[0] === 2 && (denoVersion[1] ?? 0) >= 8;
const nodeRequire = typeof require === "function" ? require : Module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('orchestrion/runtime/register.js', document.baseURI).href)));
let nodeRequire;
nodeRequire = require;
const mod = Module;

@@ -27,11 +27,14 @@ try {

const { initialize, resolve, load } = nodeRequire("@apm-js-collab/tracing-hooks/hook-sync.mjs");
initialize({ instrumentations: config.SENTRY_INSTRUMENTATIONS });
initialize({ instrumentations: index.SENTRY_INSTRUMENTATIONS });
mod.registerHooks({ resolve, load });
debugBuild.DEBUG_BUILD && core.debug.log("[orchestrion] registered diagnostics-channel injection via Module.registerHooks()");
} else if (typeof mod.register === "function" && !globalAny.Bun && !globalAny.Deno) {
mod.register(node_url.pathToFileURL(nodeRequire.resolve("@apm-js-collab/tracing-hooks/hook.mjs")).href, {
data: { instrumentations: config.SENTRY_INSTRUMENTATIONS }
let parentURL;
parentURL = node_url.pathToFileURL(__filename).href;
mod.register("@apm-js-collab/tracing-hooks/hook.mjs", {
parentURL,
data: { instrumentations: index.SENTRY_INSTRUMENTATIONS }
});
const ModulePatch = nodeRequire("@apm-js-collab/tracing-hooks");
new ModulePatch({ instrumentations: config.SENTRY_INSTRUMENTATIONS }).patch();
new ModulePatch({ instrumentations: index.SENTRY_INSTRUMENTATIONS }).patch();
debugBuild.DEBUG_BUILD && core.debug.log("[orchestrion] registered diagnostics-channel injection via Module.register()");

@@ -38,0 +41,0 @@ } else {

@@ -1,1 +0,1 @@

{"version":3,"file":"register.js","sources":["../../../../src/orchestrion/runtime/register.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { createRequire } from 'node:module';\nimport * as Module from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { SENTRY_INSTRUMENTATIONS } from '../config';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Synchronously register the diagnostics-channel injection module hooks.\n *\n * This is the single source of truth for the registration logic. It is used by:\n * - `Sentry.init()` (the Node SDK calls it directly — that's why this module\n * must be CJS-compatible / dual-built, so it can be `require()`d synchronously\n * before the app's `import`s resolve), and\n * - `import-hook.mjs`, the side-effecting `--import` entry, which just calls it.\n *\n * Libraries imported *after* this call publish the `tracingChannel` events that\n * the channel-based integrations subscribe to.\n *\n * Idempotent via `globalThis.__SENTRY_ORCHESTRION__` — a no-op if the runtime\n * `--import` hook or a bundler plugin already injected the channels.\n */\nexport function registerDiagnosticsChannelInjection(): void {\n const g = (globalThis.__SENTRY_ORCHESTRION__ ??= {});\n\n // Already injected (runtime --import hook or bundler plugin) — nothing to do.\n if (g.runtime || g.bundler) {\n return;\n }\n\n const globalAny = globalThis as { Bun?: unknown; Deno?: { version?: { deno?: string } } };\n const parseVersion = (v: string): number[] => v.split('.').map(n => parseInt(n, 10));\n const nodeVersion = parseVersion(process.versions.node ?? '0.0.0');\n const denoVersion = parseVersion(globalAny.Deno?.version?.deno ?? '0.0.0');\n // `Module.registerHooks` only became stable in Node 24.13 / 25.1 and Deno 2.8.\n const stableSyncHooks =\n (nodeVersion[0] ?? 0) > 25 ||\n (nodeVersion[0] === 25 && (nodeVersion[1] ?? 0) >= 1) ||\n (nodeVersion[0] === 24 && (nodeVersion[1] ?? 0) >= 13) ||\n (denoVersion[0] ?? 0) > 2 ||\n (denoVersion[0] === 2 && (denoVersion[1] ?? 0) >= 8);\n\n // Prefer the builtin `require` if possible. This is present in CommonJS,\n // including a bundler's CJS output, so no need to ever have to evaluate\n // `import.meta.url` there.\n //\n // esbuild and friends rewrite `import.meta.url` to `{}` for CJS output,\n // which would make `createRequire(undefined)` throw.\n // Only use `import.meta.url` in true ESM, where there's no `require`\n const nodeRequire = typeof require === 'function' ? require : createRequire(import.meta.url);\n\n // `Module.registerHooks` / `Module.register` are newer than the @types/node\n // we build against, hence the cast.\n const mod = Module as unknown as {\n registerHooks?: (hooks: unknown) => void;\n register?: (specifier: string, options: unknown) => void;\n };\n\n // runs both at `--import` time and (synchronously) inside `Sentry.init()`,\n // so an unguarded throw would either abort startup or make `init()` throw.\n // On any failure (e.g. dep resolution, `require(esm)` / Node-compat\n // incompatibility) we warn (DEBUG only) and continue without channel\n // injection\n try {\n if (typeof mod.registerHooks === 'function' && stableSyncHooks) {\n // Sync hooks cover CJS and ESM, no separate `_compile` patch needed.\n // We require() the module here so that we can synchronously load it,\n // including from a CommonJS Sentry build, without bundlers pulling in.\n // All versions in stableSyncHooks support this.\n const { initialize, resolve, load } = nodeRequire('@apm-js-collab/tracing-hooks/hook-sync.mjs') as {\n initialize: (opts: { instrumentations: unknown }) => void;\n resolve: unknown;\n load: unknown;\n };\n initialize({ instrumentations: SENTRY_INSTRUMENTATIONS });\n mod.registerHooks({ resolve, load });\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.registerHooks()');\n } else if (typeof mod.register === 'function' && !globalAny.Bun && !globalAny.Deno) {\n // `Module.register` + the `_compile` patch is Node 18.19–24.12 / 25.0\n // path. Bun/Deno are excluded: they don't support this combination and\n // must use the stable `registerHooks` path above (or none at all).\n // Resolve the hook to an absolute file URL ourselves so\n // `Module.register` needs no `parentURL`, so no need for\n // `import.meta.url` polyfilling\n mod.register(pathToFileURL(nodeRequire.resolve('@apm-js-collab/tracing-hooks/hook.mjs')).href, {\n data: { instrumentations: SENTRY_INSTRUMENTATIONS },\n });\n\n // ALSO patch `Module.prototype._compile` for the CJS side: when an ESM\n // file `import`s a CJS package, the package's internal `require()` calls\n // are resolved through the CJS machinery and never reach the ESM\n // register hook, so without this patch the file we want to instrument\n // loads untransformed.\n const ModulePatch = nodeRequire('@apm-js-collab/tracing-hooks') as new (opts: { instrumentations: unknown }) => {\n patch: () => void;\n };\n new ModulePatch({ instrumentations: SENTRY_INSTRUMENTATIONS }).patch();\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.register()');\n } else {\n DEBUG_BUILD &&\n debug.warn('[Sentry] No available Node API to register diagnostics-channel injection hooks; skipping.');\n return;\n }\n } catch (error) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] Failed to register diagnostics-channel injection hooks; channel-based integrations ' +\n 'will not record spans.',\n error,\n );\n return;\n }\n\n g.runtime = true;\n}\n"],"names":["createRequire","SENTRY_INSTRUMENTATIONS","DEBUG_BUILD","debug","pathToFileURL"],"mappings":";;;;;;;;;AA2BO,SAAS,mCAAA,GAA4C;AAC1D,EAAA,MAAM,CAAA,GAAK,UAAA,CAAW,sBAAA,KAAX,UAAA,CAAW,yBAA2B,EAAC,CAAA;AAGlD,EAAA,IAAI,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,EAAS;AAC1B,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,UAAA;AAClB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAwB,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,QAAA,CAAS,CAAA,EAAG,EAAE,CAAC,CAAA;AACnF,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,OAAA,CAAQ,QAAA,CAAS,QAAQ,OAAO,CAAA;AACjE,EAAA,MAAM,cAAc,YAAA,CAAa,SAAA,CAAU,IAAA,EAAM,OAAA,EAAS,QAAQ,OAAO,CAAA;AAEzE,EAAA,MAAM,mBACH,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,MACvB,WAAA,CAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,YAAY,CAAC,CAAA,IAAK,CAAA,KAAM,CAAA,IAClD,YAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,KAAM,EAAA,IAAA,CAClD,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,CAAA,IACvB,WAAA,CAAY,CAAC,CAAA,KAAM,CAAA,IAAA,CAAM,WAAA,CAAY,CAAC,KAAK,CAAA,KAAM,CAAA;AASpD,EAAA,MAAM,cAAc,OAAO,OAAA,KAAY,aAAa,OAAA,GAAUA,oBAAA,CAAc,iRAAe,CAAA;AAI3F,EAAA,MAAM,GAAA,GAAM,MAAA;AAUZ,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,GAAA,CAAI,aAAA,KAAkB,UAAA,IAAc,eAAA,EAAiB;AAK9D,MAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,IAAA,EAAK,GAAI,YAAY,4CAA4C,CAAA;AAK9F,MAAA,UAAA,CAAW,EAAE,gBAAA,EAAkBC,8BAAA,EAAyB,CAAA;AACxD,MAAA,GAAA,CAAI,aAAA,CAAc,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA;AACnC,MAAAC,sBAAA,IAAeC,UAAA,CAAM,IAAI,mFAAmF,CAAA;AAAA,IAC9G,CAAA,MAAA,IAAW,OAAO,GAAA,CAAI,QAAA,KAAa,UAAA,IAAc,CAAC,SAAA,CAAU,GAAA,IAAO,CAAC,SAAA,CAAU,IAAA,EAAM;AAOlF,MAAA,GAAA,CAAI,SAASC,sBAAA,CAAc,WAAA,CAAY,QAAQ,uCAAuC,CAAC,EAAE,IAAA,EAAM;AAAA,QAC7F,IAAA,EAAM,EAAE,gBAAA,EAAkBH,8BAAA;AAAwB,OACnD,CAAA;AAOD,MAAA,MAAM,WAAA,GAAc,YAAY,8BAA8B,CAAA;AAG9D,MAAA,IAAI,YAAY,EAAE,gBAAA,EAAkBA,8BAAA,EAAyB,EAAE,KAAA,EAAM;AACrE,MAAAC,sBAAA,IAAeC,UAAA,CAAM,IAAI,8EAA8E,CAAA;AAAA,IACzG,CAAA,MAAO;AACL,MAAAD,sBAAA,IACEC,UAAA,CAAM,KAAK,2FAA2F,CAAA;AACxG,MAAA;AAAA,IACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAAD,sBAAA,IACEC,UAAA,CAAM,IAAA;AAAA,MACJ,oHAAA;AAAA,MAEA;AAAA,KACF;AACF,IAAA;AAAA,EACF;AAEA,EAAA,CAAA,CAAE,OAAA,GAAU,IAAA;AACd;;;;"}
{"version":3,"file":"register.js","sources":["../../../../src/orchestrion/runtime/register.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { createRequire } from 'node:module';\nimport * as Module from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { SENTRY_INSTRUMENTATIONS } from '../config';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Synchronously register the diagnostics-channel injection module hooks.\n *\n * This is the single source of truth for the registration logic. It is used by:\n * - `Sentry.init()` (the Node SDK calls it directly — that's why this module\n * must be CJS-compatible / dual-built, so it can be `require()`d synchronously\n * before the app's `import`s resolve), and\n * - `import-hook.mjs`, the side-effecting `--import` entry, which just calls it.\n *\n * Libraries imported *after* this call publish the `tracingChannel` events that\n * the channel-based integrations subscribe to.\n *\n * Idempotent via `globalThis.__SENTRY_ORCHESTRION__` — a no-op if the runtime\n * `--import` hook or a bundler plugin already injected the channels.\n */\nexport function registerDiagnosticsChannelInjection(): void {\n const g = (globalThis.__SENTRY_ORCHESTRION__ ??= {});\n\n // Already injected (runtime --import hook or bundler plugin) — nothing to do.\n if (g.runtime || g.bundler) {\n return;\n }\n\n const globalAny = globalThis as { Bun?: unknown; Deno?: { version?: { deno?: string } } };\n const parseVersion = (v: string): number[] => v.split('.').map(n => parseInt(n, 10));\n const nodeVersion = parseVersion(process.versions.node ?? '0.0.0');\n const denoVersion = parseVersion(globalAny.Deno?.version?.deno ?? '0.0.0');\n // `Module.registerHooks` only became stable in Node 24.13 / 25.1 and Deno 2.8.\n const stableSyncHooks =\n (nodeVersion[0] ?? 0) > 25 ||\n (nodeVersion[0] === 25 && (nodeVersion[1] ?? 0) >= 1) ||\n (nodeVersion[0] === 24 && (nodeVersion[1] ?? 0) >= 13) ||\n (denoVersion[0] ?? 0) > 2 ||\n (denoVersion[0] === 2 && (denoVersion[1] ?? 0) >= 8);\n\n let nodeRequire: (specifier: string) => unknown;\n /*! rollup-include-cjs-only */\n nodeRequire = require;\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n nodeRequire = createRequire(import.meta.url);\n /*! rollup-include-esm-only-end */\n\n // `Module.registerHooks` / `Module.register` are newer than the @types/node\n // we build against, hence the cast.\n const mod = Module as unknown as {\n registerHooks?: (hooks: unknown) => void;\n register?: (specifier: string, options: unknown) => void;\n };\n\n // runs both at `--import` time and (synchronously) inside `Sentry.init()`,\n // so an unguarded throw would either abort startup or make `init()` throw.\n // On any failure (e.g. dep resolution, `require(esm)` / Node-compat\n // incompatibility) we warn (DEBUG only) and continue without channel\n // injection\n try {\n if (typeof mod.registerHooks === 'function' && stableSyncHooks) {\n // Sync hooks cover CJS and ESM, no separate `_compile` patch needed.\n // We require() the module here so that we can synchronously load it,\n // including from a CommonJS Sentry build, without bundlers pulling in.\n // All versions in stableSyncHooks support this.\n const { initialize, resolve, load } = nodeRequire('@apm-js-collab/tracing-hooks/hook-sync.mjs') as {\n initialize: (opts: { instrumentations: unknown }) => void;\n resolve: unknown;\n load: unknown;\n };\n initialize({ instrumentations: SENTRY_INSTRUMENTATIONS });\n mod.registerHooks({ resolve, load });\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.registerHooks()');\n } else if (typeof mod.register === 'function' && !globalAny.Bun && !globalAny.Deno) {\n // `Module.register` + the `_compile` patch is Node 18.19–24.12 / 25.0\n // path. Bun/Deno are excluded: they don't support this combination and\n // must use the stable `registerHooks` path above (or none at all).\n let parentURL: string;\n /*! rollup-include-cjs-only */\n parentURL = pathToFileURL(__filename).href;\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n parentURL = import.meta.url;\n /*! rollup-include-esm-only-end */\n\n mod.register('@apm-js-collab/tracing-hooks/hook.mjs', {\n parentURL,\n data: { instrumentations: SENTRY_INSTRUMENTATIONS },\n });\n\n // ALSO patch `Module.prototype._compile` for the CJS side: when an ESM\n // file `import`s a CJS package, the package's internal `require()` calls\n // are resolved through the CJS machinery and never reach the ESM\n // register hook, so without this patch the file we want to instrument\n // loads untransformed.\n const ModulePatch = nodeRequire('@apm-js-collab/tracing-hooks') as new (opts: { instrumentations: unknown }) => {\n patch: () => void;\n };\n new ModulePatch({ instrumentations: SENTRY_INSTRUMENTATIONS }).patch();\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.register()');\n } else {\n DEBUG_BUILD &&\n debug.warn('[Sentry] No available Node API to register diagnostics-channel injection hooks; skipping.');\n return;\n }\n } catch (error) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] Failed to register diagnostics-channel injection hooks; channel-based integrations ' +\n 'will not record spans.',\n error,\n );\n return;\n }\n\n g.runtime = true;\n}\n"],"names":["SENTRY_INSTRUMENTATIONS","DEBUG_BUILD","debug","pathToFileURL"],"mappings":";;;;;;;;AA2BO,SAAS,mCAAA,GAA4C;AAC1D,EAAA,MAAM,CAAA,GAAK,UAAA,CAAW,sBAAA,KAAX,UAAA,CAAW,yBAA2B,EAAC,CAAA;AAGlD,EAAA,IAAI,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,EAAS;AAC1B,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,UAAA;AAClB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAwB,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,QAAA,CAAS,CAAA,EAAG,EAAE,CAAC,CAAA;AACnF,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,OAAA,CAAQ,QAAA,CAAS,QAAQ,OAAO,CAAA;AACjE,EAAA,MAAM,cAAc,YAAA,CAAa,SAAA,CAAU,IAAA,EAAM,OAAA,EAAS,QAAQ,OAAO,CAAA;AAEzE,EAAA,MAAM,mBACH,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,MACvB,WAAA,CAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,YAAY,CAAC,CAAA,IAAK,CAAA,KAAM,CAAA,IAClD,YAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,KAAM,EAAA,IAAA,CAClD,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,CAAA,IACvB,WAAA,CAAY,CAAC,CAAA,KAAM,CAAA,IAAA,CAAM,WAAA,CAAY,CAAC,KAAK,CAAA,KAAM,CAAA;AAEpD,EAAA,IAAI,WAAA;AAAA,EACJ,WAAA,GAAA,OAAA;AACA,EAAA,MAAA,GAAA,GAAA,MAAc;AAAA,EACd,IAAA;AAAA,IACA,IAAA,OAAA,GAAA,CAAA,aAAA,KAAA,UAAA,IAAA,eAAA,EAAA;AACA,MAAA,MAAA,EAAA,UAAc,EAAA,kBAA0B,WAAG,CAAA,4CAAA,CAAA;AAAA,MAC3C,UAAA,CAAA,EAAA,gBAAA,EAAAA,6BAAA,EAAA,CAAA;AAIA,MAAA,GAAM,CAAA,aAAM,CAAA,EAAA,OAAA,EAAA,IAAA,EAAA,CAAA;AAUZ,MAAIC,sBAAA,IAAAC,UAAA,CAAA,GAAA,CAAA,mFAAA,CAAA;AACF,IAAA,CAAA,MAAI,IAAO,OAAI,GAAA,CAAA,QAAA,KAAkB,UAAA,IAAc,CAAA,SAAA,CAAA,GAAA,IAAiB,CAAA,SAAA,CAAA,IAAA,EAAA;AAK9D,MAAA,IAAA,SAAQ;AAKR,MAAA,SAAA,GAAWC,sBAAE,CAAA,UAAkB,CAAA,CAAA,IAAA;AAC/B,MAAA,GAAA,CAAI,QAAA,CAAA,uCAA+B,EAAA;AACnC,QAAA,SAAA;AAA4G,QAC9G,IAAA,EAAA,EAAW,gBAAW,EAAAH,6BAA4B;AAIhD,OAAA,CAAA;AAAI,MACJ,MAAA,WAAA,GAAA,WAAA,CAAA,8BAAA,CAAA;AACA,MAAA,IAAA,WAAY,CAAA,EAAA,kBAAwBA,6BAAE,EAAA,CAAA,CAAA,KAAA,EAAA;AAAA,MACtCC,sBAAA,IAAAC,UAAA,CAAA,GAAA,CAAA,8EAAA,CAAA;AAAA,IAAA,CAAA,MACA;AACA,MAAAD,sBAAA,IAAYC,UAAA,CAAA,IAAY,CAAA,2FAAA,CAAA;AAAA,MACxB;AAEA,IAAA;AAAsD,EAAA,CAAA,CAAA,OACpD,KAAA,EAAA;AAAA,IAAAD,sBACM,IAAEC,UAAA,CAAA,IAAA;AAA0C,MACpD,oHAAC;AAOD,MAAA;AAGA,KAAA;AACA,IAAA;AAAuG,EAAA;AAEvG,EAAA,CAAA,CAAA,OAAA,GAAA,IAAA;AAEA;;;;"}

@@ -122,3 +122,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const raw = isObject ? "message" in error ? error.message : void 0 : error;
const message = raw ? String(raw) : "unknown_error";
const message = raw ? String(raw) : void 0;
const type = isObject && "name" in error ? String(error.name) : "unknown";

@@ -125,0 +125,0 @@ return {

@@ -1,1 +0,1 @@

{"version":3,"file":"tracing-channel.js","sources":["../../src/tracing-channel.ts"],"sourcesContent":["import type { TracingChannel, TracingChannelSubscribers } from 'node:diagnostics_channel';\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport type { ExclusiveEventHintOrCaptureContext, Span } from '@sentry/core';\nimport { debug, captureException, SPAN_STATUS_ERROR, getAsyncContextStrategy, getMainCarrier } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { ERROR_TYPE } from '@sentry/conventions/attributes';\n\nexport type TracingChannelPayloadWithSpan<TData extends object> = TData & {\n /**\n * The current active span for the traced call.\n */\n _sentrySpan?: Span;\n\n /**\n * The context's active store value, used to restore the context for asyncStart continuations for callback-based tracing.\n */\n _sentryCallerStore?: unknown;\n};\n\n/*\n * A type patch so that we don't have to handle all subscription types.\n */\nexport interface SentryTracingChannel<TData extends object = object> extends Omit<\n TracingChannel<TData, TracingChannelPayloadWithSpan<TData>>,\n 'subscribe' | 'unsubscribe'\n> {\n subscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n unsubscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n}\n\nexport interface TracingChannelLifeCycleOptions<TData extends object = object> {\n /**\n * Invoked with the span and the channel context object once the traced operation completes\n * Use it to enrich the span from the result/error (branch on `'error' in data` / `'result' in data`) or to run cleanup.\n */\n beforeSpanEnd?: (span: Span, data: TracingChannelPayloadWithSpan<TData>) => void;\n\n /**\n * Whether a thrown error is captured as a Sentry event. The span is always marked with error status regardless. Defaults to `false`.\n * You can alternatively pass a function that sets the ExclusiveEventHintOrCaptureContext on the captured error.\n * Set `true` for instrumentations that own the error boundary, (e.g: route handlers)\n * For database drivers, it is not recommended to set this at all.\n */\n captureError?: boolean | ((e: unknown) => ExclusiveEventHintOrCaptureContext);\n\n /**\n * Take ownership of *when* the span ends: return `true` and the helper won't end it on\n * `end`/`asyncEnd`. For results that settle out-of-band — e.g. a streamed `EventEmitter` that\n * completes via its own `'end'`/`'error'` events.\n *\n * Call `end` when it settles — `end()` on success, `end(error)` on failure. `end` owns *how* the span\n * ends (error status/attributes, `captureError`, `beforeSpanEnd`) and is idempotent. Default `false`\n * lets the helper end the span as usual.\n */\n deferSpanEnd?: (args: {\n span: Span;\n data: TracingChannelPayloadWithSpan<TData>;\n /** Ends the span: `end()` on success, `end(error)` on failure. Idempotent. */\n end: (error?: unknown) => void;\n }) => boolean;\n}\n\n/** Returned by {@link bindTracingChannelToSpan}: the bound channel plus a teardown handle. */\nexport interface TracingChannelBindingHandle<TData extends object = object> {\n /**\n * The tracing channel with the span bound into async context.\n */\n channel: SentryTracingChannel<TData>;\n\n /**\n * Tears down the binding: unsubscribes lifecycle handlers, when present, and unbinds the start store.\n * Idempotent, and a no-op when no async context binding was available.\n */\n unbind: () => void;\n}\n\nconst NOOP = (): void => {};\n\n/**\n * Bind a span and its lifecycle to a tracing channel so the span becomes the active async context\n * for the traced operation and is ended when the operation completes.\n *\n * `getSpan` may return `undefined` to opt a payload out entirely: nothing is bound, no span is\n * tracked, and the active context is left untouched. Use it for events that ride the same channel\n * but should reuse the enclosing span instead of opening (and ending) their own — e.g. an agent\n * loop's per-step events, where ending a freshly opened span would close the parent prematurely.\n */\nexport function bindTracingChannelToSpan<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n opts?: TracingChannelLifeCycleOptions<TData>,\n): TracingChannelBindingHandle<TData> {\n const handle = bindSpanToChannelStore(channel, getSpan);\n\n const beforeSpanEnd = opts?.beforeSpanEnd;\n const deferSpanEnd = opts?.deferSpanEnd;\n const getErrorHint = (e: unknown): ExclusiveEventHintOrCaptureContext => {\n if (typeof opts?.captureError === 'function') {\n return opts.captureError(e);\n }\n\n return {\n mechanism: {\n type: 'auto.diagnostic_channels.bind_span',\n handled: false,\n },\n };\n };\n\n // Apply Sentry error status + attributes (and capture, if configured) to a span. Shared by the\n // channel `error` lifecycle and the deferred `end` util so the two can't drift.\n const annotateSpanError = (span: Span, error: unknown): void => {\n if (opts?.captureError) {\n captureException(error, getErrorHint(error));\n }\n\n const { message, attributes } = getErrorInfo(error);\n span.setStatus({ code: SPAN_STATUS_ERROR, message });\n span.setAttributes(attributes);\n };\n\n // Creates an end fn for deferred handlers to use, ensures consistent span end behavior\n const makeDeferredEnd = (span: Span, data: TracingChannelPayloadWithSpan<TData>) => {\n let ended = false;\n\n return (error?: unknown): void => {\n if (ended) {\n return;\n }\n\n ended = true;\n if (error !== undefined) {\n annotateSpanError(span, error);\n }\n\n endBoundSpan(data, beforeSpanEnd);\n };\n };\n\n const subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>> = {\n start: NOOP,\n asyncStart: NOOP,\n end(data) {\n // The operation settled synchronously (returned or threw)\n // Presence checks because caller can return `undefined` result or throw a falsy value.\n if ('error' in data || 'result' in data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n }\n },\n error(data) {\n // No span was bound for this payload (`getSpan` returned undefined), so there is nothing to\n // annotate and no instrumentation that owns capturing this error.\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n\n annotateSpanError(span, data.error);\n },\n asyncEnd(data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n },\n };\n\n handle.channel.subscribe(subscribers);\n\n return {\n channel: handle.channel,\n unbind: () => {\n handle.channel.unsubscribe(subscribers);\n handle.unbind();\n },\n };\n}\n\n/**\n * Bind a span into the channel's async context so it becomes active for the traced operation,\n * without managing its lifecycle. The primitive behind {@link bindTracingChannelToSpan}, which\n * layers span-ending and error handling on top.\n *\n * `getSpan` may return `undefined` to leave the active context untouched for that payload.\n */\nfunction bindSpanToChannelStore<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n): TracingChannelBindingHandle<TData> {\n // Grabs the tracing channel binding defined by the AsyncContext strategy implementation\n const binding = getAsyncContextStrategy(getMainCarrier()).getTracingChannelBinding?.();\n\n // If no binding, then either the implementer doesn't support tracing channels or there is no active strategy\n // Failure mode here means we would still access the channel and potentially subscribe to it, but parenting will be off.\n if (!binding) {\n DEBUG_BUILD && debug.log('[TracingChannel] Could not access async context binding.');\n\n return {\n channel,\n unbind: NOOP,\n };\n }\n\n // Grab the ALS instance, we don't really care what is in it as long as the AsyncContext strategy can use its value to figure out parenting.\n const asyncLocalStorage = binding.asyncLocalStorage as AsyncLocalStorage<TData>;\n\n // bindStore activates the ALS for the traced call; any getStore() inside it returns the value bound for that context.\n // 1. Produce: getStoreWithActiveSpan(span) clones the current scope, plants the span via _INTERNAL_setSpanForScope, and returns { scope, isolationScope }, the active context carrying our span.\n // 2. Bind: the courier hands that opaque value to channel.start.bindStore(asyncLocalStorage, producer), which runs the traced op inside asyncLocalStorage.run(value, …); it never inspects the value.\n // 3. Read: inside the op, Sentry's scope machinery calls getScopes() → asyncStorage.getStore() on that same ALS, so getCurrentScope/getIsolationScope/getActiveSpan resolve to the scope carrying our span.\n // 4. Nest: any child span started in the traced op parents to that active span.\n channel.start.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n // Stash the caller's store before we swap in the span store, so `asyncStart` can restore it for\n // callback-style channels (see `_sentryCallerStore`).\n data._sentryCallerStore = asyncLocalStorage.getStore();\n\n const span = getSpan(data);\n if (!span) {\n // Leave the active context untouched so nested operations keep parenting to the enclosing span.\n return data._sentryCallerStore as TData;\n }\n data._sentrySpan = span;\n\n return binding.getStoreWithActiveSpan(span) as TData;\n });\n\n // Restore the caller's context for the async continuation. Only callback-style channels `runStores`\n // `asyncStart` (so the callback runs inside this store). promise channels `publish` it, leaving this\n // inert, their continuation already inherits the caller's context natively.\n channel.asyncStart.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n return data._sentryCallerStore as TData;\n });\n\n return {\n channel,\n unbind: () => {\n // Removes the stores\n channel.start.unbindStore(asyncLocalStorage);\n channel.asyncStart.unbindStore(asyncLocalStorage);\n },\n };\n}\n\nfunction endBoundSpan<TData extends object>(\n data: TracingChannelPayloadWithSpan<TData>,\n beforeSpanEnd: TracingChannelLifeCycleOptions<TData>['beforeSpanEnd'],\n): void {\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n beforeSpanEnd?.(span, data);\n span.end();\n}\n\ntype ErrorInfo = {\n message: string;\n attributes: Record<string, string>;\n};\n\n/**\n * Best-effort message and attribute extraction for thrown/rejected values.\n */\nfunction getErrorInfo(error: unknown): ErrorInfo {\n const isObject = !!error && typeof error === 'object';\n const raw = isObject ? ('message' in error ? error.message : undefined) : error;\n\n const message = raw ? String(raw) : 'unknown_error';\n const type = isObject && 'name' in error ? String(error.name) : 'unknown';\n\n return {\n message,\n attributes: {\n [ERROR_TYPE]: type,\n },\n };\n}\n"],"names":["captureException","SPAN_STATUS_ERROR","getAsyncContextStrategy","getMainCarrier","DEBUG_BUILD","debug","ERROR_TYPE"],"mappings":"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"}
{"version":3,"file":"tracing-channel.js","sources":["../../src/tracing-channel.ts"],"sourcesContent":["import type { TracingChannel, TracingChannelSubscribers } from 'node:diagnostics_channel';\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport type { ExclusiveEventHintOrCaptureContext, Span } from '@sentry/core';\nimport { debug, captureException, SPAN_STATUS_ERROR, getAsyncContextStrategy, getMainCarrier } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { ERROR_TYPE } from '@sentry/conventions/attributes';\n\nexport type TracingChannelPayloadWithSpan<TData extends object> = TData & {\n /**\n * The current active span for the traced call.\n */\n _sentrySpan?: Span;\n\n /**\n * The context's active store value, used to restore the context for asyncStart continuations for callback-based tracing.\n */\n _sentryCallerStore?: unknown;\n};\n\n/*\n * A type patch so that we don't have to handle all subscription types.\n */\nexport interface SentryTracingChannel<TData extends object = object> extends Omit<\n TracingChannel<TData, TracingChannelPayloadWithSpan<TData>>,\n 'subscribe' | 'unsubscribe'\n> {\n subscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n unsubscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n}\n\nexport interface TracingChannelLifeCycleOptions<TData extends object = object> {\n /**\n * Invoked with the span and the channel context object once the traced operation completes\n * Use it to enrich the span from the result/error (branch on `'error' in data` / `'result' in data`) or to run cleanup.\n */\n beforeSpanEnd?: (span: Span, data: TracingChannelPayloadWithSpan<TData>) => void;\n\n /**\n * Whether a thrown error is captured as a Sentry event. The span is always marked with error status regardless. Defaults to `false`.\n * You can alternatively pass a function that sets the ExclusiveEventHintOrCaptureContext on the captured error.\n * Set `true` for instrumentations that own the error boundary, (e.g: route handlers)\n * For database drivers, it is not recommended to set this at all.\n */\n captureError?: boolean | ((e: unknown) => ExclusiveEventHintOrCaptureContext);\n\n /**\n * Take ownership of *when* the span ends: return `true` and the helper won't end it on\n * `end`/`asyncEnd`. For results that settle out-of-band — e.g. a streamed `EventEmitter` that\n * completes via its own `'end'`/`'error'` events.\n *\n * Call `end` when it settles — `end()` on success, `end(error)` on failure. `end` owns *how* the span\n * ends (error status/attributes, `captureError`, `beforeSpanEnd`) and is idempotent. Default `false`\n * lets the helper end the span as usual.\n */\n deferSpanEnd?: (args: {\n span: Span;\n data: TracingChannelPayloadWithSpan<TData>;\n /** Ends the span: `end()` on success, `end(error)` on failure. Idempotent. */\n end: (error?: unknown) => void;\n }) => boolean;\n}\n\n/** Returned by {@link bindTracingChannelToSpan}: the bound channel plus a teardown handle. */\nexport interface TracingChannelBindingHandle<TData extends object = object> {\n /**\n * The tracing channel with the span bound into async context.\n */\n channel: SentryTracingChannel<TData>;\n\n /**\n * Tears down the binding: unsubscribes lifecycle handlers, when present, and unbinds the start store.\n * Idempotent, and a no-op when no async context binding was available.\n */\n unbind: () => void;\n}\n\nconst NOOP = (): void => {};\n\n/**\n * Bind a span and its lifecycle to a tracing channel so the span becomes the active async context\n * for the traced operation and is ended when the operation completes.\n *\n * `getSpan` may return `undefined` to opt a payload out entirely: nothing is bound, no span is\n * tracked, and the active context is left untouched. Use it for events that ride the same channel\n * but should reuse the enclosing span instead of opening (and ending) their own — e.g. an agent\n * loop's per-step events, where ending a freshly opened span would close the parent prematurely.\n */\nexport function bindTracingChannelToSpan<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n opts?: TracingChannelLifeCycleOptions<TData>,\n): TracingChannelBindingHandle<TData> {\n const handle = bindSpanToChannelStore(channel, getSpan);\n\n const beforeSpanEnd = opts?.beforeSpanEnd;\n const deferSpanEnd = opts?.deferSpanEnd;\n const getErrorHint = (e: unknown): ExclusiveEventHintOrCaptureContext => {\n if (typeof opts?.captureError === 'function') {\n return opts.captureError(e);\n }\n\n return {\n mechanism: {\n type: 'auto.diagnostic_channels.bind_span',\n handled: false,\n },\n };\n };\n\n // Apply Sentry error status + attributes (and capture, if configured) to a span. Shared by the\n // channel `error` lifecycle and the deferred `end` util so the two can't drift.\n const annotateSpanError = (span: Span, error: unknown): void => {\n if (opts?.captureError) {\n captureException(error, getErrorHint(error));\n }\n\n const { message, attributes } = getErrorInfo(error);\n span.setStatus({ code: SPAN_STATUS_ERROR, message });\n span.setAttributes(attributes);\n };\n\n // Creates an end fn for deferred handlers to use, ensures consistent span end behavior\n const makeDeferredEnd = (span: Span, data: TracingChannelPayloadWithSpan<TData>) => {\n let ended = false;\n\n return (error?: unknown): void => {\n if (ended) {\n return;\n }\n\n ended = true;\n if (error !== undefined) {\n annotateSpanError(span, error);\n }\n\n endBoundSpan(data, beforeSpanEnd);\n };\n };\n\n const subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>> = {\n start: NOOP,\n asyncStart: NOOP,\n end(data) {\n // The operation settled synchronously (returned or threw)\n // Presence checks because caller can return `undefined` result or throw a falsy value.\n if ('error' in data || 'result' in data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n }\n },\n error(data) {\n // No span was bound for this payload (`getSpan` returned undefined), so there is nothing to\n // annotate and no instrumentation that owns capturing this error.\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n\n annotateSpanError(span, data.error);\n },\n asyncEnd(data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n },\n };\n\n handle.channel.subscribe(subscribers);\n\n return {\n channel: handle.channel,\n unbind: () => {\n handle.channel.unsubscribe(subscribers);\n handle.unbind();\n },\n };\n}\n\n/**\n * Bind a span into the channel's async context so it becomes active for the traced operation,\n * without managing its lifecycle. The primitive behind {@link bindTracingChannelToSpan}, which\n * layers span-ending and error handling on top.\n *\n * `getSpan` may return `undefined` to leave the active context untouched for that payload.\n */\nfunction bindSpanToChannelStore<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n): TracingChannelBindingHandle<TData> {\n // Grabs the tracing channel binding defined by the AsyncContext strategy implementation\n const binding = getAsyncContextStrategy(getMainCarrier()).getTracingChannelBinding?.();\n\n // If no binding, then either the implementer doesn't support tracing channels or there is no active strategy\n // Failure mode here means we would still access the channel and potentially subscribe to it, but parenting will be off.\n if (!binding) {\n DEBUG_BUILD && debug.log('[TracingChannel] Could not access async context binding.');\n\n return {\n channel,\n unbind: NOOP,\n };\n }\n\n // Grab the ALS instance, we don't really care what is in it as long as the AsyncContext strategy can use its value to figure out parenting.\n const asyncLocalStorage = binding.asyncLocalStorage as AsyncLocalStorage<TData>;\n\n // bindStore activates the ALS for the traced call; any getStore() inside it returns the value bound for that context.\n // 1. Produce: getStoreWithActiveSpan(span) clones the current scope, plants the span via _INTERNAL_setSpanForScope, and returns { scope, isolationScope }, the active context carrying our span.\n // 2. Bind: the courier hands that opaque value to channel.start.bindStore(asyncLocalStorage, producer), which runs the traced op inside asyncLocalStorage.run(value, …); it never inspects the value.\n // 3. Read: inside the op, Sentry's scope machinery calls getScopes() → asyncStorage.getStore() on that same ALS, so getCurrentScope/getIsolationScope/getActiveSpan resolve to the scope carrying our span.\n // 4. Nest: any child span started in the traced op parents to that active span.\n channel.start.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n // Stash the caller's store before we swap in the span store, so `asyncStart` can restore it for\n // callback-style channels (see `_sentryCallerStore`).\n data._sentryCallerStore = asyncLocalStorage.getStore();\n\n const span = getSpan(data);\n if (!span) {\n // Leave the active context untouched so nested operations keep parenting to the enclosing span.\n return data._sentryCallerStore as TData;\n }\n data._sentrySpan = span;\n\n return binding.getStoreWithActiveSpan(span) as TData;\n });\n\n // Restore the caller's context for the async continuation. Only callback-style channels `runStores`\n // `asyncStart` (so the callback runs inside this store). promise channels `publish` it, leaving this\n // inert, their continuation already inherits the caller's context natively.\n channel.asyncStart.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n return data._sentryCallerStore as TData;\n });\n\n return {\n channel,\n unbind: () => {\n // Removes the stores\n channel.start.unbindStore(asyncLocalStorage);\n channel.asyncStart.unbindStore(asyncLocalStorage);\n },\n };\n}\n\nfunction endBoundSpan<TData extends object>(\n data: TracingChannelPayloadWithSpan<TData>,\n beforeSpanEnd: TracingChannelLifeCycleOptions<TData>['beforeSpanEnd'],\n): void {\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n beforeSpanEnd?.(span, data);\n span.end();\n}\n\ntype ErrorInfo = {\n message: string | undefined;\n attributes: Record<string, string>;\n};\n\n/**\n * Best-effort message and attribute extraction for thrown/rejected values.\n */\nfunction getErrorInfo(error: unknown): ErrorInfo {\n const isObject = !!error && typeof error === 'object';\n const raw = isObject ? ('message' in error ? error.message : undefined) : error;\n\n // Leave the status message unset if not set (e.g. an `AggregateError` from\n // ECONNREFUSED, whose `.message` is empty). Otherwise cast to string.\n const message = raw ? String(raw) : undefined;\n const type = isObject && 'name' in error ? String(error.name) : 'unknown';\n\n return {\n message,\n attributes: {\n [ERROR_TYPE]: type,\n },\n };\n}\n"],"names":["captureException","SPAN_STATUS_ERROR","getAsyncContextStrategy","getMainCarrier","DEBUG_BUILD","debug","ERROR_TYPE"],"mappings":"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"}

@@ -20,3 +20,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const toolDescriptionsByCallId = /* @__PURE__ */ new Map();
const ROOT_OPERATION_TYPES = /* @__PURE__ */ new Set(["generateText", "streamText", "embed", "rerank"]);
const ROOT_OPERATION_TYPES = /* @__PURE__ */ new Set(["generateText", "streamText", "embed", "embedMany", "rerank"]);
function clearOperationId(data) {

@@ -28,6 +28,9 @@ if (!ROOT_OPERATION_TYPES.has(data.type)) {

if (callId) {
operationIdByCallId.delete(callId);
toolDescriptionsByCallId.delete(callId);
clearOperationCallId(callId);
}
}
function clearOperationCallId(callId) {
operationIdByCallId.delete(callId);
toolDescriptionsByCallId.delete(callId);
}
function recordToolDescriptions(callId, tools) {

@@ -112,6 +115,9 @@ if (!callId || !Array.isArray(tools)) {

case "embed":
case "embedMany": {
const input = type === "embedMany" ? event.values : event.value;
return startGenAiSpan(GEN_AI_EMBEDDINGS_OPERATION, modelId, {
...baseAttributes,
...recordInputs && event.value !== void 0 ? { [attributes.GEN_AI_EMBEDDINGS_INPUT]: safeStringify(event.value) } : {}
...recordInputs && input !== void 0 ? { [attributes.GEN_AI_EMBEDDINGS_INPUT]: safeStringify(input) } : {}
});
}
case "rerank":

@@ -361,2 +367,3 @@ return startGenAiSpan(GEN_AI_RERANK_OPERATION, modelId, baseAttributes);

exports.clearOperationCallId = clearOperationCallId;
exports.clearOperationId = clearOperationId;

@@ -363,0 +370,0 @@ exports.createSpanFromMessage = createSpanFromMessage;

@@ -1,1 +0,1 @@

{"version":3,"file":"vercel-ai-dc-subscriber.js","sources":["../../../src/vercel-ai/vercel-ai-dc-subscriber.ts"],"sourcesContent":["/* eslint-disable max-lines */\n// `@sentry/conventions` marks several gen_ai attributes (e.g. `GEN_AI_SYSTEM`, `GEN_AI_TOOL_*`,\n// `GEN_AI_REQUEST_AVAILABLE_TOOLS`) as deprecated in favour of newer semconv names. We intentionally\n// keep emitting the current names so these spans match the OTel-based (v6) integration and what the\n// Sentry product consumes today; migrating to the new names is a separate, coordinated change.\n/* eslint-disable typescript-eslint/no-deprecated */\nimport {\n GEN_AI_EMBEDDINGS_INPUT,\n GEN_AI_FUNCTION_ID,\n GEN_AI_INPUT_MESSAGES,\n GEN_AI_OPERATION_NAME,\n GEN_AI_OUTPUT_MESSAGES,\n GEN_AI_REQUEST_AVAILABLE_TOOLS,\n GEN_AI_REQUEST_MODEL,\n GEN_AI_RESPONSE_FINISH_REASONS,\n GEN_AI_RESPONSE_ID,\n GEN_AI_RESPONSE_MODEL,\n GEN_AI_RESPONSE_STREAMING,\n GEN_AI_SYSTEM,\n GEN_AI_TOOL_INPUT,\n GEN_AI_TOOL_NAME,\n GEN_AI_TOOL_OUTPUT,\n GEN_AI_TOOL_TYPE,\n GEN_AI_USAGE_INPUT_TOKENS,\n GEN_AI_USAGE_OUTPUT_TOKENS,\n GEN_AI_USAGE_TOTAL_TOKENS,\n} from '@sentry/conventions/attributes';\nimport { GEN_AI_EXECUTE_TOOL_SPAN_OP, GEN_AI_INVOKE_AGENT_SPAN_OP } from '@sentry/conventions/op';\nimport type { Span } from '@sentry/core';\nimport {\n captureException,\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n getClient,\n getProviderMetadataAttributes,\n getTruncatedJsonString,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n SPAN_STATUS_ERROR,\n spanToJSON,\n spanToTraceContext,\n startInactiveSpan,\n withScope,\n} from '@sentry/core';\nimport type { TracingChannel } from 'node:diagnostics_channel';\nimport { bindTracingChannelToSpan } from '../tracing-channel';\n\n/**\n * The single tracing channel the `ai` package (>= 7) publishes all telemetry lifecycle events to\n * via `node:diagnostics_channel`. Events are discriminated by their `type` field.\n * @see https://github.com/vercel/ai/pull/15660\n */\nconst AI_SDK_TELEMETRY_TRACING_CHANNEL = 'ai:telemetry';\n\nconst ORIGIN = 'auto.vercelai.channel';\n\n// `@sentry/conventions` does not expose these yet, so we keep the literals here.\nconst GEN_AI_TOOL_CALL_ID_ATTRIBUTE = 'gen_ai.tool.call.id';\nconst GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE = 'gen_ai.tool.description';\nconst GEN_AI_EMBEDDINGS_OPERATION = 'embeddings';\nconst GEN_AI_RERANK_OPERATION = 'rerank';\n// The model-call op matches the Vercel AI OTel integration (`gen_ai.generate_content`) rather than\n// the generic `gen_ai.chat`, so v6 (OTel) and v7 (channel) produce the same spans.\nconst GEN_AI_GENERATE_CONTENT_OPERATION = 'generate_content';\n\n// Subset of the `vercel.ai.*` passthrough attributes the OTel integration emits that we reproduce.\nconst VERCEL_AI_OPERATION_ID_ATTRIBUTE = 'vercel.ai.operationId';\nconst VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE = 'vercel.ai.model.provider';\nconst VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE = 'vercel.ai.settings.maxRetries';\n\n// Tracks the top-level operationId (and whether it streams) per `callId` so a model-call span can\n// name its `doGenerate`/`doStream` operation the same way the OTel integration does. `isStream` is\n// the authoritative event-type signal rather than a substring check on the (possibly custom)\n// operationId. Cleared when the top-level span ends.\nconst operationIdByCallId = new Map<string, { operationId: string; isStream: boolean }>();\n\n// Per-operation map of tool name → description, harvested from a model-call /\n// top-level event's `tools` (keyed by the shared `callId`). The AI SDK's\n// `executeTool` event doesn't carry the tool's description, so we backfill it\n// onto the tool span here — without relying on the OTel `vercelAiEventProcessor`\n// (which isn't registered in channel/orchestrion mode). Cleared with the\n// operation. Only populated when inputs are recorded, matching the OTel path\n// (which sources descriptions from the recorded `available_tools`).\nconst toolDescriptionsByCallId = new Map<string, Map<string, string>>();\n\n// Only top-level operations own the `callId` → operationId mapping; `step`/`languageModelCall`/\n// `executeTool` share the parent's `callId`, so they must not clear it.\nconst ROOT_OPERATION_TYPES = new Set<ChannelEventType>(['generateText', 'streamText', 'embed', 'rerank']);\n\n/** Drop the per-operation `callId` maps once the owning top-level operation settles (success or error). */\nexport function clearOperationId(data: VercelAiChannelMessage): void {\n if (!ROOT_OPERATION_TYPES.has(data.type)) {\n return;\n }\n const callId = asString(data.event.callId);\n if (callId) {\n operationIdByCallId.delete(callId);\n toolDescriptionsByCallId.delete(callId);\n }\n}\n\n/** Record tool name → description from an event's `tools`, so tool spans can backfill the description. */\nfunction recordToolDescriptions(callId: string | undefined, tools: unknown): void {\n if (!callId || !Array.isArray(tools)) {\n return;\n }\n let descriptions = toolDescriptionsByCallId.get(callId);\n for (const tool of tools) {\n if (isRecord(tool) && typeof tool.name === 'string' && typeof tool.description === 'string') {\n descriptions = descriptions ?? new Map();\n if (!descriptions.has(tool.name)) {\n descriptions.set(tool.name, tool.description);\n }\n }\n }\n if (descriptions) {\n toolDescriptionsByCallId.set(callId, descriptions);\n }\n}\n\n/**\n * Resolve a tool's description, preferring the per-operation map (populated from the model-call /\n * top-level event's `tools`, v7) and falling back to a `tools` collection on the event itself —\n * which may be an array of `{ name, description }` or a record keyed by tool name (v6).\n */\nfunction resolveToolDescription(callId: string | undefined, toolName: string, tools: unknown): string | undefined {\n const fromMap = callId ? toolDescriptionsByCallId.get(callId)?.get(toolName) : undefined;\n if (fromMap) {\n return fromMap;\n }\n if (Array.isArray(tools)) {\n const match = tools.find(tool => isRecord(tool) && tool.name === toolName);\n return isRecord(match) ? asString(match.description) : undefined;\n }\n if (isRecord(tools)) {\n const tool = tools[toolName];\n return isRecord(tool) ? asString(tool.description) : undefined;\n }\n return undefined;\n}\n\n/** The lifecycle event types the `ai:telemetry` channel can carry. */\nexport type ChannelEventType =\n | 'generateText'\n | 'streamText'\n | 'step'\n | 'languageModelCall'\n | 'executeTool'\n | 'embed'\n | 'rerank';\n\n/**\n * The context object the AI SDK passes through one tracing-channel call. It is the same object\n * identity across `start`/`end`/`asyncEnd`/`error`, and Node's `tracingChannel` attaches\n * `result`/`error` to it as the traced promise settles.\n */\nexport interface VercelAiChannelMessage {\n type: ChannelEventType;\n event: Record<string, unknown>;\n result?: unknown;\n error?: unknown;\n}\n\n/**\n * Platform-provided factory that returns a tracing channel for the given channel name. The factory\n * is responsible for, when `start` fires, calling `transformStart(data)` and storing the returned\n * span on `data._sentrySpan` so the subscriber's `asyncEnd`/`error` handlers can read it.\n *\n * Node passes `@sentry/opentelemetry/tracing-channel`, which uses `bindStore` to additionally make\n * the span the active OTel context for the duration of the traced operation. That is what makes\n * nested AI SDK operations (model calls, tool calls) become children of the enclosing span without\n * any manual parent bookkeeping here.\n */\ntype VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;\n\n/** Integration-level recording options, pinned at subscribe time so we never look the integration up per event. */\ninterface VercelAiChannelOptions {\n recordInputs?: boolean;\n recordOutputs?: boolean;\n enableTruncation?: boolean;\n}\n\nlet subscribed = false;\n\n/**\n * Subscribe Sentry span handlers to the `ai` SDK's native telemetry tracing channel (`ai:telemetry`,\n * available in `ai` >= 7) and emit fully-formed `gen_ai.*` spans directly — no OpenTelemetry span\n * post-processing involved.\n *\n * The integration passes its options in directly (rather than us looking the integration up on every\n * event); the global `dataCollection.genAI` default is still read from the client per event.\n *\n * Safe to always call: on `ai` versions that don't publish to the channel (e.g. < 7) nothing is\n * ever emitted and this is inert, so there is no double-instrumentation against the OTel-based\n * patcher. Idempotent.\n */\nexport function subscribeVercelAiTracingChannel(\n tracingChannel: VercelAiTracingChannelFactory,\n options: VercelAiChannelOptions = {},\n): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n bindTracingChannelToSpan(\n tracingChannel<VercelAiChannelMessage>(AI_SDK_TELEMETRY_TRACING_CHANNEL),\n data => createSpanFromMessage(data, options),\n {\n // The helper ends the span; we enrich it from the settled result first (tokens, output messages,\n // finish reasons, response model/id, provider metadata) and drop the per-operation `callId` maps.\n beforeSpanEnd: (span, data) => {\n enrichSpanOnEnd(span, data, options);\n clearOperationId(data);\n },\n },\n );\n}\n\n/**\n * Transform a channel `start` payload into the span that should be active for the operation. For\n * `step` we deliberately don't open a span (model calls and tool calls are siblings under the\n * invoke_agent span, matching the OTel-based output), so we reuse the active span and mark the\n * payload to skip ending it.\n */\nexport function createSpanFromMessage(\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): Span | undefined {\n const { type, event } = data;\n\n if (type === 'step' || !event || typeof event !== 'object') {\n // Opt out: returning `undefined` leaves the enclosing `invoke_agent` span as the active context\n // (model-call and tool-call events nest under it) without opening — or ending — a span of its own.\n return undefined;\n }\n\n const { recordInputs, enableTruncation } = getRecordingOptions(event, channelOptions);\n const provider = asString(event.provider);\n const modelId = asString(event.modelId);\n const callId = asString(event.callId);\n const maxRetries = asNumber(event.maxRetries);\n\n // Harvest tool descriptions from the operation/model-call `tools` so tool spans can backfill them.\n // Gated on `recordInputs` to match the OTel path, which only records `available_tools` then.\n if (recordInputs) {\n recordToolDescriptions(callId, event.tools);\n }\n\n const baseAttributes: Record<string, string | number | boolean> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n ...(provider ? { [GEN_AI_SYSTEM]: provider, [VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE]: provider } : {}),\n ...(modelId ? { [GEN_AI_REQUEST_MODEL]: modelId } : {}),\n ...(maxRetries !== undefined ? { [VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE]: maxRetries } : {}),\n };\n\n switch (type) {\n case 'generateText':\n case 'streamText':\n return buildInvokeAgentSpan(event, baseAttributes, recordInputs, enableTruncation, callId, type === 'streamText');\n case 'languageModelCall':\n return buildModelCallSpan(event, baseAttributes, recordInputs, enableTruncation, callId, modelId);\n case 'executeTool':\n return buildToolSpan(event, recordInputs);\n case 'embed':\n return startGenAiSpan(GEN_AI_EMBEDDINGS_OPERATION, modelId, {\n ...baseAttributes,\n ...(recordInputs && event.value !== undefined ? { [GEN_AI_EMBEDDINGS_INPUT]: safeStringify(event.value) } : {}),\n });\n case 'rerank':\n return startGenAiSpan(GEN_AI_RERANK_OPERATION, modelId, baseAttributes);\n default:\n // Unknown event type: opt out rather than open a span we can't shape correctly.\n return undefined;\n }\n}\n\ntype Attributes = Record<string, string | number | boolean>;\n\n/** Start a `gen_ai.<operation>` span named `<operation> <suffix>` (or just `<operation>` when no suffix). */\nfunction startGenAiSpan(operation: string, suffix: string | undefined, attributes: Attributes): Span {\n return startInactiveSpan({\n name: suffix ? `${operation} ${suffix}` : operation,\n op: `gen_ai.${operation}`,\n attributes: { [GEN_AI_OPERATION_NAME]: operation, ...attributes },\n });\n}\n\nfunction buildInvokeAgentSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n isStream: boolean,\n): Span {\n const functionId = asString(event.functionId);\n const operationId = asString(event.operationId) ?? (isStream ? 'ai.streamText' : 'ai.generateText');\n if (callId) {\n operationIdByCallId.set(callId, { operationId, isStream });\n }\n return startGenAiSpan(GEN_AI_INVOKE_AGENT_SPAN_OP, functionId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n [GEN_AI_RESPONSE_STREAMING]: isStream,\n ...(functionId ? { [GEN_AI_FUNCTION_ID]: functionId } : {}),\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n });\n}\n\nfunction buildModelCallSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n modelId: string | undefined,\n): Span {\n const parent = callId ? operationIdByCallId.get(callId) : undefined;\n const operationId = parent\n ? `${parent.operationId}.${parent.isStream ? 'doStream' : 'doGenerate'}`\n : 'ai.generateText.doGenerate';\n return startGenAiSpan(GEN_AI_GENERATE_CONTENT_OPERATION, modelId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n ...(recordInputs && Array.isArray(event.tools)\n ? { [GEN_AI_REQUEST_AVAILABLE_TOOLS]: safeStringify(event.tools) }\n : {}),\n });\n}\n\nfunction buildToolSpan(event: Record<string, unknown>, recordInputs: boolean): Span {\n const toolCall = isRecord(event.toolCall) ? event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(event.toolCallId) ?? asString(toolCall.toolCallId);\n const toolInput = toolCall.input ?? toolCall.args;\n // The `executeTool` event has no description; backfill it from the operation's recorded tools.\n // Gated on `recordInputs` to match the OTel path (descriptions come from the recorded tools list).\n const description =\n recordInputs && toolName ? resolveToolDescription(asString(event.callId), toolName, event.tools) : undefined;\n return startGenAiSpan(GEN_AI_EXECUTE_TOOL_SPAN_OP, toolName, {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [GEN_AI_TOOL_TYPE]: 'function',\n ...(toolName ? { [GEN_AI_TOOL_NAME]: toolName } : {}),\n ...(toolCallId ? { [GEN_AI_TOOL_CALL_ID_ATTRIBUTE]: toolCallId } : {}),\n ...(description ? { [GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE]: description } : {}),\n ...(recordInputs && toolInput !== undefined ? { [GEN_AI_TOOL_INPUT]: safeStringify(toolInput) } : {}),\n });\n}\n\n/**\n * Best-effort enrichment from the resolved value the AI SDK attaches to the channel context.\n * Everything here is guarded: when a field is missing or the shape differs across `ai` versions,\n * we simply don't set the attribute rather than emit a malformed span.\n */\nexport function enrichSpanOnEnd(\n span: Span,\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): void {\n const { type, result } = data;\n if (!isRecord(result)) {\n return;\n }\n\n const { recordOutputs } = getRecordingOptions(data.event, channelOptions);\n\n if (type === 'executeTool') {\n if (recordOutputs) {\n span.setAttribute(GEN_AI_TOOL_OUTPUT, safeStringify(result.output ?? result));\n }\n // From V5 on, tool errors are not rejected (so the `error` channel verb never fires) — they\n // surface as `tool-error` content on the resolved result. Mirror the OTel path by marking the\n // span and capturing the error.\n const output = isRecord(result.output) ? result.output : undefined;\n if (output?.type === 'tool-error') {\n captureToolError(span, data, output.error);\n }\n return;\n }\n\n // `languageModelCall` results report usage as `{ total }` objects; top-level/step results report\n // flat numbers. `tokenCount` handles both.\n const usage = isRecord(result.usage) ? result.usage : undefined;\n if (usage) {\n const inputTokens = tokenCount(usage.inputTokens) ?? tokenCount(usage.tokens);\n const outputTokens = tokenCount(usage.outputTokens);\n const totalTokens = tokenCount(usage.totalTokens) ?? sum(inputTokens, outputTokens);\n if (inputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n if (totalTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n }\n\n // Match the OTel integration: finish reasons live on the model-call (`generate_content`) span, not\n // on the top-level `invoke_agent` span.\n const finishReason = getFinishReason(result);\n if (finishReason && type === 'languageModelCall') {\n span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, safeStringify([finishReason]));\n }\n\n const response = isRecord(result.response) ? result.response : undefined;\n const responseId = asString(response?.id) ?? asString(result.responseId);\n if (responseId) {\n span.setAttribute(GEN_AI_RESPONSE_ID, responseId);\n }\n const responseModel = asString(response?.modelId) ?? asString(data.event.modelId);\n if (responseModel) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL, responseModel);\n }\n\n // Provider-specific cache/reasoning/prediction token breakdowns and `gen_ai.conversation.id`.\n // The channel exposes `providerMetadata` as an object (the OTel path parses it from a string);\n // both share `getProviderMetadataAttributes` so the emitted shape is identical.\n const providerMetadata = (result as { providerMetadata?: unknown }).providerMetadata;\n const providerAttributes = getProviderMetadataAttributes(providerMetadata);\n // Don't overwrite a conversation id already set on span start (e.g. by `conversationIdIntegration`\n // from a user-set scope value); the provider-derived id is only a fallback. Matches the OTel path.\n if (\n GEN_AI_CONVERSATION_ID_ATTRIBUTE in providerAttributes &&\n spanToJSON(span).data[GEN_AI_CONVERSATION_ID_ATTRIBUTE]\n ) {\n // oxlint-disable-next-line typescript/no-dynamic-delete\n delete providerAttributes[GEN_AI_CONVERSATION_ID_ATTRIBUTE];\n }\n span.setAttributes(providerAttributes);\n\n if (recordOutputs) {\n // `languageModelCall` exposes the response as a `content` parts array; top-level results expose\n // `text` + `toolCalls`. Both normalize into the OTel `gen_ai.output.messages` assistant message.\n const parts =\n type === 'languageModelCall' && Array.isArray(result.content)\n ? partsFromContent(result.content)\n : partsFromTextAndToolCalls(result.text, result.toolCalls);\n const outputMessages = buildOutputMessages(parts, finishReason);\n if (outputMessages) {\n span.setAttribute(GEN_AI_OUTPUT_MESSAGES, outputMessages);\n }\n }\n}\n\n/** Maps a Vercel AI finish reason to the OTel `gen_ai.output.messages` form (`tool-calls` → `tool_call`). */\nfunction normalizeFinishReason(finishReason: string | undefined): string {\n return finishReason === 'tool-calls' ? 'tool_call' : (finishReason ?? 'stop');\n}\n\n/** Reads the finish reason from a result — a string on top-level results, `{ unified }` on model calls. */\nfunction getFinishReason(result: Record<string, unknown>): string | undefined {\n const finishReason = result.finishReason;\n if (typeof finishReason === 'string') {\n return finishReason;\n }\n return isRecord(finishReason) ? asString(finishReason.unified) : undefined;\n}\n\n/** Reads a token count that may be a plain number or a `{ total }` object (model-call usage). */\nfunction tokenCount(value: unknown): number | undefined {\n return asNumber(value) ?? (isRecord(value) ? asNumber(value.total) : undefined);\n}\n\nfunction buildOutputMessages(\n parts: Array<Record<string, unknown>>,\n finishReason: string | undefined,\n): string | undefined {\n if (!parts.length) {\n return undefined;\n }\n return safeStringify([{ role: 'assistant', parts, finish_reason: normalizeFinishReason(finishReason) }]);\n}\n\nfunction toolCallPart(toolCall: Record<string, unknown>): Record<string, unknown> {\n const args = toolCall.input ?? toolCall.args;\n return {\n type: 'tool_call',\n id: asString(toolCall.toolCallId),\n name: asString(toolCall.toolName),\n arguments: typeof args === 'string' ? args : safeStringify(args ?? {}),\n };\n}\n\nfunction partsFromContent(content: unknown[]): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n for (const item of content) {\n if (!isRecord(item)) {\n continue;\n }\n if (item.type === 'text' && typeof item.text === 'string') {\n parts.push({ type: 'text', content: item.text });\n } else if (item.type === 'tool-call') {\n parts.push(toolCallPart(item));\n }\n }\n return parts;\n}\n\nfunction partsFromTextAndToolCalls(text: unknown, toolCalls: unknown): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n if (typeof text === 'string' && text.length) {\n parts.push({ type: 'text', content: text });\n }\n if (Array.isArray(toolCalls)) {\n for (const toolCall of toolCalls) {\n if (isRecord(toolCall)) {\n parts.push(toolCallPart(toolCall));\n }\n }\n }\n return parts;\n}\n\nfunction captureToolError(span: Span, data: VercelAiChannelMessage, error: unknown): void {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: error instanceof Error ? error.message : 'tool_error',\n });\n\n const toolCall = isRecord(data.event.toolCall) ? data.event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(data.event.toolCallId) ?? asString(toolCall.toolCallId);\n\n withScope(scope => {\n scope.setContext('trace', spanToTraceContext(span));\n if (toolName) {\n scope.setTag('vercel.ai.tool.name', toolName);\n }\n if (toolCallId) {\n scope.setTag('vercel.ai.tool.callId', toolCallId);\n }\n scope.setLevel('error');\n captureException(\n error instanceof Error ? error : new Error(typeof error === 'string' ? error : 'Tool execution failed'),\n {\n mechanism: { type: 'auto.vercelai.channel', handled: false },\n },\n );\n });\n}\n\nfunction getRecordingOptions(\n event: Record<string, unknown>,\n channelOptions: VercelAiChannelOptions,\n): {\n recordInputs: boolean;\n recordOutputs: boolean;\n enableTruncation: boolean;\n} {\n const genAI = getClient()?.getDataCollectionOptions().genAI;\n\n return {\n recordInputs: resolveRecording(channelOptions.recordInputs, event.recordInputs, genAI?.inputs),\n recordOutputs: resolveRecording(channelOptions.recordOutputs, event.recordOutputs, genAI?.outputs),\n enableTruncation: shouldEnableTruncation(channelOptions.enableTruncation),\n };\n}\n\n/**\n * Mirrors the OTel integration's `determineRecordingSettings` precedence: an integration-level option\n * wins, then the per-call `experimental_telemetry.recordInputs/recordOutputs` flag the AI SDK forwards\n * on the channel event, then the global `dataCollection.genAI` default.\n *\n * NOTE: the OTel integration also defaults recording to `true` for a call with\n * `experimental_telemetry: { isEnabled: true }`. The `ai:telemetry` channel does not expose `isEnabled`\n * (nor a resolved recording flag), so that per-call default cannot be reproduced here — v7 users who\n * want inputs/outputs recorded must enable `dataCollection.genAI` or set `recordInputs`/`recordOutputs`.\n */\nfunction resolveRecording(integrationOption: unknown, perCallOption: unknown, globalDefault: unknown): boolean {\n if (typeof integrationOption === 'boolean') {\n return integrationOption;\n }\n if (typeof perCallOption === 'boolean') {\n return perCallOption;\n }\n return globalDefault === true;\n}\n\nfunction buildInputMessageAttributes(\n event: Record<string, unknown>,\n enableTruncation: boolean,\n): Record<string, string | number> {\n const attributes: Record<string, string | number> = {};\n\n // `ai` >= 7 forbids system messages in `messages`/`prompt` and exposes the system prompt as a\n // separate `instructions` field. The OTel path lifts the system message out of the prompt into\n // `gen_ai.system_instructions` as `[{ type: 'text', content }]`; mirror that shape here.\n const instructions = asString(event.instructions);\n if (instructions) {\n attributes[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE] = safeStringify([{ type: 'text', content: instructions }]);\n }\n\n // The AI SDK start events extend `StandardizedPrompt`; messages live on `messages`, otherwise the\n // simpler `prompt` field is used.\n const messages = event.messages ?? event.prompt;\n if (messages !== undefined) {\n attributes[GEN_AI_INPUT_MESSAGES] = enableTruncation ? getTruncatedJsonString(messages) : safeStringify(messages);\n // The original (pre-truncation) message count, so the product can show how many were dropped.\n attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE] = Array.isArray(messages) ? messages.length : 1;\n }\n\n return attributes;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && !isNaN(value) ? value : undefined;\n}\n\nfunction sum(a: number | undefined, b: number | undefined): number | undefined {\n return a === undefined && b === undefined ? undefined : (a ?? 0) + (b ?? 0);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return '[unserializable]';\n }\n}\n"],"names":["tracingChannel","bindTracingChannelToSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_SYSTEM","GEN_AI_REQUEST_MODEL","GEN_AI_EMBEDDINGS_INPUT","attributes","startInactiveSpan","GEN_AI_OPERATION_NAME","GEN_AI_INVOKE_AGENT_SPAN_OP","GEN_AI_RESPONSE_STREAMING","GEN_AI_FUNCTION_ID","GEN_AI_REQUEST_AVAILABLE_TOOLS","GEN_AI_EXECUTE_TOOL_SPAN_OP","GEN_AI_TOOL_TYPE","GEN_AI_TOOL_NAME","GEN_AI_TOOL_INPUT","GEN_AI_TOOL_OUTPUT","GEN_AI_USAGE_INPUT_TOKENS","GEN_AI_USAGE_OUTPUT_TOKENS","GEN_AI_USAGE_TOTAL_TOKENS","GEN_AI_RESPONSE_FINISH_REASONS","GEN_AI_RESPONSE_ID","GEN_AI_RESPONSE_MODEL","getProviderMetadataAttributes","GEN_AI_CONVERSATION_ID_ATTRIBUTE","spanToJSON","GEN_AI_OUTPUT_MESSAGES","SPAN_STATUS_ERROR","withScope","spanToTraceContext","captureException","getClient","shouldEnableTruncation","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_INPUT_MESSAGES","getTruncatedJsonString","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE"],"mappings":"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"}
{"version":3,"file":"vercel-ai-dc-subscriber.js","sources":["../../../src/vercel-ai/vercel-ai-dc-subscriber.ts"],"sourcesContent":["/* eslint-disable max-lines */\n// `@sentry/conventions` marks several gen_ai attributes (e.g. `GEN_AI_SYSTEM`, `GEN_AI_TOOL_*`,\n// `GEN_AI_REQUEST_AVAILABLE_TOOLS`) as deprecated in favour of newer semconv names. We intentionally\n// keep emitting the current names so these spans match the OTel-based (v6) integration and what the\n// Sentry product consumes today; migrating to the new names is a separate, coordinated change.\n/* eslint-disable typescript-eslint/no-deprecated */\nimport {\n GEN_AI_EMBEDDINGS_INPUT,\n GEN_AI_FUNCTION_ID,\n GEN_AI_INPUT_MESSAGES,\n GEN_AI_OPERATION_NAME,\n GEN_AI_OUTPUT_MESSAGES,\n GEN_AI_REQUEST_AVAILABLE_TOOLS,\n GEN_AI_REQUEST_MODEL,\n GEN_AI_RESPONSE_FINISH_REASONS,\n GEN_AI_RESPONSE_ID,\n GEN_AI_RESPONSE_MODEL,\n GEN_AI_RESPONSE_STREAMING,\n GEN_AI_SYSTEM,\n GEN_AI_TOOL_INPUT,\n GEN_AI_TOOL_NAME,\n GEN_AI_TOOL_OUTPUT,\n GEN_AI_TOOL_TYPE,\n GEN_AI_USAGE_INPUT_TOKENS,\n GEN_AI_USAGE_OUTPUT_TOKENS,\n GEN_AI_USAGE_TOTAL_TOKENS,\n} from '@sentry/conventions/attributes';\nimport { GEN_AI_EXECUTE_TOOL_SPAN_OP, GEN_AI_INVOKE_AGENT_SPAN_OP } from '@sentry/conventions/op';\nimport type { Span } from '@sentry/core';\nimport {\n captureException,\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n getClient,\n getProviderMetadataAttributes,\n getTruncatedJsonString,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n SPAN_STATUS_ERROR,\n spanToJSON,\n spanToTraceContext,\n startInactiveSpan,\n withScope,\n} from '@sentry/core';\nimport type { TracingChannel } from 'node:diagnostics_channel';\nimport { bindTracingChannelToSpan } from '../tracing-channel';\n\n/**\n * The single tracing channel the `ai` package (>= 7) publishes all telemetry lifecycle events to\n * via `node:diagnostics_channel`. Events are discriminated by their `type` field.\n * @see https://github.com/vercel/ai/pull/15660\n */\nconst AI_SDK_TELEMETRY_TRACING_CHANNEL = 'ai:telemetry';\n\nconst ORIGIN = 'auto.vercelai.channel';\n\n// `@sentry/conventions` does not expose these yet, so we keep the literals here.\nconst GEN_AI_TOOL_CALL_ID_ATTRIBUTE = 'gen_ai.tool.call.id';\nconst GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE = 'gen_ai.tool.description';\nconst GEN_AI_EMBEDDINGS_OPERATION = 'embeddings';\nconst GEN_AI_RERANK_OPERATION = 'rerank';\n// The model-call op matches the Vercel AI OTel integration (`gen_ai.generate_content`) rather than\n// the generic `gen_ai.chat`, so v6 (OTel) and v7 (channel) produce the same spans.\nconst GEN_AI_GENERATE_CONTENT_OPERATION = 'generate_content';\n\n// Subset of the `vercel.ai.*` passthrough attributes the OTel integration emits that we reproduce.\nconst VERCEL_AI_OPERATION_ID_ATTRIBUTE = 'vercel.ai.operationId';\nconst VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE = 'vercel.ai.model.provider';\nconst VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE = 'vercel.ai.settings.maxRetries';\n\n// Tracks the top-level operationId (and whether it streams) per `callId` so a model-call span can\n// name its `doGenerate`/`doStream` operation the same way the OTel integration does. `isStream` is\n// the authoritative event-type signal rather than a substring check on the (possibly custom)\n// operationId. Cleared when the top-level span ends.\nconst operationIdByCallId = new Map<string, { operationId: string; isStream: boolean }>();\n\n// Per-operation map of tool name → description, harvested from a model-call /\n// top-level event's `tools` (keyed by the shared `callId`). The AI SDK's\n// `executeTool` event doesn't carry the tool's description, so we backfill it\n// onto the tool span here — without relying on the OTel `vercelAiEventProcessor`\n// (which isn't registered in channel/orchestrion mode). Cleared with the\n// operation. Only populated when inputs are recorded, matching the OTel path\n// (which sources descriptions from the recorded `available_tools`).\nconst toolDescriptionsByCallId = new Map<string, Map<string, string>>();\n\n// Only top-level operations own the `callId` → operationId mapping; `step`/`languageModelCall`/\n// `executeTool` share the parent's `callId`, so they must not clear it.\nconst ROOT_OPERATION_TYPES = new Set<ChannelEventType>(['generateText', 'streamText', 'embed', 'embedMany', 'rerank']);\n\n/** Drop the per-operation `callId` maps once the owning top-level operation settles (success or error). */\nexport function clearOperationId(data: VercelAiChannelMessage): void {\n if (!ROOT_OPERATION_TYPES.has(data.type)) {\n return;\n }\n const callId = asString(data.event.callId);\n if (callId) {\n clearOperationCallId(callId);\n }\n}\n\n/**\n * Drop the per-operation `callId` maps for a single id. The v6 orchestrion adapter uses this to clear a\n * `streamText` operation only after its lazily-run model call settles — the operation's own span ends\n * synchronously (when `streamText` returns) but the model call runs later as the stream is consumed, and\n * it still needs the operation's `operationId`/`isStream` entry to name itself `ai.streamText.doStream`.\n */\nexport function clearOperationCallId(callId: string): void {\n operationIdByCallId.delete(callId);\n toolDescriptionsByCallId.delete(callId);\n}\n\n/** Record tool name → description from an event's `tools`, so tool spans can backfill the description. */\nfunction recordToolDescriptions(callId: string | undefined, tools: unknown): void {\n if (!callId || !Array.isArray(tools)) {\n return;\n }\n let descriptions = toolDescriptionsByCallId.get(callId);\n for (const tool of tools) {\n if (isRecord(tool) && typeof tool.name === 'string' && typeof tool.description === 'string') {\n descriptions = descriptions ?? new Map();\n if (!descriptions.has(tool.name)) {\n descriptions.set(tool.name, tool.description);\n }\n }\n }\n if (descriptions) {\n toolDescriptionsByCallId.set(callId, descriptions);\n }\n}\n\n/**\n * Resolve a tool's description, preferring the per-operation map (populated from the model-call /\n * top-level event's `tools`, v7) and falling back to a `tools` collection on the event itself —\n * which may be an array of `{ name, description }` or a record keyed by tool name (v6).\n */\nfunction resolveToolDescription(callId: string | undefined, toolName: string, tools: unknown): string | undefined {\n const fromMap = callId ? toolDescriptionsByCallId.get(callId)?.get(toolName) : undefined;\n if (fromMap) {\n return fromMap;\n }\n if (Array.isArray(tools)) {\n const match = tools.find(tool => isRecord(tool) && tool.name === toolName);\n return isRecord(match) ? asString(match.description) : undefined;\n }\n if (isRecord(tools)) {\n const tool = tools[toolName];\n return isRecord(tool) ? asString(tool.description) : undefined;\n }\n return undefined;\n}\n\n/** The lifecycle event types the `ai:telemetry` channel can carry. */\nexport type ChannelEventType =\n | 'generateText'\n | 'streamText'\n | 'step'\n | 'languageModelCall'\n | 'executeTool'\n | 'embed'\n | 'embedMany'\n | 'rerank';\n\n/**\n * The context object the AI SDK passes through one tracing-channel call. It is the same object\n * identity across `start`/`end`/`asyncEnd`/`error`, and Node's `tracingChannel` attaches\n * `result`/`error` to it as the traced promise settles.\n */\nexport interface VercelAiChannelMessage {\n type: ChannelEventType;\n event: Record<string, unknown>;\n result?: unknown;\n error?: unknown;\n}\n\n/**\n * Platform-provided factory that returns a tracing channel for the given channel name. The factory\n * is responsible for, when `start` fires, calling `transformStart(data)` and storing the returned\n * span on `data._sentrySpan` so the subscriber's `asyncEnd`/`error` handlers can read it.\n *\n * Node passes `@sentry/opentelemetry/tracing-channel`, which uses `bindStore` to additionally make\n * the span the active OTel context for the duration of the traced operation. That is what makes\n * nested AI SDK operations (model calls, tool calls) become children of the enclosing span without\n * any manual parent bookkeeping here.\n */\nexport type VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;\n\n/** Integration-level recording options, pinned at subscribe time so we never look the integration up per event. */\nexport interface VercelAiChannelOptions {\n recordInputs?: boolean;\n recordOutputs?: boolean;\n enableTruncation?: boolean;\n}\n\nlet subscribed = false;\n\n/**\n * Subscribe Sentry span handlers to the `ai` SDK's native telemetry tracing channel (`ai:telemetry`,\n * available in `ai` >= 7) and emit fully-formed `gen_ai.*` spans directly — no OpenTelemetry span\n * post-processing involved.\n *\n * The integration passes its options in directly (rather than us looking the integration up on every\n * event); the global `dataCollection.genAI` default is still read from the client per event.\n *\n * Safe to always call: on `ai` versions that don't publish to the channel (e.g. < 7) nothing is\n * ever emitted and this is inert, so there is no double-instrumentation against the OTel-based\n * patcher. Idempotent.\n */\nexport function subscribeVercelAiTracingChannel(\n tracingChannel: VercelAiTracingChannelFactory,\n options: VercelAiChannelOptions = {},\n): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n bindTracingChannelToSpan(\n tracingChannel<VercelAiChannelMessage>(AI_SDK_TELEMETRY_TRACING_CHANNEL),\n data => createSpanFromMessage(data, options),\n {\n // The helper ends the span; we enrich it from the settled result first (tokens, output messages,\n // finish reasons, response model/id, provider metadata) and drop the per-operation `callId` maps.\n beforeSpanEnd: (span, data) => {\n enrichSpanOnEnd(span, data, options);\n clearOperationId(data);\n },\n },\n );\n}\n\n/**\n * Transform a channel `start` payload into the span that should be active for the operation. For\n * `step` we deliberately don't open a span (model calls and tool calls are siblings under the\n * invoke_agent span, matching the OTel-based output), so we reuse the active span and mark the\n * payload to skip ending it.\n */\nexport function createSpanFromMessage(\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): Span | undefined {\n const { type, event } = data;\n\n if (type === 'step' || !event || typeof event !== 'object') {\n // Opt out: returning `undefined` leaves the enclosing `invoke_agent` span as the active context\n // (model-call and tool-call events nest under it) without opening — or ending — a span of its own.\n return undefined;\n }\n\n const { recordInputs, enableTruncation } = getRecordingOptions(event, channelOptions);\n const provider = asString(event.provider);\n const modelId = asString(event.modelId);\n const callId = asString(event.callId);\n const maxRetries = asNumber(event.maxRetries);\n\n // Harvest tool descriptions from the operation/model-call `tools` so tool spans can backfill them.\n // Gated on `recordInputs` to match the OTel path, which only records `available_tools` then.\n if (recordInputs) {\n recordToolDescriptions(callId, event.tools);\n }\n\n const baseAttributes: Record<string, string | number | boolean> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n ...(provider ? { [GEN_AI_SYSTEM]: provider, [VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE]: provider } : {}),\n ...(modelId ? { [GEN_AI_REQUEST_MODEL]: modelId } : {}),\n ...(maxRetries !== undefined ? { [VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE]: maxRetries } : {}),\n };\n\n switch (type) {\n case 'generateText':\n case 'streamText':\n return buildInvokeAgentSpan(event, baseAttributes, recordInputs, enableTruncation, callId, type === 'streamText');\n case 'languageModelCall':\n return buildModelCallSpan(event, baseAttributes, recordInputs, enableTruncation, callId, modelId);\n case 'executeTool':\n return buildToolSpan(event, recordInputs);\n case 'embed':\n case 'embedMany': {\n // `embed` carries a single `value`; `embedMany` a `values` array — both map to the embeddings input.\n const input = type === 'embedMany' ? event.values : event.value;\n return startGenAiSpan(GEN_AI_EMBEDDINGS_OPERATION, modelId, {\n ...baseAttributes,\n ...(recordInputs && input !== undefined ? { [GEN_AI_EMBEDDINGS_INPUT]: safeStringify(input) } : {}),\n });\n }\n case 'rerank':\n return startGenAiSpan(GEN_AI_RERANK_OPERATION, modelId, baseAttributes);\n default:\n // Unknown event type: opt out rather than open a span we can't shape correctly.\n return undefined;\n }\n}\n\ntype Attributes = Record<string, string | number | boolean>;\n\n/** Start a `gen_ai.<operation>` span named `<operation> <suffix>` (or just `<operation>` when no suffix). */\nfunction startGenAiSpan(operation: string, suffix: string | undefined, attributes: Attributes): Span {\n return startInactiveSpan({\n name: suffix ? `${operation} ${suffix}` : operation,\n op: `gen_ai.${operation}`,\n attributes: { [GEN_AI_OPERATION_NAME]: operation, ...attributes },\n });\n}\n\nfunction buildInvokeAgentSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n isStream: boolean,\n): Span {\n const functionId = asString(event.functionId);\n const operationId = asString(event.operationId) ?? (isStream ? 'ai.streamText' : 'ai.generateText');\n if (callId) {\n operationIdByCallId.set(callId, { operationId, isStream });\n }\n return startGenAiSpan(GEN_AI_INVOKE_AGENT_SPAN_OP, functionId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n [GEN_AI_RESPONSE_STREAMING]: isStream,\n ...(functionId ? { [GEN_AI_FUNCTION_ID]: functionId } : {}),\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n });\n}\n\nfunction buildModelCallSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n modelId: string | undefined,\n): Span {\n const parent = callId ? operationIdByCallId.get(callId) : undefined;\n const operationId = parent\n ? `${parent.operationId}.${parent.isStream ? 'doStream' : 'doGenerate'}`\n : 'ai.generateText.doGenerate';\n return startGenAiSpan(GEN_AI_GENERATE_CONTENT_OPERATION, modelId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n ...(recordInputs && Array.isArray(event.tools)\n ? { [GEN_AI_REQUEST_AVAILABLE_TOOLS]: safeStringify(event.tools) }\n : {}),\n });\n}\n\nfunction buildToolSpan(event: Record<string, unknown>, recordInputs: boolean): Span {\n const toolCall = isRecord(event.toolCall) ? event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(event.toolCallId) ?? asString(toolCall.toolCallId);\n const toolInput = toolCall.input ?? toolCall.args;\n // The `executeTool` event has no description; backfill it from the operation's recorded tools.\n // Gated on `recordInputs` to match the OTel path (descriptions come from the recorded tools list).\n const description =\n recordInputs && toolName ? resolveToolDescription(asString(event.callId), toolName, event.tools) : undefined;\n return startGenAiSpan(GEN_AI_EXECUTE_TOOL_SPAN_OP, toolName, {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [GEN_AI_TOOL_TYPE]: 'function',\n ...(toolName ? { [GEN_AI_TOOL_NAME]: toolName } : {}),\n ...(toolCallId ? { [GEN_AI_TOOL_CALL_ID_ATTRIBUTE]: toolCallId } : {}),\n ...(description ? { [GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE]: description } : {}),\n ...(recordInputs && toolInput !== undefined ? { [GEN_AI_TOOL_INPUT]: safeStringify(toolInput) } : {}),\n });\n}\n\n/**\n * Best-effort enrichment from the resolved value the AI SDK attaches to the channel context.\n * Everything here is guarded: when a field is missing or the shape differs across `ai` versions,\n * we simply don't set the attribute rather than emit a malformed span.\n */\nexport function enrichSpanOnEnd(\n span: Span,\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): void {\n const { type, result } = data;\n if (!isRecord(result)) {\n return;\n }\n\n const { recordOutputs } = getRecordingOptions(data.event, channelOptions);\n\n if (type === 'executeTool') {\n if (recordOutputs) {\n span.setAttribute(GEN_AI_TOOL_OUTPUT, safeStringify(result.output ?? result));\n }\n // From V5 on, tool errors are not rejected (so the `error` channel verb never fires) — they\n // surface as `tool-error` content on the resolved result. Mirror the OTel path by marking the\n // span and capturing the error.\n const output = isRecord(result.output) ? result.output : undefined;\n if (output?.type === 'tool-error') {\n captureToolError(span, data, output.error);\n }\n return;\n }\n\n // `languageModelCall` results report usage as `{ total }` objects; top-level/step results report\n // flat numbers. `tokenCount` handles both.\n const usage = isRecord(result.usage) ? result.usage : undefined;\n if (usage) {\n const inputTokens = tokenCount(usage.inputTokens) ?? tokenCount(usage.tokens);\n const outputTokens = tokenCount(usage.outputTokens);\n const totalTokens = tokenCount(usage.totalTokens) ?? sum(inputTokens, outputTokens);\n if (inputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n if (totalTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n }\n\n // Match the OTel integration: finish reasons live on the model-call (`generate_content`) span, not\n // on the top-level `invoke_agent` span.\n const finishReason = getFinishReason(result);\n if (finishReason && type === 'languageModelCall') {\n span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, safeStringify([finishReason]));\n }\n\n const response = isRecord(result.response) ? result.response : undefined;\n const responseId = asString(response?.id) ?? asString(result.responseId);\n if (responseId) {\n span.setAttribute(GEN_AI_RESPONSE_ID, responseId);\n }\n const responseModel = asString(response?.modelId) ?? asString(data.event.modelId);\n if (responseModel) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL, responseModel);\n }\n\n // Provider-specific cache/reasoning/prediction token breakdowns and `gen_ai.conversation.id`.\n // The channel exposes `providerMetadata` as an object (the OTel path parses it from a string);\n // both share `getProviderMetadataAttributes` so the emitted shape is identical.\n const providerMetadata = (result as { providerMetadata?: unknown }).providerMetadata;\n const providerAttributes = getProviderMetadataAttributes(providerMetadata);\n // Don't overwrite a conversation id already set on span start (e.g. by `conversationIdIntegration`\n // from a user-set scope value); the provider-derived id is only a fallback. Matches the OTel path.\n if (\n GEN_AI_CONVERSATION_ID_ATTRIBUTE in providerAttributes &&\n spanToJSON(span).data[GEN_AI_CONVERSATION_ID_ATTRIBUTE]\n ) {\n // oxlint-disable-next-line typescript/no-dynamic-delete\n delete providerAttributes[GEN_AI_CONVERSATION_ID_ATTRIBUTE];\n }\n span.setAttributes(providerAttributes);\n\n if (recordOutputs) {\n // `languageModelCall` exposes the response as a `content` parts array; top-level results expose\n // `text` + `toolCalls`. Both normalize into the OTel `gen_ai.output.messages` assistant message.\n const parts =\n type === 'languageModelCall' && Array.isArray(result.content)\n ? partsFromContent(result.content)\n : partsFromTextAndToolCalls(result.text, result.toolCalls);\n const outputMessages = buildOutputMessages(parts, finishReason);\n if (outputMessages) {\n span.setAttribute(GEN_AI_OUTPUT_MESSAGES, outputMessages);\n }\n }\n}\n\n/** Maps a Vercel AI finish reason to the OTel `gen_ai.output.messages` form (`tool-calls` → `tool_call`). */\nfunction normalizeFinishReason(finishReason: string | undefined): string {\n return finishReason === 'tool-calls' ? 'tool_call' : (finishReason ?? 'stop');\n}\n\n/** Reads the finish reason from a result — a string on top-level results, `{ unified }` on model calls. */\nfunction getFinishReason(result: Record<string, unknown>): string | undefined {\n const finishReason = result.finishReason;\n if (typeof finishReason === 'string') {\n return finishReason;\n }\n return isRecord(finishReason) ? asString(finishReason.unified) : undefined;\n}\n\n/** Reads a token count that may be a plain number or a `{ total }` object (model-call usage). */\nfunction tokenCount(value: unknown): number | undefined {\n return asNumber(value) ?? (isRecord(value) ? asNumber(value.total) : undefined);\n}\n\nfunction buildOutputMessages(\n parts: Array<Record<string, unknown>>,\n finishReason: string | undefined,\n): string | undefined {\n if (!parts.length) {\n return undefined;\n }\n return safeStringify([{ role: 'assistant', parts, finish_reason: normalizeFinishReason(finishReason) }]);\n}\n\nfunction toolCallPart(toolCall: Record<string, unknown>): Record<string, unknown> {\n const args = toolCall.input ?? toolCall.args;\n return {\n type: 'tool_call',\n id: asString(toolCall.toolCallId),\n name: asString(toolCall.toolName),\n arguments: typeof args === 'string' ? args : safeStringify(args ?? {}),\n };\n}\n\nfunction partsFromContent(content: unknown[]): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n for (const item of content) {\n if (!isRecord(item)) {\n continue;\n }\n if (item.type === 'text' && typeof item.text === 'string') {\n parts.push({ type: 'text', content: item.text });\n } else if (item.type === 'tool-call') {\n parts.push(toolCallPart(item));\n }\n }\n return parts;\n}\n\nfunction partsFromTextAndToolCalls(text: unknown, toolCalls: unknown): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n if (typeof text === 'string' && text.length) {\n parts.push({ type: 'text', content: text });\n }\n if (Array.isArray(toolCalls)) {\n for (const toolCall of toolCalls) {\n if (isRecord(toolCall)) {\n parts.push(toolCallPart(toolCall));\n }\n }\n }\n return parts;\n}\n\nfunction captureToolError(span: Span, data: VercelAiChannelMessage, error: unknown): void {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: error instanceof Error ? error.message : 'tool_error',\n });\n\n const toolCall = isRecord(data.event.toolCall) ? data.event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(data.event.toolCallId) ?? asString(toolCall.toolCallId);\n\n withScope(scope => {\n scope.setContext('trace', spanToTraceContext(span));\n if (toolName) {\n scope.setTag('vercel.ai.tool.name', toolName);\n }\n if (toolCallId) {\n scope.setTag('vercel.ai.tool.callId', toolCallId);\n }\n scope.setLevel('error');\n captureException(\n error instanceof Error ? error : new Error(typeof error === 'string' ? error : 'Tool execution failed'),\n {\n mechanism: { type: 'auto.vercelai.channel', handled: false },\n },\n );\n });\n}\n\nfunction getRecordingOptions(\n event: Record<string, unknown>,\n channelOptions: VercelAiChannelOptions,\n): {\n recordInputs: boolean;\n recordOutputs: boolean;\n enableTruncation: boolean;\n} {\n const genAI = getClient()?.getDataCollectionOptions().genAI;\n\n return {\n recordInputs: resolveRecording(channelOptions.recordInputs, event.recordInputs, genAI?.inputs),\n recordOutputs: resolveRecording(channelOptions.recordOutputs, event.recordOutputs, genAI?.outputs),\n enableTruncation: shouldEnableTruncation(channelOptions.enableTruncation),\n };\n}\n\n/**\n * Mirrors the OTel integration's `determineRecordingSettings` precedence: an integration-level option\n * wins, then the per-call `experimental_telemetry.recordInputs/recordOutputs` flag the AI SDK forwards\n * on the channel event, then the global `dataCollection.genAI` default.\n *\n * NOTE: the OTel integration also defaults recording to `true` for a call with\n * `experimental_telemetry: { isEnabled: true }`. The `ai:telemetry` channel does not expose `isEnabled`\n * (nor a resolved recording flag), so that per-call default cannot be reproduced here — v7 users who\n * want inputs/outputs recorded must enable `dataCollection.genAI` or set `recordInputs`/`recordOutputs`.\n */\nfunction resolveRecording(integrationOption: unknown, perCallOption: unknown, globalDefault: unknown): boolean {\n if (typeof integrationOption === 'boolean') {\n return integrationOption;\n }\n if (typeof perCallOption === 'boolean') {\n return perCallOption;\n }\n return globalDefault === true;\n}\n\nfunction buildInputMessageAttributes(\n event: Record<string, unknown>,\n enableTruncation: boolean,\n): Record<string, string | number> {\n const attributes: Record<string, string | number> = {};\n\n // `ai` >= 7 forbids system messages in `messages`/`prompt` and exposes the system prompt as a\n // separate `instructions` field. The OTel path lifts the system message out of the prompt into\n // `gen_ai.system_instructions` as `[{ type: 'text', content }]`; mirror that shape here.\n const instructions = asString(event.instructions);\n if (instructions) {\n attributes[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE] = safeStringify([{ type: 'text', content: instructions }]);\n }\n\n // The AI SDK start events extend `StandardizedPrompt`; messages live on `messages`, otherwise the\n // simpler `prompt` field is used.\n const messages = event.messages ?? event.prompt;\n if (messages !== undefined) {\n attributes[GEN_AI_INPUT_MESSAGES] = enableTruncation ? getTruncatedJsonString(messages) : safeStringify(messages);\n // The original (pre-truncation) message count, so the product can show how many were dropped.\n attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE] = Array.isArray(messages) ? messages.length : 1;\n }\n\n return attributes;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && !isNaN(value) ? value : undefined;\n}\n\nfunction sum(a: number | undefined, b: number | undefined): number | undefined {\n return a === undefined && b === undefined ? undefined : (a ?? 0) + (b ?? 0);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return '[unserializable]';\n }\n}\n"],"names":["tracingChannel","bindTracingChannelToSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_SYSTEM","GEN_AI_REQUEST_MODEL","GEN_AI_EMBEDDINGS_INPUT","attributes","startInactiveSpan","GEN_AI_OPERATION_NAME","GEN_AI_INVOKE_AGENT_SPAN_OP","GEN_AI_RESPONSE_STREAMING","GEN_AI_FUNCTION_ID","GEN_AI_REQUEST_AVAILABLE_TOOLS","GEN_AI_EXECUTE_TOOL_SPAN_OP","GEN_AI_TOOL_TYPE","GEN_AI_TOOL_NAME","GEN_AI_TOOL_INPUT","GEN_AI_TOOL_OUTPUT","GEN_AI_USAGE_INPUT_TOKENS","GEN_AI_USAGE_OUTPUT_TOKENS","GEN_AI_USAGE_TOTAL_TOKENS","GEN_AI_RESPONSE_FINISH_REASONS","GEN_AI_RESPONSE_ID","GEN_AI_RESPONSE_MODEL","getProviderMetadataAttributes","GEN_AI_CONVERSATION_ID_ATTRIBUTE","spanToJSON","GEN_AI_OUTPUT_MESSAGES","SPAN_STATUS_ERROR","withScope","spanToTraceContext","captureException","getClient","shouldEnableTruncation","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_INPUT_MESSAGES","getTruncatedJsonString","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE"],"mappings":"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"}

@@ -0,2 +1,4 @@

export { mongooseIntegration } from './mongoose/index.js';
export { IOREDIS_DC_CHANNEL_COMMAND, IOREDIS_DC_CHANNEL_CONNECT, REDIS_DC_CHANNEL_BATCH, REDIS_DC_CHANNEL_COMMAND, REDIS_DC_CHANNEL_CONNECT, subscribeRedisDiagnosticChannels } from './redis/redis-dc-subscriber.js';
export { defaultDbStatementSerializer } from './redis/redis-statement-serializer.js';
export { bindTracingChannelToSpan } from './tracing-channel.js';

@@ -3,0 +5,0 @@ export { vercelAiIntegration } from './vercel-ai/index.js';

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { defineIntegration, debug, waitForTracingChannelBinding, bindScopeToEmitter, getCurrentScope, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { defineIntegration, debug, waitForTracingChannelBinding, getCurrentScope, startInactiveSpan, SPAN_KIND, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, bindScopeToEmitter } from '@sentry/core';
import { DEBUG_BUILD } from '../../debug-build.js';

@@ -34,2 +34,3 @@ import { CHANNELS } from '../../orchestrion/channels.js';

name: sql ?? "mysql.query",
kind: SPAN_KIND.CLIENT,
op: "db",

@@ -36,0 +37,0 @@ attributes: {

@@ -1,1 +0,1 @@

{"version":3,"file":"mysql.js","sources":["../../../../src/integrations/tracing-channel/mysql.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, Scope } from '@sentry/core';\nimport {\n bindScopeToEmitter,\n debug,\n defineIntegration,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// NOTE: this uses the same name as the OTel integration by design.\n// When enabled, OTel 'Mysql' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Mysql' as const;\n\n// OTel \"OLD\" db/net semantic-conventions, inlined to keep this integration free of OTel deps. Matches\n// `@opentelemetry/instrumentation-mysql`'s default and the SDK's `inferDbSpanData` (which renames spans\n// off `db.statement`).\nconst ATTR_DB_SYSTEM = 'db.system';\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nconst ATTR_DB_NAME = 'db.name';\nconst ATTR_DB_USER = 'db.user';\nconst ATTR_DB_STATEMENT = 'db.statement';\nconst ATTR_NET_PEER_NAME = 'net.peer.name';\nconst ATTR_NET_PEER_PORT = 'net.peer.port';\n\n/**\n * The shape orchestrion's transform attaches to the tracing-channel `context` object. Documented here\n * rather than imported because orchestrion's runtime doesn't export it.\n */\ninterface MysqlQueryChannelContext {\n // The live args array passed to the wrapped `connection.query` call; `arguments[0]` is the SQL.\n arguments: unknown[];\n self?: MysqlConnection;\n moduleVersion?: string;\n result?: unknown;\n error?: unknown;\n // The caller's scope, captured at `start` and replayed onto the streamed `Query` emitter (see below).\n _sentryCallerScope?: Scope;\n}\n\ninterface MysqlConnectionConfig {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n // Pool connections nest the real config one level deeper.\n connectionConfig?: MysqlConnectionConfig;\n}\n\ninterface MysqlConnection {\n config?: MysqlConnectionConfig;\n}\n\nconst _mysqlChannelIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19 so do nothing in that case.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`[orchestrion:mysql] subscribing to channel \"${CHANNELS.MYSQL_QUERY}\"`);\n\n waitForTracingChannelBinding(() => {\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<MysqlQueryChannelContext>(CHANNELS.MYSQL_QUERY),\n data => {\n const sql = extractSql(data.arguments[0]);\n const { host, port, database, user } = getConnectionConfig(data.self);\n const portNumber = typeof port === 'string' ? parseInt(port, 10) : port;\n const portIsNumber = typeof portNumber === 'number' && !isNaN(portNumber);\n\n // For the streamed path: mysql emits the `Query` emitter's events from its socket data\n // handler with the caller's context lost. `deferSpanEnd` replays this scope onto the emitter.\n data._sentryCallerScope = getCurrentScope();\n\n return startInactiveSpan({\n name: sql ?? 'mysql.query',\n op: 'db',\n attributes: {\n [ATTR_DB_SYSTEM]: 'mysql',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.orchestrion.mysql',\n [ATTR_DB_CONNECTION_STRING]: getJDBCString(host, portIsNumber ? portNumber : undefined, database),\n ...(database ? { [ATTR_DB_NAME]: database } : {}),\n ...(user ? { [ATTR_DB_USER]: user } : {}),\n ...(sql ? { [ATTR_DB_STATEMENT]: sql } : {}),\n ...(host ? { [ATTR_NET_PEER_NAME]: host } : {}),\n ...(portIsNumber ? { [ATTR_NET_PEER_PORT]: portNumber } : {}),\n },\n });\n },\n {\n // No-callback `query(sql)` returns a streamable `Query` emitter as `result`; it settles on the\n // emitter's `'end'`/`'error'`, not the channel, so defer ending to those.\n deferSpanEnd({ data, end }) {\n const result = data.result;\n if (!result || typeof result !== 'object' || !hasOnMethod(result)) {\n return false;\n }\n\n // Replay the caller's scope so user listeners on the emitter nest under it, not a new trace.\n const callerScope = data._sentryCallerScope;\n if (callerScope) {\n bindScopeToEmitter(result, callerScope);\n }\n\n result.on('error', err => end(err));\n result.on('end', () => end());\n\n return true;\n },\n },\n );\n });\n },\n };\n}) satisfies IntegrationFn;\n\nfunction hasOnMethod(obj: object): obj is { on: (event: string, listener: (arg?: unknown) => void) => unknown } {\n return 'on' in obj && typeof (obj as { on?: unknown }).on === 'function';\n}\n\nfunction extractSql(firstArg: unknown): string | undefined {\n if (typeof firstArg === 'string') {\n return firstArg;\n }\n if (firstArg && typeof firstArg === 'object' && 'sql' in firstArg) {\n const sql = (firstArg as { sql?: unknown }).sql;\n return typeof sql === 'string' ? sql : undefined;\n }\n return undefined;\n}\n\nfunction getConnectionConfig(connection: MysqlConnection | undefined): {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n} {\n // Pool connections nest the real config under `.connectionConfig`; single\n // connections expose it directly. Matches `@opentelemetry/instrumentation-mysql`.\n const config = connection?.config?.connectionConfig ?? connection?.config ?? {};\n return {\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n };\n}\n\nfunction getJDBCString(host: string | undefined, port: number | undefined, database: string | undefined): string {\n let s = `jdbc:mysql://${host || 'localhost'}`;\n if (typeof port === 'number') {\n s += `:${port}`;\n }\n if (database) {\n s += `/${database}`;\n }\n return s;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven mysql integration.\n *\n * Subscribes to the `orchestrion:mysql:query` diagnostics_channel that the\n * orchestrion code transform injects into `mysql/lib/Connection.js`'s\n * `Connection.prototype.query`. Requires the orchestrion runtime hook or\n * bundler plugin to be active — wire that up via `_experimentalSetupOrchestrion`.\n */\nexport const mysqlChannelIntegration = defineIntegration(_mysqlChannelIntegration);\n"],"names":[],"mappings":"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"}
{"version":3,"file":"mysql.js","sources":["../../../../src/integrations/tracing-channel/mysql.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { IntegrationFn, Scope } from '@sentry/core';\nimport {\n bindScopeToEmitter,\n debug,\n defineIntegration,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n startInactiveSpan,\n waitForTracingChannelBinding,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { CHANNELS } from '../../orchestrion/channels';\nimport { bindTracingChannelToSpan } from '../../tracing-channel';\n\n// NOTE: this uses the same name as the OTel integration by design.\n// When enabled, OTel 'Mysql' integration is omitted from the default set.\nconst INTEGRATION_NAME = 'Mysql' as const;\n\n// OTel \"OLD\" db/net semantic-conventions, inlined to keep this integration free of OTel deps. Matches\n// `@opentelemetry/instrumentation-mysql`'s default and the SDK's `inferDbSpanData` (which renames spans\n// off `db.statement`).\nconst ATTR_DB_SYSTEM = 'db.system';\nconst ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nconst ATTR_DB_NAME = 'db.name';\nconst ATTR_DB_USER = 'db.user';\nconst ATTR_DB_STATEMENT = 'db.statement';\nconst ATTR_NET_PEER_NAME = 'net.peer.name';\nconst ATTR_NET_PEER_PORT = 'net.peer.port';\n\n/**\n * The shape orchestrion's transform attaches to the tracing-channel `context` object. Documented here\n * rather than imported because orchestrion's runtime doesn't export it.\n */\ninterface MysqlQueryChannelContext {\n // The live args array passed to the wrapped `connection.query` call; `arguments[0]` is the SQL.\n arguments: unknown[];\n self?: MysqlConnection;\n moduleVersion?: string;\n result?: unknown;\n error?: unknown;\n // The caller's scope, captured at `start` and replayed onto the streamed `Query` emitter (see below).\n _sentryCallerScope?: Scope;\n}\n\ninterface MysqlConnectionConfig {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n // Pool connections nest the real config one level deeper.\n connectionConfig?: MysqlConnectionConfig;\n}\n\ninterface MysqlConnection {\n config?: MysqlConnectionConfig;\n}\n\nconst _mysqlChannelIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // `tracingChannel` is unavailable before Node 18.19 so do nothing in that case.\n if (!diagnosticsChannel.tracingChannel) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`[orchestrion:mysql] subscribing to channel \"${CHANNELS.MYSQL_QUERY}\"`);\n\n waitForTracingChannelBinding(() => {\n bindTracingChannelToSpan(\n diagnosticsChannel.tracingChannel<MysqlQueryChannelContext>(CHANNELS.MYSQL_QUERY),\n data => {\n const sql = extractSql(data.arguments[0]);\n const { host, port, database, user } = getConnectionConfig(data.self);\n const portNumber = typeof port === 'string' ? parseInt(port, 10) : port;\n const portIsNumber = typeof portNumber === 'number' && !isNaN(portNumber);\n\n // For the streamed path: mysql emits the `Query` emitter's events from its socket data\n // handler with the caller's context lost. `deferSpanEnd` replays this scope onto the emitter.\n data._sentryCallerScope = getCurrentScope();\n\n return startInactiveSpan({\n name: sql ?? 'mysql.query',\n kind: SPAN_KIND.CLIENT,\n op: 'db',\n attributes: {\n [ATTR_DB_SYSTEM]: 'mysql',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.orchestrion.mysql',\n [ATTR_DB_CONNECTION_STRING]: getJDBCString(host, portIsNumber ? portNumber : undefined, database),\n ...(database ? { [ATTR_DB_NAME]: database } : {}),\n ...(user ? { [ATTR_DB_USER]: user } : {}),\n ...(sql ? { [ATTR_DB_STATEMENT]: sql } : {}),\n ...(host ? { [ATTR_NET_PEER_NAME]: host } : {}),\n ...(portIsNumber ? { [ATTR_NET_PEER_PORT]: portNumber } : {}),\n },\n });\n },\n {\n // No-callback `query(sql)` returns a streamable `Query` emitter as `result`; it settles on the\n // emitter's `'end'`/`'error'`, not the channel, so defer ending to those.\n deferSpanEnd({ data, end }) {\n const result = data.result;\n if (!result || typeof result !== 'object' || !hasOnMethod(result)) {\n return false;\n }\n\n // Replay the caller's scope so user listeners on the emitter nest under it, not a new trace.\n const callerScope = data._sentryCallerScope;\n if (callerScope) {\n bindScopeToEmitter(result, callerScope);\n }\n\n result.on('error', err => end(err));\n result.on('end', () => end());\n\n return true;\n },\n },\n );\n });\n },\n };\n}) satisfies IntegrationFn;\n\nfunction hasOnMethod(obj: object): obj is { on: (event: string, listener: (arg?: unknown) => void) => unknown } {\n return 'on' in obj && typeof (obj as { on?: unknown }).on === 'function';\n}\n\nfunction extractSql(firstArg: unknown): string | undefined {\n if (typeof firstArg === 'string') {\n return firstArg;\n }\n if (firstArg && typeof firstArg === 'object' && 'sql' in firstArg) {\n const sql = (firstArg as { sql?: unknown }).sql;\n return typeof sql === 'string' ? sql : undefined;\n }\n return undefined;\n}\n\nfunction getConnectionConfig(connection: MysqlConnection | undefined): {\n host?: string;\n port?: number | string;\n database?: string;\n user?: string;\n} {\n // Pool connections nest the real config under `.connectionConfig`; single\n // connections expose it directly. Matches `@opentelemetry/instrumentation-mysql`.\n const config = connection?.config?.connectionConfig ?? connection?.config ?? {};\n return {\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n };\n}\n\nfunction getJDBCString(host: string | undefined, port: number | undefined, database: string | undefined): string {\n let s = `jdbc:mysql://${host || 'localhost'}`;\n if (typeof port === 'number') {\n s += `:${port}`;\n }\n if (database) {\n s += `/${database}`;\n }\n return s;\n}\n\n/**\n * EXPERIMENTAL — orchestrion-driven mysql integration.\n *\n * Subscribes to the `orchestrion:mysql:query` diagnostics_channel that the\n * orchestrion code transform injects into `mysql/lib/Connection.js`'s\n * `Connection.prototype.query`. Requires the orchestrion runtime hook or\n * bundler plugin to be active — wire that up via `_experimentalSetupOrchestrion`.\n */\nexport const mysqlChannelIntegration = defineIntegration(_mysqlChannelIntegration);\n"],"names":[],"mappings":"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"}
import codeTransformer from '@apm-js-collab/code-transformer-bundler-plugins/vite';
import MagicString from 'magic-string';
import { SENTRY_INSTRUMENTATIONS, INSTRUMENTED_MODULE_NAMES } from '../config.js';
import { SENTRY_INSTRUMENTATIONS, INSTRUMENTED_MODULE_NAMES } from '../config/index.js';

@@ -5,0 +5,0 @@ function sentryOrchestrionPlugin() {

@@ -0,4 +1,19 @@

import { mysqlChannels } from './config/mysql.js';
import { lruMemoizerChannels } from './config/lru-memoizer.js';
import { ioredisChannels } from './config/ioredis.js';
import { pgChannels } from './config/pg.js';
import { openaiChannels } from './config/openai.js';
import { anthropicAiChannels } from './config/anthropic-ai.js';
import { vercelAiChannels } from './config/vercel-ai.js';
import { hapiChannels } from './config/hapi.js';
const CHANNELS = {
MYSQL_QUERY: "orchestrion:mysql:query",
LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load"
...mysqlChannels,
...lruMemoizerChannels,
...ioredisChannels,
...pgChannels,
...openaiChannels,
...anthropicAiChannels,
...vercelAiChannels,
...hapiChannels
};

@@ -5,0 +20,0 @@

@@ -1,1 +0,1 @@

{"version":3,"file":"channels.js","sources":["../../../src/orchestrion/channels.ts"],"sourcesContent":["/**\n * Fully-qualified `diagnostics_channel` names that orchestrion publishes to.\n *\n * Orchestrion's transform always prefixes the configured `channelName` with\n * `orchestrion:${module.name}:`. So a config of\n * `{ channelName: 'query', module: { name: 'mysql' } }`\n * publishes to `orchestrion:mysql:query`.\n *\n * Subscribers (`integrations/<lib>/tracing-channel.ts`) consume the full\n * prefixed string from this map; the config files set only the unprefixed\n * suffix in `channelName`. Keeping both pieces in one file is what guarantees\n * they don't drift apart and silently stop firing.\n */\nexport const CHANNELS = {\n MYSQL_QUERY: 'orchestrion:mysql:query',\n LRU_MEMOIZER_LOAD: 'orchestrion:lru-memoizer:load',\n} as const;\n\nexport type ChannelName = (typeof CHANNELS)[keyof typeof CHANNELS];\n"],"names":[],"mappings":"AAaO,MAAM,QAAA,GAAW;AAAA,EACtB,WAAA,EAAa,yBAAA;AAAA,EACb,iBAAA,EAAmB;AACrB;;;;"}
{"version":3,"file":"channels.js","sources":["../../../src/orchestrion/channels.ts"],"sourcesContent":["import { mysqlChannels } from './config/mysql';\nimport { lruMemoizerChannels } from './config/lru-memoizer';\nimport { ioredisChannels } from './config/ioredis';\nimport { pgChannels } from './config/pg';\nimport { openaiChannels } from './config/openai';\nimport { anthropicAiChannels } from './config/anthropic-ai';\nimport { vercelAiChannels } from './config/vercel-ai';\nimport { hapiChannels } from './config/hapi';\n\n/**\n * Fully-qualified `diagnostics_channel` names that orchestrion publishes to.\n *\n * Orchestrion's transform always prefixes the configured `channelName` with\n * `orchestrion:${module.name}:`. So a config of\n * `{ channelName: 'query', module: { name: 'mysql' } }`\n * publishes to `orchestrion:mysql:query`.\n *\n * Subscribers (`integrations/<lib>/tracing-channel.ts`) consume the full\n * prefixed string from this map; the config files set only the unprefixed\n * suffix in `channelName`. Keeping both pieces in one file is what guarantees\n * they don't drift apart and silently stop firing.\n */\nexport const CHANNELS = {\n ...mysqlChannels,\n ...lruMemoizerChannels,\n ...ioredisChannels,\n ...pgChannels,\n ...openaiChannels,\n ...anthropicAiChannels,\n ...vercelAiChannels,\n ...hapiChannels,\n} as const;\n\nexport type ChannelName = (typeof CHANNELS)[keyof typeof CHANNELS];\n"],"names":[],"mappings":";;;;;;;;;AAsBO,MAAM,QAAA,GAAW;AAAA,EACtB,GAAG,aAAA;AAAA,EACH,GAAG,mBAAA;AAAA,EACH,GAAG,eAAA;AAAA,EACH,GAAG,UAAA;AAAA,EACH,GAAG,cAAA;AAAA,EACH,GAAG,mBAAA;AAAA,EACH,GAAG,gBAAA;AAAA,EACH,GAAG;AACL;;;;"}
import { debug } from '@sentry/core';
import { DEBUG_BUILD } from '../debug-build.js';
function isOrchestrionInjected() {
const marker = globalThis.__SENTRY_ORCHESTRION__;
return !!(marker?.runtime || marker?.bundler);
}
function detectOrchestrionSetup() {

@@ -10,3 +14,3 @@ if (!DEBUG_BUILD) return;

DEBUG_BUILD && debug.log(`[orchestrion] detect: runtime=${runtime} bundler=${bundler}`);
if (!runtime && !bundler) {
if (!isOrchestrionInjected()) {
DEBUG_BUILD && debug.warn(

@@ -18,3 +22,3 @@ "[Sentry] No diagnostics-channel injection detected. Channel-based integrations (mysql, \u2026) will not record spans. Make sure the diagnostics channels are injected via the runtime `--import` hook or a bundler plugin before the instrumented modules load."

export { detectOrchestrionSetup };
export { detectOrchestrionSetup, isOrchestrionInjected };
//# sourceMappingURL=detect.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"detect.js","sources":["../../../src/orchestrion/detect.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Verifies that the diagnostics channels have been injected either by the\n * runtime `--import` hook (or init-time registration), a bundler plugin, or\n * both, and warns if not.\n *\n * Both injectors being active at once is fine: they operate on disjoint module\n * sets (a module is either loaded through Node's loader and transformed by the\n * runtime hook, or inlined by the bundler and transformed by the plugin), so\n * a single module can't be double-wrapped. A hybrid setup, with some deps\n * external and runtime-instrumented, others bundled and plugin-instrumented,\n * is fine.\n *\n * Note: intentionally does NOT warn in production, only in debug builds,\n * because production warnings are reserved for truly critical issues.\n */\nexport function detectOrchestrionSetup(): void {\n if (!DEBUG_BUILD) return;\n\n const marker = globalThis.__SENTRY_ORCHESTRION__;\n const runtime = !!marker?.runtime;\n const bundler = !!marker?.bundler;\n\n DEBUG_BUILD && debug.log(`[orchestrion] detect: runtime=${runtime} bundler=${bundler}`);\n\n if (!runtime && !bundler) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] No diagnostics-channel injection detected. Channel-based integrations ' +\n '(mysql, …) will not record spans. Make sure the diagnostics channels are injected ' +\n 'via the runtime `--import` hook or a bundler plugin before the instrumented modules load.',\n );\n }\n}\n"],"names":[],"mappings":";;;AAuBO,SAAS,sBAAA,GAA+B;AAC7C,EAAA,IAAI,CAAC,WAAA,EAAa;AAElB,EAAA,MAAM,SAAS,UAAA,CAAW,sBAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAE1B,EAAA,WAAA,IAAe,MAAM,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAEtF,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,EAAS;AACxB,IAAA,WAAA,IACE,KAAA,CAAM,IAAA;AAAA,MACJ;AAAA,KAGF;AAAA,EACJ;AACF;;;;"}
{"version":3,"file":"detect.js","sources":["../../../src/orchestrion/detect.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Whether orchestrion has injected the diagnostics channels into this process,\n * either by the runtime `--import` hook / init-time registration (`runtime`)\n * or a bundler plugin (`bundler`). Both injectors set a flag on the\n * `globalThis.__SENTRY_ORCHESTRION__` marker.\n *\n * Use this to avoid wiring up channel-subscriber integrations when nothing\n * will ever publish to those channels.\n */\nexport function isOrchestrionInjected(): boolean {\n const marker = globalThis.__SENTRY_ORCHESTRION__;\n return !!(marker?.runtime || marker?.bundler);\n}\n\n/**\n * Verifies that the diagnostics channels have been injected either by the\n * runtime `--import` hook (or init-time registration), a bundler plugin, or\n * both, and warns if not.\n *\n * Both injectors being active at once is fine: they operate on disjoint module\n * sets (a module is either loaded through Node's loader and transformed by the\n * runtime hook, or inlined by the bundler and transformed by the plugin), so\n * a single module can't be double-wrapped. A hybrid setup, with some deps\n * external and runtime-instrumented, others bundled and plugin-instrumented,\n * is fine.\n *\n * Note: intentionally does NOT warn in production, only in debug builds,\n * because production warnings are reserved for truly critical issues.\n */\nexport function detectOrchestrionSetup(): void {\n if (!DEBUG_BUILD) return;\n\n const marker = globalThis.__SENTRY_ORCHESTRION__;\n const runtime = !!marker?.runtime;\n const bundler = !!marker?.bundler;\n\n DEBUG_BUILD && debug.log(`[orchestrion] detect: runtime=${runtime} bundler=${bundler}`);\n\n if (!isOrchestrionInjected()) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] No diagnostics-channel injection detected. Channel-based integrations ' +\n '(mysql, …) will not record spans. Make sure the diagnostics channels are injected ' +\n 'via the runtime `--import` hook or a bundler plugin before the instrumented modules load.',\n );\n }\n}\n"],"names":[],"mappings":";;;AAiBO,SAAS,qBAAA,GAAiC;AAC/C,EAAA,MAAM,SAAS,UAAA,CAAW,sBAAA;AAC1B,EAAA,OAAO,CAAC,EAAE,MAAA,EAAQ,OAAA,IAAW,MAAA,EAAQ,OAAA,CAAA;AACvC;AAiBO,SAAS,sBAAA,GAA+B;AAC7C,EAAA,IAAI,CAAC,WAAA,EAAa;AAElB,EAAA,MAAM,SAAS,UAAA,CAAW,sBAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,MAAA,EAAQ,OAAA;AAE1B,EAAA,WAAA,IAAe,MAAM,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAEtF,EAAA,IAAI,CAAC,uBAAsB,EAAG;AAC5B,IAAA,WAAA,IACE,KAAA,CAAM,IAAA;AAAA,MACJ;AAAA,KAGF;AAAA,EACJ;AACF;;;;"}

@@ -1,4 +0,22 @@

export { detectOrchestrionSetup } from './detect.js';
export { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql.js';
export { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer.js';
import { anthropicChannelIntegration } from '../integrations/tracing-channel/anthropic.js';
import { hapiChannelIntegration } from '../integrations/tracing-channel/hapi.js';
export { ioredisChannelIntegration } from '../integrations/tracing-channel/ioredis.js';
import { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer.js';
import { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql.js';
import { openaiChannelIntegration } from '../integrations/tracing-channel/openai.js';
import { postgresChannelIntegration } from '../integrations/tracing-channel/postgres.js';
import { vercelAiChannelIntegration } from '../integrations/tracing-channel/vercel-ai.js';
export { detectOrchestrionSetup, isOrchestrionInjected } from './detect.js';
const channelIntegrations = {
postgresIntegration: postgresChannelIntegration,
mysqlIntegration: mysqlChannelIntegration,
lruMemoizerIntegration: lruMemoizerChannelIntegration,
openaiIntegration: openaiChannelIntegration,
anthropicIntegration: anthropicChannelIntegration,
vercelAiIntegration: vercelAiChannelIntegration,
hapiIntegration: hapiChannelIntegration
};
export { anthropicChannelIntegration, channelIntegrations, hapiChannelIntegration, lruMemoizerChannelIntegration, mysqlChannelIntegration, openaiChannelIntegration, postgresChannelIntegration, vercelAiChannelIntegration };
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
{"version":3,"file":"index.js","sources":["../../../src/orchestrion/index.ts"],"sourcesContent":["import { anthropicChannelIntegration } from '../integrations/tracing-channel/anthropic';\nimport { hapiChannelIntegration } from '../integrations/tracing-channel/hapi';\nimport { ioredisChannelIntegration } from '../integrations/tracing-channel/ioredis';\nimport { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer';\nimport { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql';\nimport { openaiChannelIntegration } from '../integrations/tracing-channel/openai';\nimport { postgresChannelIntegration } from '../integrations/tracing-channel/postgres';\nimport { vercelAiChannelIntegration } from '../integrations/tracing-channel/vercel-ai';\n\nexport { detectOrchestrionSetup, isOrchestrionInjected } from './detect';\nexport {\n anthropicChannelIntegration,\n hapiChannelIntegration,\n ioredisChannelIntegration,\n lruMemoizerChannelIntegration,\n mysqlChannelIntegration,\n openaiChannelIntegration,\n postgresChannelIntegration,\n vercelAiChannelIntegration,\n};\nexport type { IORedisChannelIntegrationOptions, IORedisResponseHook } from '../integrations/tracing-channel/ioredis';\n\n/**\n * The canonical set of orchestrion diagnostics-channel integrations, keyed by their public\n * (OTel-parity) factory name.\n *\n * Single source of truth: add a new channel integration here and every consumer — the `@sentry/node`\n * opt-in helper (`experimentalUseDiagnosticsChannelInjection`) and its public\n * `diagnosticsChannelInjectionIntegrations()` map — picks it up automatically, so there's no separate\n * list to keep in sync.\n *\n * NOTE: `ioredisChannelIntegration` is intentionally NOT here. It only partially replaces the\n * composite OTel `Redis` integration and needs the node SDK's redis cache `responseHook` (which\n * can't live in `server-utils`), so `@sentry/node` wires it up separately.\n */\nexport const channelIntegrations = {\n postgresIntegration: postgresChannelIntegration,\n mysqlIntegration: mysqlChannelIntegration,\n lruMemoizerIntegration: lruMemoizerChannelIntegration,\n openaiIntegration: openaiChannelIntegration,\n anthropicIntegration: anthropicChannelIntegration,\n vercelAiIntegration: vercelAiChannelIntegration,\n hapiIntegration: hapiChannelIntegration,\n} as const;\n"],"names":[],"mappings":";;;;;;;;;;AAmCO,MAAM,mBAAA,GAAsB;AAAA,EACjC,mBAAA,EAAqB,0BAAA;AAAA,EACrB,gBAAA,EAAkB,uBAAA;AAAA,EAClB,sBAAA,EAAwB,6BAAA;AAAA,EACxB,iBAAA,EAAmB,wBAAA;AAAA,EACnB,oBAAA,EAAsB,2BAAA;AAAA,EACtB,mBAAA,EAAqB,0BAAA;AAAA,EACrB,eAAA,EAAiB;AACnB;;;;"}
import { debug } from '@sentry/core';
import * as Module from 'node:module';
import { createRequire } from 'node:module';
import { pathToFileURL } from 'node:url';
import 'node:url';
import { DEBUG_BUILD } from '../../debug-build.js';
import { SENTRY_INSTRUMENTATIONS } from '../config.js';
import { SENTRY_INSTRUMENTATIONS } from '../config/index.js';

@@ -18,3 +18,4 @@ function registerDiagnosticsChannelInjection() {

const stableSyncHooks = (nodeVersion[0] ?? 0) > 25 || nodeVersion[0] === 25 && (nodeVersion[1] ?? 0) >= 1 || nodeVersion[0] === 24 && (nodeVersion[1] ?? 0) >= 13 || (denoVersion[0] ?? 0) > 2 || denoVersion[0] === 2 && (denoVersion[1] ?? 0) >= 8;
const nodeRequire = typeof require === "function" ? require : createRequire(import.meta.url);
let nodeRequire;
nodeRequire = createRequire(import.meta.url);
const mod = Module;

@@ -28,3 +29,6 @@ try {

} else if (typeof mod.register === "function" && !globalAny.Bun && !globalAny.Deno) {
mod.register(pathToFileURL(nodeRequire.resolve("@apm-js-collab/tracing-hooks/hook.mjs")).href, {
let parentURL;
parentURL = import.meta.url;
mod.register("@apm-js-collab/tracing-hooks/hook.mjs", {
parentURL,
data: { instrumentations: SENTRY_INSTRUMENTATIONS }

@@ -31,0 +35,0 @@ });

@@ -1,1 +0,1 @@

{"version":3,"file":"register.js","sources":["../../../../src/orchestrion/runtime/register.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { createRequire } from 'node:module';\nimport * as Module from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { SENTRY_INSTRUMENTATIONS } from '../config';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Synchronously register the diagnostics-channel injection module hooks.\n *\n * This is the single source of truth for the registration logic. It is used by:\n * - `Sentry.init()` (the Node SDK calls it directly — that's why this module\n * must be CJS-compatible / dual-built, so it can be `require()`d synchronously\n * before the app's `import`s resolve), and\n * - `import-hook.mjs`, the side-effecting `--import` entry, which just calls it.\n *\n * Libraries imported *after* this call publish the `tracingChannel` events that\n * the channel-based integrations subscribe to.\n *\n * Idempotent via `globalThis.__SENTRY_ORCHESTRION__` — a no-op if the runtime\n * `--import` hook or a bundler plugin already injected the channels.\n */\nexport function registerDiagnosticsChannelInjection(): void {\n const g = (globalThis.__SENTRY_ORCHESTRION__ ??= {});\n\n // Already injected (runtime --import hook or bundler plugin) — nothing to do.\n if (g.runtime || g.bundler) {\n return;\n }\n\n const globalAny = globalThis as { Bun?: unknown; Deno?: { version?: { deno?: string } } };\n const parseVersion = (v: string): number[] => v.split('.').map(n => parseInt(n, 10));\n const nodeVersion = parseVersion(process.versions.node ?? '0.0.0');\n const denoVersion = parseVersion(globalAny.Deno?.version?.deno ?? '0.0.0');\n // `Module.registerHooks` only became stable in Node 24.13 / 25.1 and Deno 2.8.\n const stableSyncHooks =\n (nodeVersion[0] ?? 0) > 25 ||\n (nodeVersion[0] === 25 && (nodeVersion[1] ?? 0) >= 1) ||\n (nodeVersion[0] === 24 && (nodeVersion[1] ?? 0) >= 13) ||\n (denoVersion[0] ?? 0) > 2 ||\n (denoVersion[0] === 2 && (denoVersion[1] ?? 0) >= 8);\n\n // Prefer the builtin `require` if possible. This is present in CommonJS,\n // including a bundler's CJS output, so no need to ever have to evaluate\n // `import.meta.url` there.\n //\n // esbuild and friends rewrite `import.meta.url` to `{}` for CJS output,\n // which would make `createRequire(undefined)` throw.\n // Only use `import.meta.url` in true ESM, where there's no `require`\n const nodeRequire = typeof require === 'function' ? require : createRequire(import.meta.url);\n\n // `Module.registerHooks` / `Module.register` are newer than the @types/node\n // we build against, hence the cast.\n const mod = Module as unknown as {\n registerHooks?: (hooks: unknown) => void;\n register?: (specifier: string, options: unknown) => void;\n };\n\n // runs both at `--import` time and (synchronously) inside `Sentry.init()`,\n // so an unguarded throw would either abort startup or make `init()` throw.\n // On any failure (e.g. dep resolution, `require(esm)` / Node-compat\n // incompatibility) we warn (DEBUG only) and continue without channel\n // injection\n try {\n if (typeof mod.registerHooks === 'function' && stableSyncHooks) {\n // Sync hooks cover CJS and ESM, no separate `_compile` patch needed.\n // We require() the module here so that we can synchronously load it,\n // including from a CommonJS Sentry build, without bundlers pulling in.\n // All versions in stableSyncHooks support this.\n const { initialize, resolve, load } = nodeRequire('@apm-js-collab/tracing-hooks/hook-sync.mjs') as {\n initialize: (opts: { instrumentations: unknown }) => void;\n resolve: unknown;\n load: unknown;\n };\n initialize({ instrumentations: SENTRY_INSTRUMENTATIONS });\n mod.registerHooks({ resolve, load });\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.registerHooks()');\n } else if (typeof mod.register === 'function' && !globalAny.Bun && !globalAny.Deno) {\n // `Module.register` + the `_compile` patch is Node 18.19–24.12 / 25.0\n // path. Bun/Deno are excluded: they don't support this combination and\n // must use the stable `registerHooks` path above (or none at all).\n // Resolve the hook to an absolute file URL ourselves so\n // `Module.register` needs no `parentURL`, so no need for\n // `import.meta.url` polyfilling\n mod.register(pathToFileURL(nodeRequire.resolve('@apm-js-collab/tracing-hooks/hook.mjs')).href, {\n data: { instrumentations: SENTRY_INSTRUMENTATIONS },\n });\n\n // ALSO patch `Module.prototype._compile` for the CJS side: when an ESM\n // file `import`s a CJS package, the package's internal `require()` calls\n // are resolved through the CJS machinery and never reach the ESM\n // register hook, so without this patch the file we want to instrument\n // loads untransformed.\n const ModulePatch = nodeRequire('@apm-js-collab/tracing-hooks') as new (opts: { instrumentations: unknown }) => {\n patch: () => void;\n };\n new ModulePatch({ instrumentations: SENTRY_INSTRUMENTATIONS }).patch();\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.register()');\n } else {\n DEBUG_BUILD &&\n debug.warn('[Sentry] No available Node API to register diagnostics-channel injection hooks; skipping.');\n return;\n }\n } catch (error) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] Failed to register diagnostics-channel injection hooks; channel-based integrations ' +\n 'will not record spans.',\n error,\n );\n return;\n }\n\n g.runtime = true;\n}\n"],"names":[],"mappings":";;;;;;;AA2BO,SAAS,mCAAA,GAA4C;AAC1D,EAAA,MAAM,CAAA,GAAK,UAAA,CAAW,sBAAA,KAAX,UAAA,CAAW,yBAA2B,EAAC,CAAA;AAGlD,EAAA,IAAI,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,EAAS;AAC1B,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,UAAA;AAClB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAwB,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,QAAA,CAAS,CAAA,EAAG,EAAE,CAAC,CAAA;AACnF,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,OAAA,CAAQ,QAAA,CAAS,QAAQ,OAAO,CAAA;AACjE,EAAA,MAAM,cAAc,YAAA,CAAa,SAAA,CAAU,IAAA,EAAM,OAAA,EAAS,QAAQ,OAAO,CAAA;AAEzE,EAAA,MAAM,mBACH,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,MACvB,WAAA,CAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,YAAY,CAAC,CAAA,IAAK,CAAA,KAAM,CAAA,IAClD,YAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,KAAM,EAAA,IAAA,CAClD,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,CAAA,IACvB,WAAA,CAAY,CAAC,CAAA,KAAM,CAAA,IAAA,CAAM,WAAA,CAAY,CAAC,KAAK,CAAA,KAAM,CAAA;AASpD,EAAA,MAAM,cAAc,OAAO,OAAA,KAAY,aAAa,OAAA,GAAU,aAAA,CAAc,YAAY,GAAG,CAAA;AAI3F,EAAA,MAAM,GAAA,GAAM,MAAA;AAUZ,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,GAAA,CAAI,aAAA,KAAkB,UAAA,IAAc,eAAA,EAAiB;AAK9D,MAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,IAAA,EAAK,GAAI,YAAY,4CAA4C,CAAA;AAK9F,MAAA,UAAA,CAAW,EAAE,gBAAA,EAAkB,uBAAA,EAAyB,CAAA;AACxD,MAAA,GAAA,CAAI,aAAA,CAAc,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA;AACnC,MAAA,WAAA,IAAe,KAAA,CAAM,IAAI,mFAAmF,CAAA;AAAA,IAC9G,CAAA,MAAA,IAAW,OAAO,GAAA,CAAI,QAAA,KAAa,UAAA,IAAc,CAAC,SAAA,CAAU,GAAA,IAAO,CAAC,SAAA,CAAU,IAAA,EAAM;AAOlF,MAAA,GAAA,CAAI,SAAS,aAAA,CAAc,WAAA,CAAY,QAAQ,uCAAuC,CAAC,EAAE,IAAA,EAAM;AAAA,QAC7F,IAAA,EAAM,EAAE,gBAAA,EAAkB,uBAAA;AAAwB,OACnD,CAAA;AAOD,MAAA,MAAM,WAAA,GAAc,YAAY,8BAA8B,CAAA;AAG9D,MAAA,IAAI,YAAY,EAAE,gBAAA,EAAkB,uBAAA,EAAyB,EAAE,KAAA,EAAM;AACrE,MAAA,WAAA,IAAe,KAAA,CAAM,IAAI,8EAA8E,CAAA;AAAA,IACzG,CAAA,MAAO;AACL,MAAA,WAAA,IACE,KAAA,CAAM,KAAK,2FAA2F,CAAA;AACxG,MAAA;AAAA,IACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,WAAA,IACE,KAAA,CAAM,IAAA;AAAA,MACJ,oHAAA;AAAA,MAEA;AAAA,KACF;AACF,IAAA;AAAA,EACF;AAEA,EAAA,CAAA,CAAE,OAAA,GAAU,IAAA;AACd;;;;"}
{"version":3,"file":"register.js","sources":["../../../../src/orchestrion/runtime/register.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport { createRequire } from 'node:module';\nimport * as Module from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { SENTRY_INSTRUMENTATIONS } from '../config';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __SENTRY_ORCHESTRION__: { runtime?: boolean; bundler?: boolean } | undefined;\n}\n\n/**\n * Synchronously register the diagnostics-channel injection module hooks.\n *\n * This is the single source of truth for the registration logic. It is used by:\n * - `Sentry.init()` (the Node SDK calls it directly — that's why this module\n * must be CJS-compatible / dual-built, so it can be `require()`d synchronously\n * before the app's `import`s resolve), and\n * - `import-hook.mjs`, the side-effecting `--import` entry, which just calls it.\n *\n * Libraries imported *after* this call publish the `tracingChannel` events that\n * the channel-based integrations subscribe to.\n *\n * Idempotent via `globalThis.__SENTRY_ORCHESTRION__` — a no-op if the runtime\n * `--import` hook or a bundler plugin already injected the channels.\n */\nexport function registerDiagnosticsChannelInjection(): void {\n const g = (globalThis.__SENTRY_ORCHESTRION__ ??= {});\n\n // Already injected (runtime --import hook or bundler plugin) — nothing to do.\n if (g.runtime || g.bundler) {\n return;\n }\n\n const globalAny = globalThis as { Bun?: unknown; Deno?: { version?: { deno?: string } } };\n const parseVersion = (v: string): number[] => v.split('.').map(n => parseInt(n, 10));\n const nodeVersion = parseVersion(process.versions.node ?? '0.0.0');\n const denoVersion = parseVersion(globalAny.Deno?.version?.deno ?? '0.0.0');\n // `Module.registerHooks` only became stable in Node 24.13 / 25.1 and Deno 2.8.\n const stableSyncHooks =\n (nodeVersion[0] ?? 0) > 25 ||\n (nodeVersion[0] === 25 && (nodeVersion[1] ?? 0) >= 1) ||\n (nodeVersion[0] === 24 && (nodeVersion[1] ?? 0) >= 13) ||\n (denoVersion[0] ?? 0) > 2 ||\n (denoVersion[0] === 2 && (denoVersion[1] ?? 0) >= 8);\n\n let nodeRequire: (specifier: string) => unknown;\n /*! rollup-include-cjs-only */\n nodeRequire = require;\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n nodeRequire = createRequire(import.meta.url);\n /*! rollup-include-esm-only-end */\n\n // `Module.registerHooks` / `Module.register` are newer than the @types/node\n // we build against, hence the cast.\n const mod = Module as unknown as {\n registerHooks?: (hooks: unknown) => void;\n register?: (specifier: string, options: unknown) => void;\n };\n\n // runs both at `--import` time and (synchronously) inside `Sentry.init()`,\n // so an unguarded throw would either abort startup or make `init()` throw.\n // On any failure (e.g. dep resolution, `require(esm)` / Node-compat\n // incompatibility) we warn (DEBUG only) and continue without channel\n // injection\n try {\n if (typeof mod.registerHooks === 'function' && stableSyncHooks) {\n // Sync hooks cover CJS and ESM, no separate `_compile` patch needed.\n // We require() the module here so that we can synchronously load it,\n // including from a CommonJS Sentry build, without bundlers pulling in.\n // All versions in stableSyncHooks support this.\n const { initialize, resolve, load } = nodeRequire('@apm-js-collab/tracing-hooks/hook-sync.mjs') as {\n initialize: (opts: { instrumentations: unknown }) => void;\n resolve: unknown;\n load: unknown;\n };\n initialize({ instrumentations: SENTRY_INSTRUMENTATIONS });\n mod.registerHooks({ resolve, load });\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.registerHooks()');\n } else if (typeof mod.register === 'function' && !globalAny.Bun && !globalAny.Deno) {\n // `Module.register` + the `_compile` patch is Node 18.19–24.12 / 25.0\n // path. Bun/Deno are excluded: they don't support this combination and\n // must use the stable `registerHooks` path above (or none at all).\n let parentURL: string;\n /*! rollup-include-cjs-only */\n parentURL = pathToFileURL(__filename).href;\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n parentURL = import.meta.url;\n /*! rollup-include-esm-only-end */\n\n mod.register('@apm-js-collab/tracing-hooks/hook.mjs', {\n parentURL,\n data: { instrumentations: SENTRY_INSTRUMENTATIONS },\n });\n\n // ALSO patch `Module.prototype._compile` for the CJS side: when an ESM\n // file `import`s a CJS package, the package's internal `require()` calls\n // are resolved through the CJS machinery and never reach the ESM\n // register hook, so without this patch the file we want to instrument\n // loads untransformed.\n const ModulePatch = nodeRequire('@apm-js-collab/tracing-hooks') as new (opts: { instrumentations: unknown }) => {\n patch: () => void;\n };\n new ModulePatch({ instrumentations: SENTRY_INSTRUMENTATIONS }).patch();\n DEBUG_BUILD && debug.log('[orchestrion] registered diagnostics-channel injection via Module.register()');\n } else {\n DEBUG_BUILD &&\n debug.warn('[Sentry] No available Node API to register diagnostics-channel injection hooks; skipping.');\n return;\n }\n } catch (error) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] Failed to register diagnostics-channel injection hooks; channel-based integrations ' +\n 'will not record spans.',\n error,\n );\n return;\n }\n\n g.runtime = true;\n}\n"],"names":[],"mappings":";;;;;;;AA2BO,SAAS,mCAAA,GAA4C;AAC1D,EAAA,MAAM,CAAA,GAAK,UAAA,CAAW,sBAAA,KAAX,UAAA,CAAW,yBAA2B,EAAC,CAAA;AAGlD,EAAA,IAAI,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,EAAS;AAC1B,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,UAAA;AAClB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAwB,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,QAAA,CAAS,CAAA,EAAG,EAAE,CAAC,CAAA;AACnF,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,OAAA,CAAQ,QAAA,CAAS,QAAQ,OAAO,CAAA;AACjE,EAAA,MAAM,cAAc,YAAA,CAAa,SAAA,CAAU,IAAA,EAAM,OAAA,EAAS,QAAQ,OAAO,CAAA;AAEzE,EAAA,MAAM,mBACH,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,MACvB,WAAA,CAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,YAAY,CAAC,CAAA,IAAK,CAAA,KAAM,CAAA,IAClD,YAAY,CAAC,CAAA,KAAM,EAAA,IAAA,CAAO,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,KAAM,EAAA,IAAA,CAClD,WAAA,CAAY,CAAC,CAAA,IAAK,CAAA,IAAK,CAAA,IACvB,WAAA,CAAY,CAAC,CAAA,KAAM,CAAA,IAAA,CAAM,WAAA,CAAY,CAAC,KAAK,CAAA,KAAM,CAAA;AAEpD,EAAA,IAAI,WAAA;AAAA,EACJ,WAAA,GAAA,aAAA,CAAA,MAAA,CAAA,IAAA,CAAA,GAAA,CAAA;AACA,EAAA,MAAA,GAAA,GAAA,MAAc;AAAA,EACd,IAAA;AAAA,IACA,IAAA,OAAA,GAAA,CAAA,aAAA,KAAA,UAAA,IAAA,eAAA,EAAA;AACA,MAAA,MAAA,EAAA,UAAc,EAAA,kBAA0B,WAAG,CAAA,4CAAA,CAAA;AAAA,MAC3C,UAAA,CAAA,EAAA,gBAAA,EAAA,uBAAA,EAAA,CAAA;AAIA,MAAA,GAAM,CAAA,aAAM,CAAA,EAAA,OAAA,EAAA,IAAA,EAAA,CAAA;AAUZ,MAAI,WAAA,IAAA,KAAA,CAAA,GAAA,CAAA,mFAAA,CAAA;AACF,IAAA,CAAA,MAAI,IAAO,OAAI,GAAA,CAAA,QAAA,KAAkB,UAAA,IAAc,CAAA,SAAA,CAAA,GAAA,IAAiB,CAAA,SAAA,CAAA,IAAA,EAAA;AAK9D,MAAA,IAAA,SAAQ;AAKR,MAAA,SAAA,GAAW,MAAE,CAAA,IAAA,CAAA,GAAA;AACb,MAAA,GAAA,CAAI,QAAA,CAAA,uCAA+B,EAAA;AACnC,QAAA,SAAA;AAA4G,QAC9G,IAAA,EAAA,EAAW,gBAAW,EAAA,uBAA4B;AAIhD,OAAA,CAAA;AAAI,MACJ,MAAA,WAAA,GAAA,WAAA,CAAA,8BAAA,CAAA;AACA,MAAA,IAAA,WAAY,CAAA,EAAA,kBAAwB,uBAAE,EAAA,CAAA,CAAA,KAAA,EAAA;AAAA,MACtC,WAAA,IAAA,KAAA,CAAA,GAAA,CAAA,8EAAA,CAAA;AAAA,IAAA,CAAA,MACA;AACA,MAAA,WAAA,IAAY,KAAA,CAAA,IAAY,CAAA,2FAAA,CAAA;AAAA,MACxB;AAEA,IAAA;AAAsD,EAAA,CAAA,CAAA,OACpD,KAAA,EAAA;AAAA,IAAA,WACM,IAAE,KAAA,CAAA,IAAA;AAA0C,MACpD,oHAAC;AAOD,MAAA;AAGA,KAAA;AACA,IAAA;AAAuG,EAAA;AAEvG,EAAA,CAAA,CAAA,OAAA,GAAA,IAAA;AAEA;;;;"}

@@ -1,1 +0,1 @@

{"type":"module","version":"10.63.0","sideEffects":false}
{"type":"module","version":"10.64.0","sideEffects":false}

@@ -1,2 +0,2 @@

import { getAsyncContextStrategy, getMainCarrier, debug, captureException, SPAN_STATUS_ERROR } from '@sentry/core';
import { getAsyncContextStrategy, getMainCarrier, debug, SPAN_STATUS_ERROR, captureException } from '@sentry/core';
import { DEBUG_BUILD } from './debug-build.js';

@@ -120,3 +120,3 @@ import { ERROR_TYPE } from '@sentry/conventions/attributes';

const raw = isObject ? "message" in error ? error.message : void 0 : error;
const message = raw ? String(raw) : "unknown_error";
const message = raw ? String(raw) : void 0;
const type = isObject && "name" in error ? String(error.name) : "unknown";

@@ -123,0 +123,0 @@ return {

@@ -1,1 +0,1 @@

{"version":3,"file":"tracing-channel.js","sources":["../../src/tracing-channel.ts"],"sourcesContent":["import type { TracingChannel, TracingChannelSubscribers } from 'node:diagnostics_channel';\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport type { ExclusiveEventHintOrCaptureContext, Span } from '@sentry/core';\nimport { debug, captureException, SPAN_STATUS_ERROR, getAsyncContextStrategy, getMainCarrier } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { ERROR_TYPE } from '@sentry/conventions/attributes';\n\nexport type TracingChannelPayloadWithSpan<TData extends object> = TData & {\n /**\n * The current active span for the traced call.\n */\n _sentrySpan?: Span;\n\n /**\n * The context's active store value, used to restore the context for asyncStart continuations for callback-based tracing.\n */\n _sentryCallerStore?: unknown;\n};\n\n/*\n * A type patch so that we don't have to handle all subscription types.\n */\nexport interface SentryTracingChannel<TData extends object = object> extends Omit<\n TracingChannel<TData, TracingChannelPayloadWithSpan<TData>>,\n 'subscribe' | 'unsubscribe'\n> {\n subscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n unsubscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n}\n\nexport interface TracingChannelLifeCycleOptions<TData extends object = object> {\n /**\n * Invoked with the span and the channel context object once the traced operation completes\n * Use it to enrich the span from the result/error (branch on `'error' in data` / `'result' in data`) or to run cleanup.\n */\n beforeSpanEnd?: (span: Span, data: TracingChannelPayloadWithSpan<TData>) => void;\n\n /**\n * Whether a thrown error is captured as a Sentry event. The span is always marked with error status regardless. Defaults to `false`.\n * You can alternatively pass a function that sets the ExclusiveEventHintOrCaptureContext on the captured error.\n * Set `true` for instrumentations that own the error boundary, (e.g: route handlers)\n * For database drivers, it is not recommended to set this at all.\n */\n captureError?: boolean | ((e: unknown) => ExclusiveEventHintOrCaptureContext);\n\n /**\n * Take ownership of *when* the span ends: return `true` and the helper won't end it on\n * `end`/`asyncEnd`. For results that settle out-of-band — e.g. a streamed `EventEmitter` that\n * completes via its own `'end'`/`'error'` events.\n *\n * Call `end` when it settles — `end()` on success, `end(error)` on failure. `end` owns *how* the span\n * ends (error status/attributes, `captureError`, `beforeSpanEnd`) and is idempotent. Default `false`\n * lets the helper end the span as usual.\n */\n deferSpanEnd?: (args: {\n span: Span;\n data: TracingChannelPayloadWithSpan<TData>;\n /** Ends the span: `end()` on success, `end(error)` on failure. Idempotent. */\n end: (error?: unknown) => void;\n }) => boolean;\n}\n\n/** Returned by {@link bindTracingChannelToSpan}: the bound channel plus a teardown handle. */\nexport interface TracingChannelBindingHandle<TData extends object = object> {\n /**\n * The tracing channel with the span bound into async context.\n */\n channel: SentryTracingChannel<TData>;\n\n /**\n * Tears down the binding: unsubscribes lifecycle handlers, when present, and unbinds the start store.\n * Idempotent, and a no-op when no async context binding was available.\n */\n unbind: () => void;\n}\n\nconst NOOP = (): void => {};\n\n/**\n * Bind a span and its lifecycle to a tracing channel so the span becomes the active async context\n * for the traced operation and is ended when the operation completes.\n *\n * `getSpan` may return `undefined` to opt a payload out entirely: nothing is bound, no span is\n * tracked, and the active context is left untouched. Use it for events that ride the same channel\n * but should reuse the enclosing span instead of opening (and ending) their own — e.g. an agent\n * loop's per-step events, where ending a freshly opened span would close the parent prematurely.\n */\nexport function bindTracingChannelToSpan<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n opts?: TracingChannelLifeCycleOptions<TData>,\n): TracingChannelBindingHandle<TData> {\n const handle = bindSpanToChannelStore(channel, getSpan);\n\n const beforeSpanEnd = opts?.beforeSpanEnd;\n const deferSpanEnd = opts?.deferSpanEnd;\n const getErrorHint = (e: unknown): ExclusiveEventHintOrCaptureContext => {\n if (typeof opts?.captureError === 'function') {\n return opts.captureError(e);\n }\n\n return {\n mechanism: {\n type: 'auto.diagnostic_channels.bind_span',\n handled: false,\n },\n };\n };\n\n // Apply Sentry error status + attributes (and capture, if configured) to a span. Shared by the\n // channel `error` lifecycle and the deferred `end` util so the two can't drift.\n const annotateSpanError = (span: Span, error: unknown): void => {\n if (opts?.captureError) {\n captureException(error, getErrorHint(error));\n }\n\n const { message, attributes } = getErrorInfo(error);\n span.setStatus({ code: SPAN_STATUS_ERROR, message });\n span.setAttributes(attributes);\n };\n\n // Creates an end fn for deferred handlers to use, ensures consistent span end behavior\n const makeDeferredEnd = (span: Span, data: TracingChannelPayloadWithSpan<TData>) => {\n let ended = false;\n\n return (error?: unknown): void => {\n if (ended) {\n return;\n }\n\n ended = true;\n if (error !== undefined) {\n annotateSpanError(span, error);\n }\n\n endBoundSpan(data, beforeSpanEnd);\n };\n };\n\n const subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>> = {\n start: NOOP,\n asyncStart: NOOP,\n end(data) {\n // The operation settled synchronously (returned or threw)\n // Presence checks because caller can return `undefined` result or throw a falsy value.\n if ('error' in data || 'result' in data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n }\n },\n error(data) {\n // No span was bound for this payload (`getSpan` returned undefined), so there is nothing to\n // annotate and no instrumentation that owns capturing this error.\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n\n annotateSpanError(span, data.error);\n },\n asyncEnd(data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n },\n };\n\n handle.channel.subscribe(subscribers);\n\n return {\n channel: handle.channel,\n unbind: () => {\n handle.channel.unsubscribe(subscribers);\n handle.unbind();\n },\n };\n}\n\n/**\n * Bind a span into the channel's async context so it becomes active for the traced operation,\n * without managing its lifecycle. The primitive behind {@link bindTracingChannelToSpan}, which\n * layers span-ending and error handling on top.\n *\n * `getSpan` may return `undefined` to leave the active context untouched for that payload.\n */\nfunction bindSpanToChannelStore<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n): TracingChannelBindingHandle<TData> {\n // Grabs the tracing channel binding defined by the AsyncContext strategy implementation\n const binding = getAsyncContextStrategy(getMainCarrier()).getTracingChannelBinding?.();\n\n // If no binding, then either the implementer doesn't support tracing channels or there is no active strategy\n // Failure mode here means we would still access the channel and potentially subscribe to it, but parenting will be off.\n if (!binding) {\n DEBUG_BUILD && debug.log('[TracingChannel] Could not access async context binding.');\n\n return {\n channel,\n unbind: NOOP,\n };\n }\n\n // Grab the ALS instance, we don't really care what is in it as long as the AsyncContext strategy can use its value to figure out parenting.\n const asyncLocalStorage = binding.asyncLocalStorage as AsyncLocalStorage<TData>;\n\n // bindStore activates the ALS for the traced call; any getStore() inside it returns the value bound for that context.\n // 1. Produce: getStoreWithActiveSpan(span) clones the current scope, plants the span via _INTERNAL_setSpanForScope, and returns { scope, isolationScope }, the active context carrying our span.\n // 2. Bind: the courier hands that opaque value to channel.start.bindStore(asyncLocalStorage, producer), which runs the traced op inside asyncLocalStorage.run(value, …); it never inspects the value.\n // 3. Read: inside the op, Sentry's scope machinery calls getScopes() → asyncStorage.getStore() on that same ALS, so getCurrentScope/getIsolationScope/getActiveSpan resolve to the scope carrying our span.\n // 4. Nest: any child span started in the traced op parents to that active span.\n channel.start.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n // Stash the caller's store before we swap in the span store, so `asyncStart` can restore it for\n // callback-style channels (see `_sentryCallerStore`).\n data._sentryCallerStore = asyncLocalStorage.getStore();\n\n const span = getSpan(data);\n if (!span) {\n // Leave the active context untouched so nested operations keep parenting to the enclosing span.\n return data._sentryCallerStore as TData;\n }\n data._sentrySpan = span;\n\n return binding.getStoreWithActiveSpan(span) as TData;\n });\n\n // Restore the caller's context for the async continuation. Only callback-style channels `runStores`\n // `asyncStart` (so the callback runs inside this store). promise channels `publish` it, leaving this\n // inert, their continuation already inherits the caller's context natively.\n channel.asyncStart.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n return data._sentryCallerStore as TData;\n });\n\n return {\n channel,\n unbind: () => {\n // Removes the stores\n channel.start.unbindStore(asyncLocalStorage);\n channel.asyncStart.unbindStore(asyncLocalStorage);\n },\n };\n}\n\nfunction endBoundSpan<TData extends object>(\n data: TracingChannelPayloadWithSpan<TData>,\n beforeSpanEnd: TracingChannelLifeCycleOptions<TData>['beforeSpanEnd'],\n): void {\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n beforeSpanEnd?.(span, data);\n span.end();\n}\n\ntype ErrorInfo = {\n message: string;\n attributes: Record<string, string>;\n};\n\n/**\n * Best-effort message and attribute extraction for thrown/rejected values.\n */\nfunction getErrorInfo(error: unknown): ErrorInfo {\n const isObject = !!error && typeof error === 'object';\n const raw = isObject ? ('message' in error ? error.message : undefined) : error;\n\n const message = raw ? String(raw) : 'unknown_error';\n const type = isObject && 'name' in error ? String(error.name) : 'unknown';\n\n return {\n message,\n attributes: {\n [ERROR_TYPE]: type,\n },\n };\n}\n"],"names":[],"mappings":"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"}
{"version":3,"file":"tracing-channel.js","sources":["../../src/tracing-channel.ts"],"sourcesContent":["import type { TracingChannel, TracingChannelSubscribers } from 'node:diagnostics_channel';\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport type { ExclusiveEventHintOrCaptureContext, Span } from '@sentry/core';\nimport { debug, captureException, SPAN_STATUS_ERROR, getAsyncContextStrategy, getMainCarrier } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { ERROR_TYPE } from '@sentry/conventions/attributes';\n\nexport type TracingChannelPayloadWithSpan<TData extends object> = TData & {\n /**\n * The current active span for the traced call.\n */\n _sentrySpan?: Span;\n\n /**\n * The context's active store value, used to restore the context for asyncStart continuations for callback-based tracing.\n */\n _sentryCallerStore?: unknown;\n};\n\n/*\n * A type patch so that we don't have to handle all subscription types.\n */\nexport interface SentryTracingChannel<TData extends object = object> extends Omit<\n TracingChannel<TData, TracingChannelPayloadWithSpan<TData>>,\n 'subscribe' | 'unsubscribe'\n> {\n subscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n unsubscribe(subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>>): void;\n}\n\nexport interface TracingChannelLifeCycleOptions<TData extends object = object> {\n /**\n * Invoked with the span and the channel context object once the traced operation completes\n * Use it to enrich the span from the result/error (branch on `'error' in data` / `'result' in data`) or to run cleanup.\n */\n beforeSpanEnd?: (span: Span, data: TracingChannelPayloadWithSpan<TData>) => void;\n\n /**\n * Whether a thrown error is captured as a Sentry event. The span is always marked with error status regardless. Defaults to `false`.\n * You can alternatively pass a function that sets the ExclusiveEventHintOrCaptureContext on the captured error.\n * Set `true` for instrumentations that own the error boundary, (e.g: route handlers)\n * For database drivers, it is not recommended to set this at all.\n */\n captureError?: boolean | ((e: unknown) => ExclusiveEventHintOrCaptureContext);\n\n /**\n * Take ownership of *when* the span ends: return `true` and the helper won't end it on\n * `end`/`asyncEnd`. For results that settle out-of-band — e.g. a streamed `EventEmitter` that\n * completes via its own `'end'`/`'error'` events.\n *\n * Call `end` when it settles — `end()` on success, `end(error)` on failure. `end` owns *how* the span\n * ends (error status/attributes, `captureError`, `beforeSpanEnd`) and is idempotent. Default `false`\n * lets the helper end the span as usual.\n */\n deferSpanEnd?: (args: {\n span: Span;\n data: TracingChannelPayloadWithSpan<TData>;\n /** Ends the span: `end()` on success, `end(error)` on failure. Idempotent. */\n end: (error?: unknown) => void;\n }) => boolean;\n}\n\n/** Returned by {@link bindTracingChannelToSpan}: the bound channel plus a teardown handle. */\nexport interface TracingChannelBindingHandle<TData extends object = object> {\n /**\n * The tracing channel with the span bound into async context.\n */\n channel: SentryTracingChannel<TData>;\n\n /**\n * Tears down the binding: unsubscribes lifecycle handlers, when present, and unbinds the start store.\n * Idempotent, and a no-op when no async context binding was available.\n */\n unbind: () => void;\n}\n\nconst NOOP = (): void => {};\n\n/**\n * Bind a span and its lifecycle to a tracing channel so the span becomes the active async context\n * for the traced operation and is ended when the operation completes.\n *\n * `getSpan` may return `undefined` to opt a payload out entirely: nothing is bound, no span is\n * tracked, and the active context is left untouched. Use it for events that ride the same channel\n * but should reuse the enclosing span instead of opening (and ending) their own — e.g. an agent\n * loop's per-step events, where ending a freshly opened span would close the parent prematurely.\n */\nexport function bindTracingChannelToSpan<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n opts?: TracingChannelLifeCycleOptions<TData>,\n): TracingChannelBindingHandle<TData> {\n const handle = bindSpanToChannelStore(channel, getSpan);\n\n const beforeSpanEnd = opts?.beforeSpanEnd;\n const deferSpanEnd = opts?.deferSpanEnd;\n const getErrorHint = (e: unknown): ExclusiveEventHintOrCaptureContext => {\n if (typeof opts?.captureError === 'function') {\n return opts.captureError(e);\n }\n\n return {\n mechanism: {\n type: 'auto.diagnostic_channels.bind_span',\n handled: false,\n },\n };\n };\n\n // Apply Sentry error status + attributes (and capture, if configured) to a span. Shared by the\n // channel `error` lifecycle and the deferred `end` util so the two can't drift.\n const annotateSpanError = (span: Span, error: unknown): void => {\n if (opts?.captureError) {\n captureException(error, getErrorHint(error));\n }\n\n const { message, attributes } = getErrorInfo(error);\n span.setStatus({ code: SPAN_STATUS_ERROR, message });\n span.setAttributes(attributes);\n };\n\n // Creates an end fn for deferred handlers to use, ensures consistent span end behavior\n const makeDeferredEnd = (span: Span, data: TracingChannelPayloadWithSpan<TData>) => {\n let ended = false;\n\n return (error?: unknown): void => {\n if (ended) {\n return;\n }\n\n ended = true;\n if (error !== undefined) {\n annotateSpanError(span, error);\n }\n\n endBoundSpan(data, beforeSpanEnd);\n };\n };\n\n const subscribers: Partial<TracingChannelSubscribers<TracingChannelPayloadWithSpan<TData>>> = {\n start: NOOP,\n asyncStart: NOOP,\n end(data) {\n // The operation settled synchronously (returned or threw)\n // Presence checks because caller can return `undefined` result or throw a falsy value.\n if ('error' in data || 'result' in data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n }\n },\n error(data) {\n // No span was bound for this payload (`getSpan` returned undefined), so there is nothing to\n // annotate and no instrumentation that owns capturing this error.\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n\n annotateSpanError(span, data.error);\n },\n asyncEnd(data) {\n const span = data._sentrySpan;\n if (span && deferSpanEnd?.({ span, data, end: makeDeferredEnd(span, data) })) {\n return;\n }\n endBoundSpan(data, beforeSpanEnd);\n },\n };\n\n handle.channel.subscribe(subscribers);\n\n return {\n channel: handle.channel,\n unbind: () => {\n handle.channel.unsubscribe(subscribers);\n handle.unbind();\n },\n };\n}\n\n/**\n * Bind a span into the channel's async context so it becomes active for the traced operation,\n * without managing its lifecycle. The primitive behind {@link bindTracingChannelToSpan}, which\n * layers span-ending and error handling on top.\n *\n * `getSpan` may return `undefined` to leave the active context untouched for that payload.\n */\nfunction bindSpanToChannelStore<TData extends object>(\n channel: TracingChannel<TData, TData>,\n getSpan: (data: TracingChannelPayloadWithSpan<TData>) => Span | undefined,\n): TracingChannelBindingHandle<TData> {\n // Grabs the tracing channel binding defined by the AsyncContext strategy implementation\n const binding = getAsyncContextStrategy(getMainCarrier()).getTracingChannelBinding?.();\n\n // If no binding, then either the implementer doesn't support tracing channels or there is no active strategy\n // Failure mode here means we would still access the channel and potentially subscribe to it, but parenting will be off.\n if (!binding) {\n DEBUG_BUILD && debug.log('[TracingChannel] Could not access async context binding.');\n\n return {\n channel,\n unbind: NOOP,\n };\n }\n\n // Grab the ALS instance, we don't really care what is in it as long as the AsyncContext strategy can use its value to figure out parenting.\n const asyncLocalStorage = binding.asyncLocalStorage as AsyncLocalStorage<TData>;\n\n // bindStore activates the ALS for the traced call; any getStore() inside it returns the value bound for that context.\n // 1. Produce: getStoreWithActiveSpan(span) clones the current scope, plants the span via _INTERNAL_setSpanForScope, and returns { scope, isolationScope }, the active context carrying our span.\n // 2. Bind: the courier hands that opaque value to channel.start.bindStore(asyncLocalStorage, producer), which runs the traced op inside asyncLocalStorage.run(value, …); it never inspects the value.\n // 3. Read: inside the op, Sentry's scope machinery calls getScopes() → asyncStorage.getStore() on that same ALS, so getCurrentScope/getIsolationScope/getActiveSpan resolve to the scope carrying our span.\n // 4. Nest: any child span started in the traced op parents to that active span.\n channel.start.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n // Stash the caller's store before we swap in the span store, so `asyncStart` can restore it for\n // callback-style channels (see `_sentryCallerStore`).\n data._sentryCallerStore = asyncLocalStorage.getStore();\n\n const span = getSpan(data);\n if (!span) {\n // Leave the active context untouched so nested operations keep parenting to the enclosing span.\n return data._sentryCallerStore as TData;\n }\n data._sentrySpan = span;\n\n return binding.getStoreWithActiveSpan(span) as TData;\n });\n\n // Restore the caller's context for the async continuation. Only callback-style channels `runStores`\n // `asyncStart` (so the callback runs inside this store). promise channels `publish` it, leaving this\n // inert, their continuation already inherits the caller's context natively.\n channel.asyncStart.bindStore(asyncLocalStorage, (data: TracingChannelPayloadWithSpan<TData>) => {\n return data._sentryCallerStore as TData;\n });\n\n return {\n channel,\n unbind: () => {\n // Removes the stores\n channel.start.unbindStore(asyncLocalStorage);\n channel.asyncStart.unbindStore(asyncLocalStorage);\n },\n };\n}\n\nfunction endBoundSpan<TData extends object>(\n data: TracingChannelPayloadWithSpan<TData>,\n beforeSpanEnd: TracingChannelLifeCycleOptions<TData>['beforeSpanEnd'],\n): void {\n const span = data._sentrySpan;\n if (!span) {\n return;\n }\n beforeSpanEnd?.(span, data);\n span.end();\n}\n\ntype ErrorInfo = {\n message: string | undefined;\n attributes: Record<string, string>;\n};\n\n/**\n * Best-effort message and attribute extraction for thrown/rejected values.\n */\nfunction getErrorInfo(error: unknown): ErrorInfo {\n const isObject = !!error && typeof error === 'object';\n const raw = isObject ? ('message' in error ? error.message : undefined) : error;\n\n // Leave the status message unset if not set (e.g. an `AggregateError` from\n // ECONNREFUSED, whose `.message` is empty). Otherwise cast to string.\n const message = raw ? String(raw) : undefined;\n const type = isObject && 'name' in error ? String(error.name) : 'unknown';\n\n return {\n message,\n attributes: {\n [ERROR_TYPE]: type,\n },\n };\n}\n"],"names":[],"mappings":"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"}

@@ -1,4 +0,4 @@

import { GEN_AI_EMBEDDINGS_INPUT, GEN_AI_OPERATION_NAME, GEN_AI_FUNCTION_ID, GEN_AI_RESPONSE_STREAMING, GEN_AI_REQUEST_AVAILABLE_TOOLS, GEN_AI_TOOL_INPUT, GEN_AI_TOOL_NAME, GEN_AI_TOOL_TYPE, GEN_AI_TOOL_OUTPUT, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, GEN_AI_RESPONSE_FINISH_REASONS, GEN_AI_RESPONSE_ID, GEN_AI_RESPONSE_MODEL, GEN_AI_OUTPUT_MESSAGES, GEN_AI_INPUT_MESSAGES, GEN_AI_REQUEST_MODEL, GEN_AI_SYSTEM } from '@sentry/conventions/attributes';
import { GEN_AI_INVOKE_AGENT_SPAN_OP, GEN_AI_EXECUTE_TOOL_SPAN_OP } from '@sentry/conventions/op';
import { startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getProviderMetadataAttributes, GEN_AI_CONVERSATION_ID_ATTRIBUTE, spanToJSON, SPAN_STATUS_ERROR, withScope, spanToTraceContext, captureException, getClient, shouldEnableTruncation, getTruncatedJsonString, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '@sentry/core';
import { GEN_AI_EMBEDDINGS_INPUT, GEN_AI_OPERATION_NAME, GEN_AI_TOOL_INPUT, GEN_AI_TOOL_NAME, GEN_AI_TOOL_TYPE, GEN_AI_REQUEST_AVAILABLE_TOOLS, GEN_AI_FUNCTION_ID, GEN_AI_RESPONSE_STREAMING, GEN_AI_TOOL_OUTPUT, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, GEN_AI_RESPONSE_FINISH_REASONS, GEN_AI_RESPONSE_ID, GEN_AI_RESPONSE_MODEL, GEN_AI_OUTPUT_MESSAGES, GEN_AI_INPUT_MESSAGES, GEN_AI_REQUEST_MODEL, GEN_AI_SYSTEM } from '@sentry/conventions/attributes';
import { GEN_AI_EXECUTE_TOOL_SPAN_OP, GEN_AI_INVOKE_AGENT_SPAN_OP } from '@sentry/conventions/op';
import { getClient, shouldEnableTruncation, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getTruncatedJsonString, getProviderMetadataAttributes, GEN_AI_CONVERSATION_ID_ATTRIBUTE, spanToJSON, SPAN_STATUS_ERROR, withScope, spanToTraceContext, captureException, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '@sentry/core';
import { bindTracingChannelToSpan } from '../tracing-channel.js';

@@ -18,3 +18,3 @@

const toolDescriptionsByCallId = /* @__PURE__ */ new Map();
const ROOT_OPERATION_TYPES = /* @__PURE__ */ new Set(["generateText", "streamText", "embed", "rerank"]);
const ROOT_OPERATION_TYPES = /* @__PURE__ */ new Set(["generateText", "streamText", "embed", "embedMany", "rerank"]);
function clearOperationId(data) {

@@ -26,6 +26,9 @@ if (!ROOT_OPERATION_TYPES.has(data.type)) {

if (callId) {
operationIdByCallId.delete(callId);
toolDescriptionsByCallId.delete(callId);
clearOperationCallId(callId);
}
}
function clearOperationCallId(callId) {
operationIdByCallId.delete(callId);
toolDescriptionsByCallId.delete(callId);
}
function recordToolDescriptions(callId, tools) {

@@ -110,6 +113,9 @@ if (!callId || !Array.isArray(tools)) {

case "embed":
case "embedMany": {
const input = type === "embedMany" ? event.values : event.value;
return startGenAiSpan(GEN_AI_EMBEDDINGS_OPERATION, modelId, {
...baseAttributes,
...recordInputs && event.value !== void 0 ? { [GEN_AI_EMBEDDINGS_INPUT]: safeStringify(event.value) } : {}
...recordInputs && input !== void 0 ? { [GEN_AI_EMBEDDINGS_INPUT]: safeStringify(input) } : {}
});
}
case "rerank":

@@ -359,3 +365,3 @@ return startGenAiSpan(GEN_AI_RERANK_OPERATION, modelId, baseAttributes);

export { clearOperationId, createSpanFromMessage, enrichSpanOnEnd, subscribeVercelAiTracingChannel };
export { clearOperationCallId, clearOperationId, createSpanFromMessage, enrichSpanOnEnd, subscribeVercelAiTracingChannel };
//# sourceMappingURL=vercel-ai-dc-subscriber.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"vercel-ai-dc-subscriber.js","sources":["../../../src/vercel-ai/vercel-ai-dc-subscriber.ts"],"sourcesContent":["/* eslint-disable max-lines */\n// `@sentry/conventions` marks several gen_ai attributes (e.g. `GEN_AI_SYSTEM`, `GEN_AI_TOOL_*`,\n// `GEN_AI_REQUEST_AVAILABLE_TOOLS`) as deprecated in favour of newer semconv names. We intentionally\n// keep emitting the current names so these spans match the OTel-based (v6) integration and what the\n// Sentry product consumes today; migrating to the new names is a separate, coordinated change.\n/* eslint-disable typescript-eslint/no-deprecated */\nimport {\n GEN_AI_EMBEDDINGS_INPUT,\n GEN_AI_FUNCTION_ID,\n GEN_AI_INPUT_MESSAGES,\n GEN_AI_OPERATION_NAME,\n GEN_AI_OUTPUT_MESSAGES,\n GEN_AI_REQUEST_AVAILABLE_TOOLS,\n GEN_AI_REQUEST_MODEL,\n GEN_AI_RESPONSE_FINISH_REASONS,\n GEN_AI_RESPONSE_ID,\n GEN_AI_RESPONSE_MODEL,\n GEN_AI_RESPONSE_STREAMING,\n GEN_AI_SYSTEM,\n GEN_AI_TOOL_INPUT,\n GEN_AI_TOOL_NAME,\n GEN_AI_TOOL_OUTPUT,\n GEN_AI_TOOL_TYPE,\n GEN_AI_USAGE_INPUT_TOKENS,\n GEN_AI_USAGE_OUTPUT_TOKENS,\n GEN_AI_USAGE_TOTAL_TOKENS,\n} from '@sentry/conventions/attributes';\nimport { GEN_AI_EXECUTE_TOOL_SPAN_OP, GEN_AI_INVOKE_AGENT_SPAN_OP } from '@sentry/conventions/op';\nimport type { Span } from '@sentry/core';\nimport {\n captureException,\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n getClient,\n getProviderMetadataAttributes,\n getTruncatedJsonString,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n SPAN_STATUS_ERROR,\n spanToJSON,\n spanToTraceContext,\n startInactiveSpan,\n withScope,\n} from '@sentry/core';\nimport type { TracingChannel } from 'node:diagnostics_channel';\nimport { bindTracingChannelToSpan } from '../tracing-channel';\n\n/**\n * The single tracing channel the `ai` package (>= 7) publishes all telemetry lifecycle events to\n * via `node:diagnostics_channel`. Events are discriminated by their `type` field.\n * @see https://github.com/vercel/ai/pull/15660\n */\nconst AI_SDK_TELEMETRY_TRACING_CHANNEL = 'ai:telemetry';\n\nconst ORIGIN = 'auto.vercelai.channel';\n\n// `@sentry/conventions` does not expose these yet, so we keep the literals here.\nconst GEN_AI_TOOL_CALL_ID_ATTRIBUTE = 'gen_ai.tool.call.id';\nconst GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE = 'gen_ai.tool.description';\nconst GEN_AI_EMBEDDINGS_OPERATION = 'embeddings';\nconst GEN_AI_RERANK_OPERATION = 'rerank';\n// The model-call op matches the Vercel AI OTel integration (`gen_ai.generate_content`) rather than\n// the generic `gen_ai.chat`, so v6 (OTel) and v7 (channel) produce the same spans.\nconst GEN_AI_GENERATE_CONTENT_OPERATION = 'generate_content';\n\n// Subset of the `vercel.ai.*` passthrough attributes the OTel integration emits that we reproduce.\nconst VERCEL_AI_OPERATION_ID_ATTRIBUTE = 'vercel.ai.operationId';\nconst VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE = 'vercel.ai.model.provider';\nconst VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE = 'vercel.ai.settings.maxRetries';\n\n// Tracks the top-level operationId (and whether it streams) per `callId` so a model-call span can\n// name its `doGenerate`/`doStream` operation the same way the OTel integration does. `isStream` is\n// the authoritative event-type signal rather than a substring check on the (possibly custom)\n// operationId. Cleared when the top-level span ends.\nconst operationIdByCallId = new Map<string, { operationId: string; isStream: boolean }>();\n\n// Per-operation map of tool name → description, harvested from a model-call /\n// top-level event's `tools` (keyed by the shared `callId`). The AI SDK's\n// `executeTool` event doesn't carry the tool's description, so we backfill it\n// onto the tool span here — without relying on the OTel `vercelAiEventProcessor`\n// (which isn't registered in channel/orchestrion mode). Cleared with the\n// operation. Only populated when inputs are recorded, matching the OTel path\n// (which sources descriptions from the recorded `available_tools`).\nconst toolDescriptionsByCallId = new Map<string, Map<string, string>>();\n\n// Only top-level operations own the `callId` → operationId mapping; `step`/`languageModelCall`/\n// `executeTool` share the parent's `callId`, so they must not clear it.\nconst ROOT_OPERATION_TYPES = new Set<ChannelEventType>(['generateText', 'streamText', 'embed', 'rerank']);\n\n/** Drop the per-operation `callId` maps once the owning top-level operation settles (success or error). */\nexport function clearOperationId(data: VercelAiChannelMessage): void {\n if (!ROOT_OPERATION_TYPES.has(data.type)) {\n return;\n }\n const callId = asString(data.event.callId);\n if (callId) {\n operationIdByCallId.delete(callId);\n toolDescriptionsByCallId.delete(callId);\n }\n}\n\n/** Record tool name → description from an event's `tools`, so tool spans can backfill the description. */\nfunction recordToolDescriptions(callId: string | undefined, tools: unknown): void {\n if (!callId || !Array.isArray(tools)) {\n return;\n }\n let descriptions = toolDescriptionsByCallId.get(callId);\n for (const tool of tools) {\n if (isRecord(tool) && typeof tool.name === 'string' && typeof tool.description === 'string') {\n descriptions = descriptions ?? new Map();\n if (!descriptions.has(tool.name)) {\n descriptions.set(tool.name, tool.description);\n }\n }\n }\n if (descriptions) {\n toolDescriptionsByCallId.set(callId, descriptions);\n }\n}\n\n/**\n * Resolve a tool's description, preferring the per-operation map (populated from the model-call /\n * top-level event's `tools`, v7) and falling back to a `tools` collection on the event itself —\n * which may be an array of `{ name, description }` or a record keyed by tool name (v6).\n */\nfunction resolveToolDescription(callId: string | undefined, toolName: string, tools: unknown): string | undefined {\n const fromMap = callId ? toolDescriptionsByCallId.get(callId)?.get(toolName) : undefined;\n if (fromMap) {\n return fromMap;\n }\n if (Array.isArray(tools)) {\n const match = tools.find(tool => isRecord(tool) && tool.name === toolName);\n return isRecord(match) ? asString(match.description) : undefined;\n }\n if (isRecord(tools)) {\n const tool = tools[toolName];\n return isRecord(tool) ? asString(tool.description) : undefined;\n }\n return undefined;\n}\n\n/** The lifecycle event types the `ai:telemetry` channel can carry. */\nexport type ChannelEventType =\n | 'generateText'\n | 'streamText'\n | 'step'\n | 'languageModelCall'\n | 'executeTool'\n | 'embed'\n | 'rerank';\n\n/**\n * The context object the AI SDK passes through one tracing-channel call. It is the same object\n * identity across `start`/`end`/`asyncEnd`/`error`, and Node's `tracingChannel` attaches\n * `result`/`error` to it as the traced promise settles.\n */\nexport interface VercelAiChannelMessage {\n type: ChannelEventType;\n event: Record<string, unknown>;\n result?: unknown;\n error?: unknown;\n}\n\n/**\n * Platform-provided factory that returns a tracing channel for the given channel name. The factory\n * is responsible for, when `start` fires, calling `transformStart(data)` and storing the returned\n * span on `data._sentrySpan` so the subscriber's `asyncEnd`/`error` handlers can read it.\n *\n * Node passes `@sentry/opentelemetry/tracing-channel`, which uses `bindStore` to additionally make\n * the span the active OTel context for the duration of the traced operation. That is what makes\n * nested AI SDK operations (model calls, tool calls) become children of the enclosing span without\n * any manual parent bookkeeping here.\n */\ntype VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;\n\n/** Integration-level recording options, pinned at subscribe time so we never look the integration up per event. */\ninterface VercelAiChannelOptions {\n recordInputs?: boolean;\n recordOutputs?: boolean;\n enableTruncation?: boolean;\n}\n\nlet subscribed = false;\n\n/**\n * Subscribe Sentry span handlers to the `ai` SDK's native telemetry tracing channel (`ai:telemetry`,\n * available in `ai` >= 7) and emit fully-formed `gen_ai.*` spans directly — no OpenTelemetry span\n * post-processing involved.\n *\n * The integration passes its options in directly (rather than us looking the integration up on every\n * event); the global `dataCollection.genAI` default is still read from the client per event.\n *\n * Safe to always call: on `ai` versions that don't publish to the channel (e.g. < 7) nothing is\n * ever emitted and this is inert, so there is no double-instrumentation against the OTel-based\n * patcher. Idempotent.\n */\nexport function subscribeVercelAiTracingChannel(\n tracingChannel: VercelAiTracingChannelFactory,\n options: VercelAiChannelOptions = {},\n): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n bindTracingChannelToSpan(\n tracingChannel<VercelAiChannelMessage>(AI_SDK_TELEMETRY_TRACING_CHANNEL),\n data => createSpanFromMessage(data, options),\n {\n // The helper ends the span; we enrich it from the settled result first (tokens, output messages,\n // finish reasons, response model/id, provider metadata) and drop the per-operation `callId` maps.\n beforeSpanEnd: (span, data) => {\n enrichSpanOnEnd(span, data, options);\n clearOperationId(data);\n },\n },\n );\n}\n\n/**\n * Transform a channel `start` payload into the span that should be active for the operation. For\n * `step` we deliberately don't open a span (model calls and tool calls are siblings under the\n * invoke_agent span, matching the OTel-based output), so we reuse the active span and mark the\n * payload to skip ending it.\n */\nexport function createSpanFromMessage(\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): Span | undefined {\n const { type, event } = data;\n\n if (type === 'step' || !event || typeof event !== 'object') {\n // Opt out: returning `undefined` leaves the enclosing `invoke_agent` span as the active context\n // (model-call and tool-call events nest under it) without opening — or ending — a span of its own.\n return undefined;\n }\n\n const { recordInputs, enableTruncation } = getRecordingOptions(event, channelOptions);\n const provider = asString(event.provider);\n const modelId = asString(event.modelId);\n const callId = asString(event.callId);\n const maxRetries = asNumber(event.maxRetries);\n\n // Harvest tool descriptions from the operation/model-call `tools` so tool spans can backfill them.\n // Gated on `recordInputs` to match the OTel path, which only records `available_tools` then.\n if (recordInputs) {\n recordToolDescriptions(callId, event.tools);\n }\n\n const baseAttributes: Record<string, string | number | boolean> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n ...(provider ? { [GEN_AI_SYSTEM]: provider, [VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE]: provider } : {}),\n ...(modelId ? { [GEN_AI_REQUEST_MODEL]: modelId } : {}),\n ...(maxRetries !== undefined ? { [VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE]: maxRetries } : {}),\n };\n\n switch (type) {\n case 'generateText':\n case 'streamText':\n return buildInvokeAgentSpan(event, baseAttributes, recordInputs, enableTruncation, callId, type === 'streamText');\n case 'languageModelCall':\n return buildModelCallSpan(event, baseAttributes, recordInputs, enableTruncation, callId, modelId);\n case 'executeTool':\n return buildToolSpan(event, recordInputs);\n case 'embed':\n return startGenAiSpan(GEN_AI_EMBEDDINGS_OPERATION, modelId, {\n ...baseAttributes,\n ...(recordInputs && event.value !== undefined ? { [GEN_AI_EMBEDDINGS_INPUT]: safeStringify(event.value) } : {}),\n });\n case 'rerank':\n return startGenAiSpan(GEN_AI_RERANK_OPERATION, modelId, baseAttributes);\n default:\n // Unknown event type: opt out rather than open a span we can't shape correctly.\n return undefined;\n }\n}\n\ntype Attributes = Record<string, string | number | boolean>;\n\n/** Start a `gen_ai.<operation>` span named `<operation> <suffix>` (or just `<operation>` when no suffix). */\nfunction startGenAiSpan(operation: string, suffix: string | undefined, attributes: Attributes): Span {\n return startInactiveSpan({\n name: suffix ? `${operation} ${suffix}` : operation,\n op: `gen_ai.${operation}`,\n attributes: { [GEN_AI_OPERATION_NAME]: operation, ...attributes },\n });\n}\n\nfunction buildInvokeAgentSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n isStream: boolean,\n): Span {\n const functionId = asString(event.functionId);\n const operationId = asString(event.operationId) ?? (isStream ? 'ai.streamText' : 'ai.generateText');\n if (callId) {\n operationIdByCallId.set(callId, { operationId, isStream });\n }\n return startGenAiSpan(GEN_AI_INVOKE_AGENT_SPAN_OP, functionId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n [GEN_AI_RESPONSE_STREAMING]: isStream,\n ...(functionId ? { [GEN_AI_FUNCTION_ID]: functionId } : {}),\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n });\n}\n\nfunction buildModelCallSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n modelId: string | undefined,\n): Span {\n const parent = callId ? operationIdByCallId.get(callId) : undefined;\n const operationId = parent\n ? `${parent.operationId}.${parent.isStream ? 'doStream' : 'doGenerate'}`\n : 'ai.generateText.doGenerate';\n return startGenAiSpan(GEN_AI_GENERATE_CONTENT_OPERATION, modelId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n ...(recordInputs && Array.isArray(event.tools)\n ? { [GEN_AI_REQUEST_AVAILABLE_TOOLS]: safeStringify(event.tools) }\n : {}),\n });\n}\n\nfunction buildToolSpan(event: Record<string, unknown>, recordInputs: boolean): Span {\n const toolCall = isRecord(event.toolCall) ? event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(event.toolCallId) ?? asString(toolCall.toolCallId);\n const toolInput = toolCall.input ?? toolCall.args;\n // The `executeTool` event has no description; backfill it from the operation's recorded tools.\n // Gated on `recordInputs` to match the OTel path (descriptions come from the recorded tools list).\n const description =\n recordInputs && toolName ? resolveToolDescription(asString(event.callId), toolName, event.tools) : undefined;\n return startGenAiSpan(GEN_AI_EXECUTE_TOOL_SPAN_OP, toolName, {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [GEN_AI_TOOL_TYPE]: 'function',\n ...(toolName ? { [GEN_AI_TOOL_NAME]: toolName } : {}),\n ...(toolCallId ? { [GEN_AI_TOOL_CALL_ID_ATTRIBUTE]: toolCallId } : {}),\n ...(description ? { [GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE]: description } : {}),\n ...(recordInputs && toolInput !== undefined ? { [GEN_AI_TOOL_INPUT]: safeStringify(toolInput) } : {}),\n });\n}\n\n/**\n * Best-effort enrichment from the resolved value the AI SDK attaches to the channel context.\n * Everything here is guarded: when a field is missing or the shape differs across `ai` versions,\n * we simply don't set the attribute rather than emit a malformed span.\n */\nexport function enrichSpanOnEnd(\n span: Span,\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): void {\n const { type, result } = data;\n if (!isRecord(result)) {\n return;\n }\n\n const { recordOutputs } = getRecordingOptions(data.event, channelOptions);\n\n if (type === 'executeTool') {\n if (recordOutputs) {\n span.setAttribute(GEN_AI_TOOL_OUTPUT, safeStringify(result.output ?? result));\n }\n // From V5 on, tool errors are not rejected (so the `error` channel verb never fires) — they\n // surface as `tool-error` content on the resolved result. Mirror the OTel path by marking the\n // span and capturing the error.\n const output = isRecord(result.output) ? result.output : undefined;\n if (output?.type === 'tool-error') {\n captureToolError(span, data, output.error);\n }\n return;\n }\n\n // `languageModelCall` results report usage as `{ total }` objects; top-level/step results report\n // flat numbers. `tokenCount` handles both.\n const usage = isRecord(result.usage) ? result.usage : undefined;\n if (usage) {\n const inputTokens = tokenCount(usage.inputTokens) ?? tokenCount(usage.tokens);\n const outputTokens = tokenCount(usage.outputTokens);\n const totalTokens = tokenCount(usage.totalTokens) ?? sum(inputTokens, outputTokens);\n if (inputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n if (totalTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n }\n\n // Match the OTel integration: finish reasons live on the model-call (`generate_content`) span, not\n // on the top-level `invoke_agent` span.\n const finishReason = getFinishReason(result);\n if (finishReason && type === 'languageModelCall') {\n span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, safeStringify([finishReason]));\n }\n\n const response = isRecord(result.response) ? result.response : undefined;\n const responseId = asString(response?.id) ?? asString(result.responseId);\n if (responseId) {\n span.setAttribute(GEN_AI_RESPONSE_ID, responseId);\n }\n const responseModel = asString(response?.modelId) ?? asString(data.event.modelId);\n if (responseModel) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL, responseModel);\n }\n\n // Provider-specific cache/reasoning/prediction token breakdowns and `gen_ai.conversation.id`.\n // The channel exposes `providerMetadata` as an object (the OTel path parses it from a string);\n // both share `getProviderMetadataAttributes` so the emitted shape is identical.\n const providerMetadata = (result as { providerMetadata?: unknown }).providerMetadata;\n const providerAttributes = getProviderMetadataAttributes(providerMetadata);\n // Don't overwrite a conversation id already set on span start (e.g. by `conversationIdIntegration`\n // from a user-set scope value); the provider-derived id is only a fallback. Matches the OTel path.\n if (\n GEN_AI_CONVERSATION_ID_ATTRIBUTE in providerAttributes &&\n spanToJSON(span).data[GEN_AI_CONVERSATION_ID_ATTRIBUTE]\n ) {\n // oxlint-disable-next-line typescript/no-dynamic-delete\n delete providerAttributes[GEN_AI_CONVERSATION_ID_ATTRIBUTE];\n }\n span.setAttributes(providerAttributes);\n\n if (recordOutputs) {\n // `languageModelCall` exposes the response as a `content` parts array; top-level results expose\n // `text` + `toolCalls`. Both normalize into the OTel `gen_ai.output.messages` assistant message.\n const parts =\n type === 'languageModelCall' && Array.isArray(result.content)\n ? partsFromContent(result.content)\n : partsFromTextAndToolCalls(result.text, result.toolCalls);\n const outputMessages = buildOutputMessages(parts, finishReason);\n if (outputMessages) {\n span.setAttribute(GEN_AI_OUTPUT_MESSAGES, outputMessages);\n }\n }\n}\n\n/** Maps a Vercel AI finish reason to the OTel `gen_ai.output.messages` form (`tool-calls` → `tool_call`). */\nfunction normalizeFinishReason(finishReason: string | undefined): string {\n return finishReason === 'tool-calls' ? 'tool_call' : (finishReason ?? 'stop');\n}\n\n/** Reads the finish reason from a result — a string on top-level results, `{ unified }` on model calls. */\nfunction getFinishReason(result: Record<string, unknown>): string | undefined {\n const finishReason = result.finishReason;\n if (typeof finishReason === 'string') {\n return finishReason;\n }\n return isRecord(finishReason) ? asString(finishReason.unified) : undefined;\n}\n\n/** Reads a token count that may be a plain number or a `{ total }` object (model-call usage). */\nfunction tokenCount(value: unknown): number | undefined {\n return asNumber(value) ?? (isRecord(value) ? asNumber(value.total) : undefined);\n}\n\nfunction buildOutputMessages(\n parts: Array<Record<string, unknown>>,\n finishReason: string | undefined,\n): string | undefined {\n if (!parts.length) {\n return undefined;\n }\n return safeStringify([{ role: 'assistant', parts, finish_reason: normalizeFinishReason(finishReason) }]);\n}\n\nfunction toolCallPart(toolCall: Record<string, unknown>): Record<string, unknown> {\n const args = toolCall.input ?? toolCall.args;\n return {\n type: 'tool_call',\n id: asString(toolCall.toolCallId),\n name: asString(toolCall.toolName),\n arguments: typeof args === 'string' ? args : safeStringify(args ?? {}),\n };\n}\n\nfunction partsFromContent(content: unknown[]): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n for (const item of content) {\n if (!isRecord(item)) {\n continue;\n }\n if (item.type === 'text' && typeof item.text === 'string') {\n parts.push({ type: 'text', content: item.text });\n } else if (item.type === 'tool-call') {\n parts.push(toolCallPart(item));\n }\n }\n return parts;\n}\n\nfunction partsFromTextAndToolCalls(text: unknown, toolCalls: unknown): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n if (typeof text === 'string' && text.length) {\n parts.push({ type: 'text', content: text });\n }\n if (Array.isArray(toolCalls)) {\n for (const toolCall of toolCalls) {\n if (isRecord(toolCall)) {\n parts.push(toolCallPart(toolCall));\n }\n }\n }\n return parts;\n}\n\nfunction captureToolError(span: Span, data: VercelAiChannelMessage, error: unknown): void {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: error instanceof Error ? error.message : 'tool_error',\n });\n\n const toolCall = isRecord(data.event.toolCall) ? data.event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(data.event.toolCallId) ?? asString(toolCall.toolCallId);\n\n withScope(scope => {\n scope.setContext('trace', spanToTraceContext(span));\n if (toolName) {\n scope.setTag('vercel.ai.tool.name', toolName);\n }\n if (toolCallId) {\n scope.setTag('vercel.ai.tool.callId', toolCallId);\n }\n scope.setLevel('error');\n captureException(\n error instanceof Error ? error : new Error(typeof error === 'string' ? error : 'Tool execution failed'),\n {\n mechanism: { type: 'auto.vercelai.channel', handled: false },\n },\n );\n });\n}\n\nfunction getRecordingOptions(\n event: Record<string, unknown>,\n channelOptions: VercelAiChannelOptions,\n): {\n recordInputs: boolean;\n recordOutputs: boolean;\n enableTruncation: boolean;\n} {\n const genAI = getClient()?.getDataCollectionOptions().genAI;\n\n return {\n recordInputs: resolveRecording(channelOptions.recordInputs, event.recordInputs, genAI?.inputs),\n recordOutputs: resolveRecording(channelOptions.recordOutputs, event.recordOutputs, genAI?.outputs),\n enableTruncation: shouldEnableTruncation(channelOptions.enableTruncation),\n };\n}\n\n/**\n * Mirrors the OTel integration's `determineRecordingSettings` precedence: an integration-level option\n * wins, then the per-call `experimental_telemetry.recordInputs/recordOutputs` flag the AI SDK forwards\n * on the channel event, then the global `dataCollection.genAI` default.\n *\n * NOTE: the OTel integration also defaults recording to `true` for a call with\n * `experimental_telemetry: { isEnabled: true }`. The `ai:telemetry` channel does not expose `isEnabled`\n * (nor a resolved recording flag), so that per-call default cannot be reproduced here — v7 users who\n * want inputs/outputs recorded must enable `dataCollection.genAI` or set `recordInputs`/`recordOutputs`.\n */\nfunction resolveRecording(integrationOption: unknown, perCallOption: unknown, globalDefault: unknown): boolean {\n if (typeof integrationOption === 'boolean') {\n return integrationOption;\n }\n if (typeof perCallOption === 'boolean') {\n return perCallOption;\n }\n return globalDefault === true;\n}\n\nfunction buildInputMessageAttributes(\n event: Record<string, unknown>,\n enableTruncation: boolean,\n): Record<string, string | number> {\n const attributes: Record<string, string | number> = {};\n\n // `ai` >= 7 forbids system messages in `messages`/`prompt` and exposes the system prompt as a\n // separate `instructions` field. The OTel path lifts the system message out of the prompt into\n // `gen_ai.system_instructions` as `[{ type: 'text', content }]`; mirror that shape here.\n const instructions = asString(event.instructions);\n if (instructions) {\n attributes[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE] = safeStringify([{ type: 'text', content: instructions }]);\n }\n\n // The AI SDK start events extend `StandardizedPrompt`; messages live on `messages`, otherwise the\n // simpler `prompt` field is used.\n const messages = event.messages ?? event.prompt;\n if (messages !== undefined) {\n attributes[GEN_AI_INPUT_MESSAGES] = enableTruncation ? getTruncatedJsonString(messages) : safeStringify(messages);\n // The original (pre-truncation) message count, so the product can show how many were dropped.\n attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE] = Array.isArray(messages) ? messages.length : 1;\n }\n\n return attributes;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && !isNaN(value) ? value : undefined;\n}\n\nfunction sum(a: number | undefined, b: number | undefined): number | undefined {\n return a === undefined && b === undefined ? undefined : (a ?? 0) + (b ?? 0);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return '[unserializable]';\n }\n}\n"],"names":[],"mappings":";;;;;AAqDA,MAAM,gCAAA,GAAmC,cAAA;AAEzC,MAAM,MAAA,GAAS,uBAAA;AAGf,MAAM,6BAAA,GAAgC,qBAAA;AACtC,MAAM,iCAAA,GAAoC,yBAAA;AAC1C,MAAM,2BAAA,GAA8B,YAAA;AACpC,MAAM,uBAAA,GAA0B,QAAA;AAGhC,MAAM,iCAAA,GAAoC,kBAAA;AAG1C,MAAM,gCAAA,GAAmC,uBAAA;AACzC,MAAM,kCAAA,GAAqC,0BAAA;AAC3C,MAAM,wCAAA,GAA2C,+BAAA;AAMjD,MAAM,mBAAA,uBAA0B,GAAA,EAAwD;AASxF,MAAM,wBAAA,uBAA+B,GAAA,EAAiC;AAItE,MAAM,oBAAA,uBAA2B,GAAA,CAAsB,CAAC,gBAAgB,YAAA,EAAc,OAAA,EAAS,QAAQ,CAAC,CAAA;AAGjG,SAAS,iBAAiB,IAAA,EAAoC;AACnE,EAAA,IAAI,CAAC,oBAAA,CAAqB,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAG;AACxC,IAAA;AAAA,EACF;AACA,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AACzC,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,mBAAA,CAAoB,OAAO,MAAM,CAAA;AACjC,IAAA,wBAAA,CAAyB,OAAO,MAAM,CAAA;AAAA,EACxC;AACF;AAGA,SAAS,sBAAA,CAAuB,QAA4B,KAAA,EAAsB;AAChF,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACpC,IAAA;AAAA,EACF;AACA,EAAA,IAAI,YAAA,GAAe,wBAAA,CAAyB,GAAA,CAAI,MAAM,CAAA;AACtD,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,QAAA,CAAS,IAAI,CAAA,IAAK,OAAO,IAAA,CAAK,SAAS,QAAA,IAAY,OAAO,IAAA,CAAK,WAAA,KAAgB,QAAA,EAAU;AAC3F,MAAA,YAAA,GAAe,YAAA,wBAAoB,GAAA,EAAI;AACvC,MAAA,IAAI,CAAC,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAG;AAChC,QAAA,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,WAAW,CAAA;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,wBAAA,CAAyB,GAAA,CAAI,QAAQ,YAAY,CAAA;AAAA,EACnD;AACF;AAOA,SAAS,sBAAA,CAAuB,MAAA,EAA4B,QAAA,EAAkB,KAAA,EAAoC;AAChH,EAAA,MAAM,OAAA,GAAU,SAAS,wBAAA,CAAyB,GAAA,CAAI,MAAM,CAAA,EAAG,GAAA,CAAI,QAAQ,CAAA,GAAI,MAAA;AAC/E,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAO,OAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,CAAA,IAAA,KAAQ,SAAS,IAAI,CAAA,IAAK,IAAA,CAAK,IAAA,KAAS,QAAQ,CAAA;AACzE,IAAA,OAAO,SAAS,KAAK,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,WAAW,CAAA,GAAI,MAAA;AAAA,EACzD;AACA,EAAA,IAAI,QAAA,CAAS,KAAK,CAAA,EAAG;AACnB,IAAA,MAAM,IAAA,GAAO,MAAM,QAAQ,CAAA;AAC3B,IAAA,OAAO,SAAS,IAAI,CAAA,GAAI,QAAA,CAAS,IAAA,CAAK,WAAW,CAAA,GAAI,MAAA;AAAA,EACvD;AACA,EAAA,OAAO,MAAA;AACT;AA2CA,IAAI,UAAA,GAAa,KAAA;AAcV,SAAS,+BAAA,CACd,cAAA,EACA,OAAA,GAAkC,EAAC,EAC7B;AACN,EAAA,IAAI,UAAA,EAAY;AACd,IAAA;AAAA,EACF;AACA,EAAA,UAAA,GAAa,IAAA;AAEb,EAAA,wBAAA;AAAA,IACE,eAAuC,gCAAgC,CAAA;AAAA,IACvE,CAAA,IAAA,KAAQ,qBAAA,CAAsB,IAAA,EAAM,OAAO,CAAA;AAAA,IAC3C;AAAA;AAAA;AAAA,MAGE,aAAA,EAAe,CAAC,IAAA,EAAM,IAAA,KAAS;AAC7B,QAAA,eAAA,CAAgB,IAAA,EAAM,MAAM,OAAO,CAAA;AACnC,QAAA,gBAAA,CAAiB,IAAI,CAAA;AAAA,MACvB;AAAA;AACF,GACF;AACF;AAQO,SAAS,qBAAA,CACd,MACA,cAAA,EACkB;AAClB,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,IAAA;AAExB,EAAA,IAAI,SAAS,MAAA,IAAU,CAAC,KAAA,IAAS,OAAO,UAAU,QAAA,EAAU;AAG1D,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,YAAA,EAAc,gBAAA,EAAiB,GAAI,mBAAA,CAAoB,OAAO,cAAc,CAAA;AACpF,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA;AACtC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA;AACpC,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,CAAM,UAAU,CAAA;AAI5C,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,sBAAA,CAAuB,MAAA,EAAQ,MAAM,KAAK,CAAA;AAAA,EAC5C;AAEA,EAAA,MAAM,cAAA,GAA4D;AAAA,IAChE,CAAC,gCAAgC,GAAG,MAAA;AAAA,IACpC,GAAI,QAAA,GAAW,EAAE,CAAC,aAAa,GAAG,QAAA,EAAU,CAAC,kCAAkC,GAAG,QAAA,EAAS,GAAI,EAAC;AAAA,IAChG,GAAI,UAAU,EAAE,CAAC,oBAAoB,GAAG,OAAA,KAAY,EAAC;AAAA,IACrD,GAAI,eAAe,MAAA,GAAY,EAAE,CAAC,wCAAwC,GAAG,UAAA,EAAW,GAAI;AAAC,GAC/F;AAEA,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,cAAA;AAAA,IACL,KAAK,YAAA;AACH,MAAA,OAAO,qBAAqB,KAAA,EAAO,cAAA,EAAgB,cAAc,gBAAA,EAAkB,MAAA,EAAQ,SAAS,YAAY,CAAA;AAAA,IAClH,KAAK,mBAAA;AACH,MAAA,OAAO,mBAAmB,KAAA,EAAO,cAAA,EAAgB,YAAA,EAAc,gBAAA,EAAkB,QAAQ,OAAO,CAAA;AAAA,IAClG,KAAK,aAAA;AACH,MAAA,OAAO,aAAA,CAAc,OAAO,YAAY,CAAA;AAAA,IAC1C,KAAK,OAAA;AACH,MAAA,OAAO,cAAA,CAAe,6BAA6B,OAAA,EAAS;AAAA,QAC1D,GAAG,cAAA;AAAA,QACH,GAAI,YAAA,IAAgB,KAAA,CAAM,KAAA,KAAU,SAAY,EAAE,CAAC,uBAAuB,GAAG,aAAA,CAAc,KAAA,CAAM,KAAK,CAAA,KAAM;AAAC,OAC9G,CAAA;AAAA,IACH,KAAK,QAAA;AACH,MAAA,OAAO,cAAA,CAAe,uBAAA,EAAyB,OAAA,EAAS,cAAc,CAAA;AAAA,IACxE;AAEE,MAAA,OAAO,MAAA;AAAA;AAEb;AAKA,SAAS,cAAA,CAAe,SAAA,EAAmB,MAAA,EAA4B,UAAA,EAA8B;AACnG,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,MAAM,MAAA,GAAS,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,GAAK,SAAA;AAAA,IAC1C,EAAA,EAAI,UAAU,SAAS,CAAA,CAAA;AAAA,IACvB,YAAY,EAAE,CAAC,qBAAqB,GAAG,SAAA,EAAW,GAAG,UAAA;AAAW,GACjE,CAAA;AACH;AAEA,SAAS,qBACP,KAAA,EACA,cAAA,EACA,YAAA,EACA,gBAAA,EACA,QACA,QAAA,EACM;AACN,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,CAAM,UAAU,CAAA;AAC5C,EAAA,MAAM,cAAc,QAAA,CAAS,KAAA,CAAM,WAAW,CAAA,KAAM,WAAW,eAAA,GAAkB,iBAAA,CAAA;AACjF,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,mBAAA,CAAoB,GAAA,CAAI,MAAA,EAAQ,EAAE,WAAA,EAAa,UAAU,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,cAAA,CAAe,6BAA6B,UAAA,EAAY;AAAA,IAC7D,GAAG,cAAA;AAAA,IACH,CAAC,gCAAgC,GAAG,WAAA;AAAA,IACpC,CAAC,yBAAyB,GAAG,QAAA;AAAA,IAC7B,GAAI,aAAa,EAAE,CAAC,kBAAkB,GAAG,UAAA,KAAe,EAAC;AAAA,IACzD,GAAI,YAAA,GAAe,2BAAA,CAA4B,KAAA,EAAO,gBAAgB,IAAI;AAAC,GAC5E,CAAA;AACH;AAEA,SAAS,mBACP,KAAA,EACA,cAAA,EACA,YAAA,EACA,gBAAA,EACA,QACA,OAAA,EACM;AACN,EAAA,MAAM,MAAA,GAAS,MAAA,GAAS,mBAAA,CAAoB,GAAA,CAAI,MAAM,CAAA,GAAI,MAAA;AAC1D,EAAA,MAAM,WAAA,GAAc,MAAA,GAChB,CAAA,EAAG,MAAA,CAAO,WAAW,IAAI,MAAA,CAAO,QAAA,GAAW,UAAA,GAAa,YAAY,CAAA,CAAA,GACpE,4BAAA;AACJ,EAAA,OAAO,cAAA,CAAe,mCAAmC,OAAA,EAAS;AAAA,IAChE,GAAG,cAAA;AAAA,IACH,CAAC,gCAAgC,GAAG,WAAA;AAAA,IACpC,GAAI,YAAA,GAAe,2BAAA,CAA4B,KAAA,EAAO,gBAAgB,IAAI,EAAC;AAAA,IAC3E,GAAI,YAAA,IAAgB,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,GACzC,EAAE,CAAC,8BAA8B,GAAG,aAAA,CAAc,KAAA,CAAM,KAAK,CAAA,KAC7D;AAAC,GACN,CAAA;AACH;AAEA,SAAS,aAAA,CAAc,OAAgC,YAAA,EAA6B;AAClF,EAAA,MAAM,WAAW,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,GAAI,KAAA,CAAM,WAAW,EAAC;AAC9D,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA;AAC3C,EAAA,MAAM,aAAa,QAAA,CAAS,KAAA,CAAM,UAAU,CAAA,IAAK,QAAA,CAAS,SAAS,UAAU,CAAA;AAC7E,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,KAAA,IAAS,QAAA,CAAS,IAAA;AAG7C,EAAA,MAAM,WAAA,GACJ,YAAA,IAAgB,QAAA,GAAW,sBAAA,CAAuB,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA,EAAG,QAAA,EAAU,KAAA,CAAM,KAAK,CAAA,GAAI,MAAA;AACrG,EAAA,OAAO,cAAA,CAAe,6BAA6B,QAAA,EAAU;AAAA,IAC3D,CAAC,gCAAgC,GAAG,MAAA;AAAA,IACpC,CAAC,gBAAgB,GAAG,UAAA;AAAA,IACpB,GAAI,WAAW,EAAE,CAAC,gBAAgB,GAAG,QAAA,KAAa,EAAC;AAAA,IACnD,GAAI,aAAa,EAAE,CAAC,6BAA6B,GAAG,UAAA,KAAe,EAAC;AAAA,IACpE,GAAI,cAAc,EAAE,CAAC,iCAAiC,GAAG,WAAA,KAAgB,EAAC;AAAA,IAC1E,GAAI,YAAA,IAAgB,SAAA,KAAc,MAAA,GAAY,EAAE,CAAC,iBAAiB,GAAG,aAAA,CAAc,SAAS,CAAA,EAAE,GAAI;AAAC,GACpG,CAAA;AACH;AAOO,SAAS,eAAA,CACd,IAAA,EACA,IAAA,EACA,cAAA,EACM;AACN,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,IAAA;AACzB,EAAA,IAAI,CAAC,QAAA,CAAS,MAAM,CAAA,EAAG;AACrB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,mBAAA,CAAoB,IAAA,CAAK,OAAO,cAAc,CAAA;AAExE,EAAA,IAAI,SAAS,aAAA,EAAe;AAC1B,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,IAAA,CAAK,aAAa,kBAAA,EAAoB,aAAA,CAAc,MAAA,CAAO,MAAA,IAAU,MAAM,CAAC,CAAA;AAAA,IAC9E;AAIA,IAAA,MAAM,SAAS,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,GAAI,OAAO,MAAA,GAAS,MAAA;AACzD,IAAA,IAAI,MAAA,EAAQ,SAAS,YAAA,EAAc;AACjC,MAAA,gBAAA,CAAiB,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,KAAK,CAAA;AAAA,IAC3C;AACA,IAAA;AAAA,EACF;AAIA,EAAA,MAAM,QAAQ,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA,GAAI,OAAO,KAAA,GAAQ,MAAA;AACtD,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,cAAc,UAAA,CAAW,KAAA,CAAM,WAAW,CAAA,IAAK,UAAA,CAAW,MAAM,MAAM,CAAA;AAC5E,IAAA,MAAM,YAAA,GAAe,UAAA,CAAW,KAAA,CAAM,YAAY,CAAA;AAClD,IAAA,MAAM,cAAc,UAAA,CAAW,KAAA,CAAM,WAAW,CAAA,IAAK,GAAA,CAAI,aAAa,YAAY,CAAA;AAClF,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,IAAA,CAAK,YAAA,CAAa,2BAA2B,WAAW,CAAA;AAAA,IAC1D;AACA,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,IAAA,CAAK,YAAA,CAAa,4BAA4B,YAAY,CAAA;AAAA,IAC5D;AACA,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,IAAA,CAAK,YAAA,CAAa,2BAA2B,WAAW,CAAA;AAAA,IAC1D;AAAA,EACF;AAIA,EAAA,MAAM,YAAA,GAAe,gBAAgB,MAAM,CAAA;AAC3C,EAAA,IAAI,YAAA,IAAgB,SAAS,mBAAA,EAAqB;AAChD,IAAA,IAAA,CAAK,aAAa,8BAAA,EAAgC,aAAA,CAAc,CAAC,YAAY,CAAC,CAAC,CAAA;AAAA,EACjF;AAEA,EAAA,MAAM,WAAW,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA,GAAI,OAAO,QAAA,GAAW,MAAA;AAC/D,EAAA,MAAM,aAAa,QAAA,CAAS,QAAA,EAAU,EAAE,CAAA,IAAK,QAAA,CAAS,OAAO,UAAU,CAAA;AACvE,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,IAAA,CAAK,YAAA,CAAa,oBAAoB,UAAU,CAAA;AAAA,EAClD;AACA,EAAA,MAAM,aAAA,GAAgB,SAAS,QAAA,EAAU,OAAO,KAAK,QAAA,CAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AAChF,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,IAAA,CAAK,YAAA,CAAa,uBAAuB,aAAa,CAAA;AAAA,EACxD;AAKA,EAAA,MAAM,mBAAoB,MAAA,CAA0C,gBAAA;AACpE,EAAA,MAAM,kBAAA,GAAqB,8BAA8B,gBAAgB,CAAA;AAGzE,EAAA,IACE,oCAAoC,kBAAA,IACpC,UAAA,CAAW,IAAI,CAAA,CAAE,IAAA,CAAK,gCAAgC,CAAA,EACtD;AAEA,IAAA,OAAO,mBAAmB,gCAAgC,CAAA;AAAA,EAC5D;AACA,EAAA,IAAA,CAAK,cAAc,kBAAkB,CAAA;AAErC,EAAA,IAAI,aAAA,EAAe;AAGjB,IAAA,MAAM,QACJ,IAAA,KAAS,mBAAA,IAAuB,KAAA,CAAM,OAAA,CAAQ,OAAO,OAAO,CAAA,GACxD,gBAAA,CAAiB,MAAA,CAAO,OAAO,CAAA,GAC/B,yBAAA,CAA0B,MAAA,CAAO,IAAA,EAAM,OAAO,SAAS,CAAA;AAC7D,IAAA,MAAM,cAAA,GAAiB,mBAAA,CAAoB,KAAA,EAAO,YAAY,CAAA;AAC9D,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,IAAA,CAAK,YAAA,CAAa,wBAAwB,cAAc,CAAA;AAAA,IAC1D;AAAA,EACF;AACF;AAGA,SAAS,sBAAsB,YAAA,EAA0C;AACvE,EAAA,OAAO,YAAA,KAAiB,YAAA,GAAe,WAAA,GAAe,YAAA,IAAgB,MAAA;AACxE;AAGA,SAAS,gBAAgB,MAAA,EAAqD;AAC5E,EAAA,MAAM,eAAe,MAAA,CAAO,YAAA;AAC5B,EAAA,IAAI,OAAO,iBAAiB,QAAA,EAAU;AACpC,IAAA,OAAO,YAAA;AAAA,EACT;AACA,EAAA,OAAO,SAAS,YAAY,CAAA,GAAI,QAAA,CAAS,YAAA,CAAa,OAAO,CAAA,GAAI,MAAA;AACnE;AAGA,SAAS,WAAW,KAAA,EAAoC;AACtD,EAAA,OAAO,QAAA,CAAS,KAAK,CAAA,KAAM,QAAA,CAAS,KAAK,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA,GAAI,MAAA,CAAA;AACvE;AAEA,SAAS,mBAAA,CACP,OACA,YAAA,EACoB;AACpB,EAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,CAAc,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,KAAA,EAAO,aAAA,EAAe,qBAAA,CAAsB,YAAY,CAAA,EAAG,CAAC,CAAA;AACzG;AAEA,SAAS,aAAa,QAAA,EAA4D;AAChF,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,IAAS,QAAA,CAAS,IAAA;AACxC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,EAAA,EAAI,QAAA,CAAS,QAAA,CAAS,UAAU,CAAA;AAAA,IAChC,IAAA,EAAM,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA;AAAA,IAChC,SAAA,EAAW,OAAO,IAAA,KAAS,QAAA,GAAW,OAAO,aAAA,CAAc,IAAA,IAAQ,EAAE;AAAA,GACvE;AACF;AAEA,SAAS,iBAAiB,OAAA,EAAoD;AAC5E,EAAA,MAAM,QAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAC1B,IAAA,IAAI,CAAC,QAAA,CAAS,IAAI,CAAA,EAAG;AACnB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAK,IAAA,KAAS,MAAA,IAAU,OAAO,IAAA,CAAK,SAAS,QAAA,EAAU;AACzD,MAAA,KAAA,CAAM,KAAK,EAAE,IAAA,EAAM,QAAQ,OAAA,EAAS,IAAA,CAAK,MAAM,CAAA;AAAA,IACjD,CAAA,MAAA,IAAW,IAAA,CAAK,IAAA,KAAS,WAAA,EAAa;AACpC,MAAA,KAAA,CAAM,IAAA,CAAK,YAAA,CAAa,IAAI,CAAC,CAAA;AAAA,IAC/B;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,yBAAA,CAA0B,MAAe,SAAA,EAAoD;AACpG,EAAA,MAAM,QAAwC,EAAC;AAC/C,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,MAAA,EAAQ;AAC3C,IAAA,KAAA,CAAM,KAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC5B,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAI,QAAA,CAAS,QAAQ,CAAA,EAAG;AACtB,QAAA,KAAA,CAAM,IAAA,CAAK,YAAA,CAAa,QAAQ,CAAC,CAAA;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,gBAAA,CAAiB,IAAA,EAAY,IAAA,EAA8B,KAAA,EAAsB;AACxF,EAAA,IAAA,CAAK,SAAA,CAAU;AAAA,IACb,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU;AAAA,GACnD,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,SAAS,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,EAAC;AACxE,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA;AAC3C,EAAA,MAAM,UAAA,GAAa,SAAS,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA,IAAK,QAAA,CAAS,SAAS,UAAU,CAAA;AAElF,EAAA,SAAA,CAAU,CAAA,KAAA,KAAS;AACjB,IAAA,KAAA,CAAM,UAAA,CAAW,OAAA,EAAS,kBAAA,CAAmB,IAAI,CAAC,CAAA;AAClD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,KAAA,CAAM,MAAA,CAAO,uBAAuB,QAAQ,CAAA;AAAA,IAC9C;AACA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,KAAA,CAAM,MAAA,CAAO,yBAAyB,UAAU,CAAA;AAAA,IAClD;AACA,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,gBAAA;AAAA,MACE,KAAA,YAAiB,QAAQ,KAAA,GAAQ,IAAI,MAAM,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,uBAAuB,CAAA;AAAA,MACtG;AAAA,QACE,SAAA,EAAW,EAAE,IAAA,EAAM,uBAAA,EAAyB,SAAS,KAAA;AAAM;AAC7D,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAEA,SAAS,mBAAA,CACP,OACA,cAAA,EAKA;AACA,EAAA,MAAM,KAAA,GAAQ,SAAA,EAAU,EAAG,wBAAA,EAAyB,CAAE,KAAA;AAEtD,EAAA,OAAO;AAAA,IACL,cAAc,gBAAA,CAAiB,cAAA,CAAe,cAAc,KAAA,CAAM,YAAA,EAAc,OAAO,MAAM,CAAA;AAAA,IAC7F,eAAe,gBAAA,CAAiB,cAAA,CAAe,eAAe,KAAA,CAAM,aAAA,EAAe,OAAO,OAAO,CAAA;AAAA,IACjG,gBAAA,EAAkB,sBAAA,CAAuB,cAAA,CAAe,gBAAgB;AAAA,GAC1E;AACF;AAYA,SAAS,gBAAA,CAAiB,iBAAA,EAA4B,aAAA,EAAwB,aAAA,EAAiC;AAC7G,EAAA,IAAI,OAAO,sBAAsB,SAAA,EAAW;AAC1C,IAAA,OAAO,iBAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAO,kBAAkB,SAAA,EAAW;AACtC,IAAA,OAAO,aAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,KAAkB,IAAA;AAC3B;AAEA,SAAS,2BAAA,CACP,OACA,gBAAA,EACiC;AACjC,EAAA,MAAM,aAA8C,EAAC;AAKrD,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,KAAA,CAAM,YAAY,CAAA;AAChD,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,UAAA,CAAW,oCAAoC,CAAA,GAAI,aAAA,CAAc,CAAC,EAAE,MAAM,MAAA,EAAQ,OAAA,EAAS,YAAA,EAAc,CAAC,CAAA;AAAA,EAC5G;AAIA,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,MAAA;AACzC,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,UAAA,CAAW,qBAAqB,CAAA,GAAI,gBAAA,GAAmB,uBAAuB,QAAQ,CAAA,GAAI,cAAc,QAAQ,CAAA;AAEhH,IAAA,UAAA,CAAW,+CAA+C,CAAA,GAAI,KAAA,CAAM,QAAQ,QAAQ,CAAA,GAAI,SAAS,MAAA,GAAS,CAAA;AAAA,EAC5G;AAEA,EAAA,OAAO,UAAA;AACT;AAEA,SAAS,SAAS,KAAA,EAAoC;AACpD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,MAAA;AAC7C;AAEA,SAAS,SAAS,KAAA,EAAoC;AACpD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,KAAK,IAAI,KAAA,GAAQ,MAAA;AAC9D;AAEA,SAAS,GAAA,CAAI,GAAuB,CAAA,EAA2C;AAC7E,EAAA,OAAO,MAAM,MAAA,IAAa,CAAA,KAAM,SAAY,MAAA,GAAA,CAAa,CAAA,IAAK,MAAM,CAAA,IAAK,CAAA,CAAA;AAC3E;AAEA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA;AAChD;AAEA,SAAS,cAAc,KAAA,EAAwB;AAC7C,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,kBAAA;AAAA,EACT;AACF;;;;"}
{"version":3,"file":"vercel-ai-dc-subscriber.js","sources":["../../../src/vercel-ai/vercel-ai-dc-subscriber.ts"],"sourcesContent":["/* eslint-disable max-lines */\n// `@sentry/conventions` marks several gen_ai attributes (e.g. `GEN_AI_SYSTEM`, `GEN_AI_TOOL_*`,\n// `GEN_AI_REQUEST_AVAILABLE_TOOLS`) as deprecated in favour of newer semconv names. We intentionally\n// keep emitting the current names so these spans match the OTel-based (v6) integration and what the\n// Sentry product consumes today; migrating to the new names is a separate, coordinated change.\n/* eslint-disable typescript-eslint/no-deprecated */\nimport {\n GEN_AI_EMBEDDINGS_INPUT,\n GEN_AI_FUNCTION_ID,\n GEN_AI_INPUT_MESSAGES,\n GEN_AI_OPERATION_NAME,\n GEN_AI_OUTPUT_MESSAGES,\n GEN_AI_REQUEST_AVAILABLE_TOOLS,\n GEN_AI_REQUEST_MODEL,\n GEN_AI_RESPONSE_FINISH_REASONS,\n GEN_AI_RESPONSE_ID,\n GEN_AI_RESPONSE_MODEL,\n GEN_AI_RESPONSE_STREAMING,\n GEN_AI_SYSTEM,\n GEN_AI_TOOL_INPUT,\n GEN_AI_TOOL_NAME,\n GEN_AI_TOOL_OUTPUT,\n GEN_AI_TOOL_TYPE,\n GEN_AI_USAGE_INPUT_TOKENS,\n GEN_AI_USAGE_OUTPUT_TOKENS,\n GEN_AI_USAGE_TOTAL_TOKENS,\n} from '@sentry/conventions/attributes';\nimport { GEN_AI_EXECUTE_TOOL_SPAN_OP, GEN_AI_INVOKE_AGENT_SPAN_OP } from '@sentry/conventions/op';\nimport type { Span } from '@sentry/core';\nimport {\n captureException,\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n getClient,\n getProviderMetadataAttributes,\n getTruncatedJsonString,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n shouldEnableTruncation,\n SPAN_STATUS_ERROR,\n spanToJSON,\n spanToTraceContext,\n startInactiveSpan,\n withScope,\n} from '@sentry/core';\nimport type { TracingChannel } from 'node:diagnostics_channel';\nimport { bindTracingChannelToSpan } from '../tracing-channel';\n\n/**\n * The single tracing channel the `ai` package (>= 7) publishes all telemetry lifecycle events to\n * via `node:diagnostics_channel`. Events are discriminated by their `type` field.\n * @see https://github.com/vercel/ai/pull/15660\n */\nconst AI_SDK_TELEMETRY_TRACING_CHANNEL = 'ai:telemetry';\n\nconst ORIGIN = 'auto.vercelai.channel';\n\n// `@sentry/conventions` does not expose these yet, so we keep the literals here.\nconst GEN_AI_TOOL_CALL_ID_ATTRIBUTE = 'gen_ai.tool.call.id';\nconst GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE = 'gen_ai.tool.description';\nconst GEN_AI_EMBEDDINGS_OPERATION = 'embeddings';\nconst GEN_AI_RERANK_OPERATION = 'rerank';\n// The model-call op matches the Vercel AI OTel integration (`gen_ai.generate_content`) rather than\n// the generic `gen_ai.chat`, so v6 (OTel) and v7 (channel) produce the same spans.\nconst GEN_AI_GENERATE_CONTENT_OPERATION = 'generate_content';\n\n// Subset of the `vercel.ai.*` passthrough attributes the OTel integration emits that we reproduce.\nconst VERCEL_AI_OPERATION_ID_ATTRIBUTE = 'vercel.ai.operationId';\nconst VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE = 'vercel.ai.model.provider';\nconst VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE = 'vercel.ai.settings.maxRetries';\n\n// Tracks the top-level operationId (and whether it streams) per `callId` so a model-call span can\n// name its `doGenerate`/`doStream` operation the same way the OTel integration does. `isStream` is\n// the authoritative event-type signal rather than a substring check on the (possibly custom)\n// operationId. Cleared when the top-level span ends.\nconst operationIdByCallId = new Map<string, { operationId: string; isStream: boolean }>();\n\n// Per-operation map of tool name → description, harvested from a model-call /\n// top-level event's `tools` (keyed by the shared `callId`). The AI SDK's\n// `executeTool` event doesn't carry the tool's description, so we backfill it\n// onto the tool span here — without relying on the OTel `vercelAiEventProcessor`\n// (which isn't registered in channel/orchestrion mode). Cleared with the\n// operation. Only populated when inputs are recorded, matching the OTel path\n// (which sources descriptions from the recorded `available_tools`).\nconst toolDescriptionsByCallId = new Map<string, Map<string, string>>();\n\n// Only top-level operations own the `callId` → operationId mapping; `step`/`languageModelCall`/\n// `executeTool` share the parent's `callId`, so they must not clear it.\nconst ROOT_OPERATION_TYPES = new Set<ChannelEventType>(['generateText', 'streamText', 'embed', 'embedMany', 'rerank']);\n\n/** Drop the per-operation `callId` maps once the owning top-level operation settles (success or error). */\nexport function clearOperationId(data: VercelAiChannelMessage): void {\n if (!ROOT_OPERATION_TYPES.has(data.type)) {\n return;\n }\n const callId = asString(data.event.callId);\n if (callId) {\n clearOperationCallId(callId);\n }\n}\n\n/**\n * Drop the per-operation `callId` maps for a single id. The v6 orchestrion adapter uses this to clear a\n * `streamText` operation only after its lazily-run model call settles — the operation's own span ends\n * synchronously (when `streamText` returns) but the model call runs later as the stream is consumed, and\n * it still needs the operation's `operationId`/`isStream` entry to name itself `ai.streamText.doStream`.\n */\nexport function clearOperationCallId(callId: string): void {\n operationIdByCallId.delete(callId);\n toolDescriptionsByCallId.delete(callId);\n}\n\n/** Record tool name → description from an event's `tools`, so tool spans can backfill the description. */\nfunction recordToolDescriptions(callId: string | undefined, tools: unknown): void {\n if (!callId || !Array.isArray(tools)) {\n return;\n }\n let descriptions = toolDescriptionsByCallId.get(callId);\n for (const tool of tools) {\n if (isRecord(tool) && typeof tool.name === 'string' && typeof tool.description === 'string') {\n descriptions = descriptions ?? new Map();\n if (!descriptions.has(tool.name)) {\n descriptions.set(tool.name, tool.description);\n }\n }\n }\n if (descriptions) {\n toolDescriptionsByCallId.set(callId, descriptions);\n }\n}\n\n/**\n * Resolve a tool's description, preferring the per-operation map (populated from the model-call /\n * top-level event's `tools`, v7) and falling back to a `tools` collection on the event itself —\n * which may be an array of `{ name, description }` or a record keyed by tool name (v6).\n */\nfunction resolveToolDescription(callId: string | undefined, toolName: string, tools: unknown): string | undefined {\n const fromMap = callId ? toolDescriptionsByCallId.get(callId)?.get(toolName) : undefined;\n if (fromMap) {\n return fromMap;\n }\n if (Array.isArray(tools)) {\n const match = tools.find(tool => isRecord(tool) && tool.name === toolName);\n return isRecord(match) ? asString(match.description) : undefined;\n }\n if (isRecord(tools)) {\n const tool = tools[toolName];\n return isRecord(tool) ? asString(tool.description) : undefined;\n }\n return undefined;\n}\n\n/** The lifecycle event types the `ai:telemetry` channel can carry. */\nexport type ChannelEventType =\n | 'generateText'\n | 'streamText'\n | 'step'\n | 'languageModelCall'\n | 'executeTool'\n | 'embed'\n | 'embedMany'\n | 'rerank';\n\n/**\n * The context object the AI SDK passes through one tracing-channel call. It is the same object\n * identity across `start`/`end`/`asyncEnd`/`error`, and Node's `tracingChannel` attaches\n * `result`/`error` to it as the traced promise settles.\n */\nexport interface VercelAiChannelMessage {\n type: ChannelEventType;\n event: Record<string, unknown>;\n result?: unknown;\n error?: unknown;\n}\n\n/**\n * Platform-provided factory that returns a tracing channel for the given channel name. The factory\n * is responsible for, when `start` fires, calling `transformStart(data)` and storing the returned\n * span on `data._sentrySpan` so the subscriber's `asyncEnd`/`error` handlers can read it.\n *\n * Node passes `@sentry/opentelemetry/tracing-channel`, which uses `bindStore` to additionally make\n * the span the active OTel context for the duration of the traced operation. That is what makes\n * nested AI SDK operations (model calls, tool calls) become children of the enclosing span without\n * any manual parent bookkeeping here.\n */\nexport type VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;\n\n/** Integration-level recording options, pinned at subscribe time so we never look the integration up per event. */\nexport interface VercelAiChannelOptions {\n recordInputs?: boolean;\n recordOutputs?: boolean;\n enableTruncation?: boolean;\n}\n\nlet subscribed = false;\n\n/**\n * Subscribe Sentry span handlers to the `ai` SDK's native telemetry tracing channel (`ai:telemetry`,\n * available in `ai` >= 7) and emit fully-formed `gen_ai.*` spans directly — no OpenTelemetry span\n * post-processing involved.\n *\n * The integration passes its options in directly (rather than us looking the integration up on every\n * event); the global `dataCollection.genAI` default is still read from the client per event.\n *\n * Safe to always call: on `ai` versions that don't publish to the channel (e.g. < 7) nothing is\n * ever emitted and this is inert, so there is no double-instrumentation against the OTel-based\n * patcher. Idempotent.\n */\nexport function subscribeVercelAiTracingChannel(\n tracingChannel: VercelAiTracingChannelFactory,\n options: VercelAiChannelOptions = {},\n): void {\n if (subscribed) {\n return;\n }\n subscribed = true;\n\n bindTracingChannelToSpan(\n tracingChannel<VercelAiChannelMessage>(AI_SDK_TELEMETRY_TRACING_CHANNEL),\n data => createSpanFromMessage(data, options),\n {\n // The helper ends the span; we enrich it from the settled result first (tokens, output messages,\n // finish reasons, response model/id, provider metadata) and drop the per-operation `callId` maps.\n beforeSpanEnd: (span, data) => {\n enrichSpanOnEnd(span, data, options);\n clearOperationId(data);\n },\n },\n );\n}\n\n/**\n * Transform a channel `start` payload into the span that should be active for the operation. For\n * `step` we deliberately don't open a span (model calls and tool calls are siblings under the\n * invoke_agent span, matching the OTel-based output), so we reuse the active span and mark the\n * payload to skip ending it.\n */\nexport function createSpanFromMessage(\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): Span | undefined {\n const { type, event } = data;\n\n if (type === 'step' || !event || typeof event !== 'object') {\n // Opt out: returning `undefined` leaves the enclosing `invoke_agent` span as the active context\n // (model-call and tool-call events nest under it) without opening — or ending — a span of its own.\n return undefined;\n }\n\n const { recordInputs, enableTruncation } = getRecordingOptions(event, channelOptions);\n const provider = asString(event.provider);\n const modelId = asString(event.modelId);\n const callId = asString(event.callId);\n const maxRetries = asNumber(event.maxRetries);\n\n // Harvest tool descriptions from the operation/model-call `tools` so tool spans can backfill them.\n // Gated on `recordInputs` to match the OTel path, which only records `available_tools` then.\n if (recordInputs) {\n recordToolDescriptions(callId, event.tools);\n }\n\n const baseAttributes: Record<string, string | number | boolean> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n ...(provider ? { [GEN_AI_SYSTEM]: provider, [VERCEL_AI_MODEL_PROVIDER_ATTRIBUTE]: provider } : {}),\n ...(modelId ? { [GEN_AI_REQUEST_MODEL]: modelId } : {}),\n ...(maxRetries !== undefined ? { [VERCEL_AI_SETTINGS_MAX_RETRIES_ATTRIBUTE]: maxRetries } : {}),\n };\n\n switch (type) {\n case 'generateText':\n case 'streamText':\n return buildInvokeAgentSpan(event, baseAttributes, recordInputs, enableTruncation, callId, type === 'streamText');\n case 'languageModelCall':\n return buildModelCallSpan(event, baseAttributes, recordInputs, enableTruncation, callId, modelId);\n case 'executeTool':\n return buildToolSpan(event, recordInputs);\n case 'embed':\n case 'embedMany': {\n // `embed` carries a single `value`; `embedMany` a `values` array — both map to the embeddings input.\n const input = type === 'embedMany' ? event.values : event.value;\n return startGenAiSpan(GEN_AI_EMBEDDINGS_OPERATION, modelId, {\n ...baseAttributes,\n ...(recordInputs && input !== undefined ? { [GEN_AI_EMBEDDINGS_INPUT]: safeStringify(input) } : {}),\n });\n }\n case 'rerank':\n return startGenAiSpan(GEN_AI_RERANK_OPERATION, modelId, baseAttributes);\n default:\n // Unknown event type: opt out rather than open a span we can't shape correctly.\n return undefined;\n }\n}\n\ntype Attributes = Record<string, string | number | boolean>;\n\n/** Start a `gen_ai.<operation>` span named `<operation> <suffix>` (or just `<operation>` when no suffix). */\nfunction startGenAiSpan(operation: string, suffix: string | undefined, attributes: Attributes): Span {\n return startInactiveSpan({\n name: suffix ? `${operation} ${suffix}` : operation,\n op: `gen_ai.${operation}`,\n attributes: { [GEN_AI_OPERATION_NAME]: operation, ...attributes },\n });\n}\n\nfunction buildInvokeAgentSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n isStream: boolean,\n): Span {\n const functionId = asString(event.functionId);\n const operationId = asString(event.operationId) ?? (isStream ? 'ai.streamText' : 'ai.generateText');\n if (callId) {\n operationIdByCallId.set(callId, { operationId, isStream });\n }\n return startGenAiSpan(GEN_AI_INVOKE_AGENT_SPAN_OP, functionId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n [GEN_AI_RESPONSE_STREAMING]: isStream,\n ...(functionId ? { [GEN_AI_FUNCTION_ID]: functionId } : {}),\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n });\n}\n\nfunction buildModelCallSpan(\n event: Record<string, unknown>,\n baseAttributes: Attributes,\n recordInputs: boolean,\n enableTruncation: boolean,\n callId: string | undefined,\n modelId: string | undefined,\n): Span {\n const parent = callId ? operationIdByCallId.get(callId) : undefined;\n const operationId = parent\n ? `${parent.operationId}.${parent.isStream ? 'doStream' : 'doGenerate'}`\n : 'ai.generateText.doGenerate';\n return startGenAiSpan(GEN_AI_GENERATE_CONTENT_OPERATION, modelId, {\n ...baseAttributes,\n [VERCEL_AI_OPERATION_ID_ATTRIBUTE]: operationId,\n ...(recordInputs ? buildInputMessageAttributes(event, enableTruncation) : {}),\n ...(recordInputs && Array.isArray(event.tools)\n ? { [GEN_AI_REQUEST_AVAILABLE_TOOLS]: safeStringify(event.tools) }\n : {}),\n });\n}\n\nfunction buildToolSpan(event: Record<string, unknown>, recordInputs: boolean): Span {\n const toolCall = isRecord(event.toolCall) ? event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(event.toolCallId) ?? asString(toolCall.toolCallId);\n const toolInput = toolCall.input ?? toolCall.args;\n // The `executeTool` event has no description; backfill it from the operation's recorded tools.\n // Gated on `recordInputs` to match the OTel path (descriptions come from the recorded tools list).\n const description =\n recordInputs && toolName ? resolveToolDescription(asString(event.callId), toolName, event.tools) : undefined;\n return startGenAiSpan(GEN_AI_EXECUTE_TOOL_SPAN_OP, toolName, {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [GEN_AI_TOOL_TYPE]: 'function',\n ...(toolName ? { [GEN_AI_TOOL_NAME]: toolName } : {}),\n ...(toolCallId ? { [GEN_AI_TOOL_CALL_ID_ATTRIBUTE]: toolCallId } : {}),\n ...(description ? { [GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE]: description } : {}),\n ...(recordInputs && toolInput !== undefined ? { [GEN_AI_TOOL_INPUT]: safeStringify(toolInput) } : {}),\n });\n}\n\n/**\n * Best-effort enrichment from the resolved value the AI SDK attaches to the channel context.\n * Everything here is guarded: when a field is missing or the shape differs across `ai` versions,\n * we simply don't set the attribute rather than emit a malformed span.\n */\nexport function enrichSpanOnEnd(\n span: Span,\n data: VercelAiChannelMessage,\n channelOptions: VercelAiChannelOptions,\n): void {\n const { type, result } = data;\n if (!isRecord(result)) {\n return;\n }\n\n const { recordOutputs } = getRecordingOptions(data.event, channelOptions);\n\n if (type === 'executeTool') {\n if (recordOutputs) {\n span.setAttribute(GEN_AI_TOOL_OUTPUT, safeStringify(result.output ?? result));\n }\n // From V5 on, tool errors are not rejected (so the `error` channel verb never fires) — they\n // surface as `tool-error` content on the resolved result. Mirror the OTel path by marking the\n // span and capturing the error.\n const output = isRecord(result.output) ? result.output : undefined;\n if (output?.type === 'tool-error') {\n captureToolError(span, data, output.error);\n }\n return;\n }\n\n // `languageModelCall` results report usage as `{ total }` objects; top-level/step results report\n // flat numbers. `tokenCount` handles both.\n const usage = isRecord(result.usage) ? result.usage : undefined;\n if (usage) {\n const inputTokens = tokenCount(usage.inputTokens) ?? tokenCount(usage.tokens);\n const outputTokens = tokenCount(usage.outputTokens);\n const totalTokens = tokenCount(usage.totalTokens) ?? sum(inputTokens, outputTokens);\n if (inputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n if (totalTokens !== undefined) {\n span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n }\n\n // Match the OTel integration: finish reasons live on the model-call (`generate_content`) span, not\n // on the top-level `invoke_agent` span.\n const finishReason = getFinishReason(result);\n if (finishReason && type === 'languageModelCall') {\n span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, safeStringify([finishReason]));\n }\n\n const response = isRecord(result.response) ? result.response : undefined;\n const responseId = asString(response?.id) ?? asString(result.responseId);\n if (responseId) {\n span.setAttribute(GEN_AI_RESPONSE_ID, responseId);\n }\n const responseModel = asString(response?.modelId) ?? asString(data.event.modelId);\n if (responseModel) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL, responseModel);\n }\n\n // Provider-specific cache/reasoning/prediction token breakdowns and `gen_ai.conversation.id`.\n // The channel exposes `providerMetadata` as an object (the OTel path parses it from a string);\n // both share `getProviderMetadataAttributes` so the emitted shape is identical.\n const providerMetadata = (result as { providerMetadata?: unknown }).providerMetadata;\n const providerAttributes = getProviderMetadataAttributes(providerMetadata);\n // Don't overwrite a conversation id already set on span start (e.g. by `conversationIdIntegration`\n // from a user-set scope value); the provider-derived id is only a fallback. Matches the OTel path.\n if (\n GEN_AI_CONVERSATION_ID_ATTRIBUTE in providerAttributes &&\n spanToJSON(span).data[GEN_AI_CONVERSATION_ID_ATTRIBUTE]\n ) {\n // oxlint-disable-next-line typescript/no-dynamic-delete\n delete providerAttributes[GEN_AI_CONVERSATION_ID_ATTRIBUTE];\n }\n span.setAttributes(providerAttributes);\n\n if (recordOutputs) {\n // `languageModelCall` exposes the response as a `content` parts array; top-level results expose\n // `text` + `toolCalls`. Both normalize into the OTel `gen_ai.output.messages` assistant message.\n const parts =\n type === 'languageModelCall' && Array.isArray(result.content)\n ? partsFromContent(result.content)\n : partsFromTextAndToolCalls(result.text, result.toolCalls);\n const outputMessages = buildOutputMessages(parts, finishReason);\n if (outputMessages) {\n span.setAttribute(GEN_AI_OUTPUT_MESSAGES, outputMessages);\n }\n }\n}\n\n/** Maps a Vercel AI finish reason to the OTel `gen_ai.output.messages` form (`tool-calls` → `tool_call`). */\nfunction normalizeFinishReason(finishReason: string | undefined): string {\n return finishReason === 'tool-calls' ? 'tool_call' : (finishReason ?? 'stop');\n}\n\n/** Reads the finish reason from a result — a string on top-level results, `{ unified }` on model calls. */\nfunction getFinishReason(result: Record<string, unknown>): string | undefined {\n const finishReason = result.finishReason;\n if (typeof finishReason === 'string') {\n return finishReason;\n }\n return isRecord(finishReason) ? asString(finishReason.unified) : undefined;\n}\n\n/** Reads a token count that may be a plain number or a `{ total }` object (model-call usage). */\nfunction tokenCount(value: unknown): number | undefined {\n return asNumber(value) ?? (isRecord(value) ? asNumber(value.total) : undefined);\n}\n\nfunction buildOutputMessages(\n parts: Array<Record<string, unknown>>,\n finishReason: string | undefined,\n): string | undefined {\n if (!parts.length) {\n return undefined;\n }\n return safeStringify([{ role: 'assistant', parts, finish_reason: normalizeFinishReason(finishReason) }]);\n}\n\nfunction toolCallPart(toolCall: Record<string, unknown>): Record<string, unknown> {\n const args = toolCall.input ?? toolCall.args;\n return {\n type: 'tool_call',\n id: asString(toolCall.toolCallId),\n name: asString(toolCall.toolName),\n arguments: typeof args === 'string' ? args : safeStringify(args ?? {}),\n };\n}\n\nfunction partsFromContent(content: unknown[]): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n for (const item of content) {\n if (!isRecord(item)) {\n continue;\n }\n if (item.type === 'text' && typeof item.text === 'string') {\n parts.push({ type: 'text', content: item.text });\n } else if (item.type === 'tool-call') {\n parts.push(toolCallPart(item));\n }\n }\n return parts;\n}\n\nfunction partsFromTextAndToolCalls(text: unknown, toolCalls: unknown): Array<Record<string, unknown>> {\n const parts: Array<Record<string, unknown>> = [];\n if (typeof text === 'string' && text.length) {\n parts.push({ type: 'text', content: text });\n }\n if (Array.isArray(toolCalls)) {\n for (const toolCall of toolCalls) {\n if (isRecord(toolCall)) {\n parts.push(toolCallPart(toolCall));\n }\n }\n }\n return parts;\n}\n\nfunction captureToolError(span: Span, data: VercelAiChannelMessage, error: unknown): void {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: error instanceof Error ? error.message : 'tool_error',\n });\n\n const toolCall = isRecord(data.event.toolCall) ? data.event.toolCall : {};\n const toolName = asString(toolCall.toolName);\n const toolCallId = asString(data.event.toolCallId) ?? asString(toolCall.toolCallId);\n\n withScope(scope => {\n scope.setContext('trace', spanToTraceContext(span));\n if (toolName) {\n scope.setTag('vercel.ai.tool.name', toolName);\n }\n if (toolCallId) {\n scope.setTag('vercel.ai.tool.callId', toolCallId);\n }\n scope.setLevel('error');\n captureException(\n error instanceof Error ? error : new Error(typeof error === 'string' ? error : 'Tool execution failed'),\n {\n mechanism: { type: 'auto.vercelai.channel', handled: false },\n },\n );\n });\n}\n\nfunction getRecordingOptions(\n event: Record<string, unknown>,\n channelOptions: VercelAiChannelOptions,\n): {\n recordInputs: boolean;\n recordOutputs: boolean;\n enableTruncation: boolean;\n} {\n const genAI = getClient()?.getDataCollectionOptions().genAI;\n\n return {\n recordInputs: resolveRecording(channelOptions.recordInputs, event.recordInputs, genAI?.inputs),\n recordOutputs: resolveRecording(channelOptions.recordOutputs, event.recordOutputs, genAI?.outputs),\n enableTruncation: shouldEnableTruncation(channelOptions.enableTruncation),\n };\n}\n\n/**\n * Mirrors the OTel integration's `determineRecordingSettings` precedence: an integration-level option\n * wins, then the per-call `experimental_telemetry.recordInputs/recordOutputs` flag the AI SDK forwards\n * on the channel event, then the global `dataCollection.genAI` default.\n *\n * NOTE: the OTel integration also defaults recording to `true` for a call with\n * `experimental_telemetry: { isEnabled: true }`. The `ai:telemetry` channel does not expose `isEnabled`\n * (nor a resolved recording flag), so that per-call default cannot be reproduced here — v7 users who\n * want inputs/outputs recorded must enable `dataCollection.genAI` or set `recordInputs`/`recordOutputs`.\n */\nfunction resolveRecording(integrationOption: unknown, perCallOption: unknown, globalDefault: unknown): boolean {\n if (typeof integrationOption === 'boolean') {\n return integrationOption;\n }\n if (typeof perCallOption === 'boolean') {\n return perCallOption;\n }\n return globalDefault === true;\n}\n\nfunction buildInputMessageAttributes(\n event: Record<string, unknown>,\n enableTruncation: boolean,\n): Record<string, string | number> {\n const attributes: Record<string, string | number> = {};\n\n // `ai` >= 7 forbids system messages in `messages`/`prompt` and exposes the system prompt as a\n // separate `instructions` field. The OTel path lifts the system message out of the prompt into\n // `gen_ai.system_instructions` as `[{ type: 'text', content }]`; mirror that shape here.\n const instructions = asString(event.instructions);\n if (instructions) {\n attributes[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE] = safeStringify([{ type: 'text', content: instructions }]);\n }\n\n // The AI SDK start events extend `StandardizedPrompt`; messages live on `messages`, otherwise the\n // simpler `prompt` field is used.\n const messages = event.messages ?? event.prompt;\n if (messages !== undefined) {\n attributes[GEN_AI_INPUT_MESSAGES] = enableTruncation ? getTruncatedJsonString(messages) : safeStringify(messages);\n // The original (pre-truncation) message count, so the product can show how many were dropped.\n attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE] = Array.isArray(messages) ? messages.length : 1;\n }\n\n return attributes;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && !isNaN(value) ? value : undefined;\n}\n\nfunction sum(a: number | undefined, b: number | undefined): number | undefined {\n return a === undefined && b === undefined ? undefined : (a ?? 0) + (b ?? 0);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return '[unserializable]';\n }\n}\n"],"names":[],"mappings":"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"}

@@ -7,4 +7,6 @@ /// <reference path="./node-diagnostics-channel.d.ts" />

*/
export { mongooseIntegration } from './mongoose';
export { IOREDIS_DC_CHANNEL_COMMAND, IOREDIS_DC_CHANNEL_CONNECT, REDIS_DC_CHANNEL_BATCH, REDIS_DC_CHANNEL_COMMAND, REDIS_DC_CHANNEL_CONNECT, subscribeRedisDiagnosticChannels, } from './redis/redis-dc-subscriber';
export { IORedisCommandData, RedisBatchData, RedisCommandData, RedisConnectData, RedisDiagnosticChannelResponseHook, RedisTracingChannelFactory, } from './redis/redis-dc-subscriber';
export { defaultDbStatementSerializer } from './redis/redis-statement-serializer';
export { bindTracingChannelToSpan } from './tracing-channel';

@@ -11,0 +13,0 @@ export { SentryTracingChannel, TracingChannelLifeCycleOptions, TracingChannelBindingHandle, TracingChannelPayloadWithSpan, } from './tracing-channel';

@@ -15,6 +15,26 @@ /**

export declare const CHANNELS: {
readonly HAPI_ROUTE: "orchestrion:@hapi/hapi:route";
readonly HAPI_EXT: "orchestrion:@hapi/hapi:ext";
readonly VERCEL_AI_GENERATE_TEXT: "orchestrion:ai:generateText";
readonly VERCEL_AI_STREAM_TEXT: "orchestrion:ai:streamText";
readonly VERCEL_AI_EMBED: "orchestrion:ai:embed";
readonly VERCEL_AI_EMBED_MANY: "orchestrion:ai:embedMany";
readonly VERCEL_AI_EXECUTE_TOOL_CALL: "orchestrion:ai:executeToolCall";
readonly VERCEL_AI_RESOLVE_LANGUAGE_MODEL: "orchestrion:ai:resolveLanguageModel";
readonly ANTHROPIC_CHAT: "orchestrion:@anthropic-ai/sdk:chat";
readonly ANTHROPIC_MODELS: "orchestrion:@anthropic-ai/sdk:models";
readonly ANTHROPIC_MESSAGES_STREAM: "orchestrion:@anthropic-ai/sdk:messages-stream";
readonly OPENAI_CHAT: "orchestrion:openai:chat";
readonly OPENAI_RESPONSES: "orchestrion:openai:responses";
readonly OPENAI_EMBEDDINGS: "orchestrion:openai:embeddings";
readonly OPENAI_CONVERSATIONS: "orchestrion:openai:conversations";
readonly PG_QUERY: "orchestrion:pg:query";
readonly PG_CONNECT: "orchestrion:pg:connect";
readonly PGPOOL_CONNECT: "orchestrion:pg-pool:connect";
readonly IOREDIS_COMMAND: "orchestrion:ioredis:command";
readonly IOREDIS_CONNECT: "orchestrion:ioredis:connect";
readonly LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load";
readonly MYSQL_QUERY: "orchestrion:mysql:query";
readonly LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load";
};
export type ChannelName = (typeof CHANNELS)[keyof typeof CHANNELS];
//# sourceMappingURL=channels.d.ts.map

@@ -8,2 +8,12 @@ declare global {

/**
* Whether orchestrion has injected the diagnostics channels into this process,
* either by the runtime `--import` hook / init-time registration (`runtime`)
* or a bundler plugin (`bundler`). Both injectors set a flag on the
* `globalThis.__SENTRY_ORCHESTRION__` marker.
*
* Use this to avoid wiring up channel-subscriber integrations when nothing
* will ever publish to those channels.
*/
export declare function isOrchestrionInjected(): boolean;
/**
* Verifies that the diagnostics channels have been injected either by the

@@ -10,0 +20,0 @@ * runtime `--import` hook (or init-time registration), a bundler plugin, or

@@ -1,4 +0,54 @@

export { detectOrchestrionSetup } from './detect';
export { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql';
export { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer';
import { anthropicChannelIntegration } from '../integrations/tracing-channel/anthropic';
import { hapiChannelIntegration } from '../integrations/tracing-channel/hapi';
import { ioredisChannelIntegration } from '../integrations/tracing-channel/ioredis';
import { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer';
import { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql';
import { openaiChannelIntegration } from '../integrations/tracing-channel/openai';
import { postgresChannelIntegration } from '../integrations/tracing-channel/postgres';
import { vercelAiChannelIntegration } from '../integrations/tracing-channel/vercel-ai';
export { detectOrchestrionSetup, isOrchestrionInjected } from './detect';
export { anthropicChannelIntegration, hapiChannelIntegration, ioredisChannelIntegration, lruMemoizerChannelIntegration, mysqlChannelIntegration, openaiChannelIntegration, postgresChannelIntegration, vercelAiChannelIntegration, };
export { IORedisChannelIntegrationOptions, IORedisResponseHook } from '../integrations/tracing-channel/ioredis';
/**
* The canonical set of orchestrion diagnostics-channel integrations, keyed by their public
* (OTel-parity) factory name.
*
* Single source of truth: add a new channel integration here and every consumer — the `@sentry/node`
* opt-in helper (`experimentalUseDiagnosticsChannelInjection`) and its public
* `diagnosticsChannelInjectionIntegrations()` map — picks it up automatically, so there's no separate
* list to keep in sync.
*
* NOTE: `ioredisChannelIntegration` is intentionally NOT here. It only partially replaces the
* composite OTel `Redis` integration and needs the node SDK's redis cache `responseHook` (which
* can't live in `server-utils`), so `@sentry/node` wires it up separately.
*/
export declare const channelIntegrations: {
readonly postgresIntegration: (options?: {
ignoreConnectSpans?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "Postgres";
};
readonly mysqlIntegration: () => import("@sentry/core").Integration & {
name: "Mysql";
};
readonly lruMemoizerIntegration: () => import("@sentry/core").Integration & {
name: "LruMemoizer";
};
readonly openaiIntegration: (options?: import("@sentry/core").OpenAiOptions | undefined) => import("@sentry/core").Integration & {
name: "OpenAI";
};
readonly anthropicIntegration: (options?: import("@sentry/core").AnthropicAiOptions | undefined) => import("@sentry/core").Integration & {
name: "Anthropic_AI";
};
readonly vercelAiIntegration: (options?: {
recordInputs?: boolean;
recordOutputs?: boolean;
enableTruncation?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "VercelAI";
};
readonly hapiIntegration: () => import("@sentry/core").Integration & {
name: "Hapi";
};
};
//# sourceMappingURL=index.d.ts.map

@@ -5,4 +5,11 @@ import { Span } from '@sentry/core';

export declare function clearOperationId(data: VercelAiChannelMessage): void;
/**
* Drop the per-operation `callId` maps for a single id. The v6 orchestrion adapter uses this to clear a
* `streamText` operation only after its lazily-run model call settles — the operation's own span ends
* synchronously (when `streamText` returns) but the model call runs later as the stream is consumed, and
* it still needs the operation's `operationId`/`isStream` entry to name itself `ai.streamText.doStream`.
*/
export declare function clearOperationCallId(callId: string): void;
/** The lifecycle event types the `ai:telemetry` channel can carry. */
export type ChannelEventType = 'generateText' | 'streamText' | 'step' | 'languageModelCall' | 'executeTool' | 'embed' | 'rerank';
export type ChannelEventType = 'generateText' | 'streamText' | 'step' | 'languageModelCall' | 'executeTool' | 'embed' | 'embedMany' | 'rerank';
/**

@@ -29,5 +36,5 @@ * The context object the AI SDK passes through one tracing-channel call. It is the same object

*/
type VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;
export type VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;
/** Integration-level recording options, pinned at subscribe time so we never look the integration up per event. */
interface VercelAiChannelOptions {
export interface VercelAiChannelOptions {
recordInputs?: boolean;

@@ -63,3 +70,2 @@ recordOutputs?: boolean;

export declare function enrichSpanOnEnd(span: Span, data: VercelAiChannelMessage, channelOptions: VercelAiChannelOptions): void;
export {};
//# sourceMappingURL=vercel-ai-dc-subscriber.d.ts.map

@@ -6,4 +6,6 @@ /**

*/
export { mongooseIntegration } from './mongoose';
export { IOREDIS_DC_CHANNEL_COMMAND, IOREDIS_DC_CHANNEL_CONNECT, REDIS_DC_CHANNEL_BATCH, REDIS_DC_CHANNEL_COMMAND, REDIS_DC_CHANNEL_CONNECT, subscribeRedisDiagnosticChannels, } from './redis/redis-dc-subscriber';
export type { IORedisCommandData, RedisBatchData, RedisCommandData, RedisConnectData, RedisDiagnosticChannelResponseHook, RedisTracingChannelFactory, } from './redis/redis-dc-subscriber';
export { defaultDbStatementSerializer } from './redis/redis-statement-serializer';
export { bindTracingChannelToSpan } from './tracing-channel';

@@ -10,0 +12,0 @@ export type { SentryTracingChannel, TracingChannelLifeCycleOptions, TracingChannelBindingHandle, TracingChannelPayloadWithSpan, } from './tracing-channel';

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,kCAAkC,EAClC,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,YAAY,EACV,oBAAoB,EACpB,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EACL,kBAAkB,EAElB,kBAAkB,EAElB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,kCAAkC,EAClC,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,YAAY,EACV,oBAAoB,EACpB,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EACL,kBAAkB,EAElB,kBAAkB,EAElB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/mysql.ts"],"names":[],"mappings":"AAuKA;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;;CAA8C,CAAC"}
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing-channel/mysql.ts"],"names":[],"mappings":"AAyKA;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;;CAA8C,CAAC"}

@@ -15,6 +15,26 @@ /**

export declare const CHANNELS: {
readonly HAPI_ROUTE: "orchestrion:@hapi/hapi:route";
readonly HAPI_EXT: "orchestrion:@hapi/hapi:ext";
readonly VERCEL_AI_GENERATE_TEXT: "orchestrion:ai:generateText";
readonly VERCEL_AI_STREAM_TEXT: "orchestrion:ai:streamText";
readonly VERCEL_AI_EMBED: "orchestrion:ai:embed";
readonly VERCEL_AI_EMBED_MANY: "orchestrion:ai:embedMany";
readonly VERCEL_AI_EXECUTE_TOOL_CALL: "orchestrion:ai:executeToolCall";
readonly VERCEL_AI_RESOLVE_LANGUAGE_MODEL: "orchestrion:ai:resolveLanguageModel";
readonly ANTHROPIC_CHAT: "orchestrion:@anthropic-ai/sdk:chat";
readonly ANTHROPIC_MODELS: "orchestrion:@anthropic-ai/sdk:models";
readonly ANTHROPIC_MESSAGES_STREAM: "orchestrion:@anthropic-ai/sdk:messages-stream";
readonly OPENAI_CHAT: "orchestrion:openai:chat";
readonly OPENAI_RESPONSES: "orchestrion:openai:responses";
readonly OPENAI_EMBEDDINGS: "orchestrion:openai:embeddings";
readonly OPENAI_CONVERSATIONS: "orchestrion:openai:conversations";
readonly PG_QUERY: "orchestrion:pg:query";
readonly PG_CONNECT: "orchestrion:pg:connect";
readonly PGPOOL_CONNECT: "orchestrion:pg-pool:connect";
readonly IOREDIS_COMMAND: "orchestrion:ioredis:command";
readonly IOREDIS_CONNECT: "orchestrion:ioredis:connect";
readonly LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load";
readonly MYSQL_QUERY: "orchestrion:mysql:query";
readonly LRU_MEMOIZER_LOAD: "orchestrion:lru-memoizer:load";
};
export type ChannelName = (typeof CHANNELS)[keyof typeof CHANNELS];
//# sourceMappingURL=channels.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/channels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ;;;CAGX,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC"}
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/channels.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;CASX,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC"}

@@ -8,2 +8,12 @@ declare global {

/**
* Whether orchestrion has injected the diagnostics channels into this process,
* either by the runtime `--import` hook / init-time registration (`runtime`)
* or a bundler plugin (`bundler`). Both injectors set a flag on the
* `globalThis.__SENTRY_ORCHESTRION__` marker.
*
* Use this to avoid wiring up channel-subscriber integrations when nothing
* will ever publish to those channels.
*/
export declare function isOrchestrionInjected(): boolean;
/**
* Verifies that the diagnostics channels have been injected either by the

@@ -10,0 +20,0 @@ * runtime `--import` hook (or init-time registration), a bundler plugin, or

@@ -1,1 +0,1 @@

{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/detect.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,sBAAsB,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAiB7C"}
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/detect.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,sBAAsB,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClF;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAG/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAiB7C"}

@@ -1,4 +0,54 @@

export { detectOrchestrionSetup } from './detect';
export { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql';
export { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer';
import { anthropicChannelIntegration } from '../integrations/tracing-channel/anthropic';
import { hapiChannelIntegration } from '../integrations/tracing-channel/hapi';
import { ioredisChannelIntegration } from '../integrations/tracing-channel/ioredis';
import { lruMemoizerChannelIntegration } from '../integrations/tracing-channel/lru-memoizer';
import { mysqlChannelIntegration } from '../integrations/tracing-channel/mysql';
import { openaiChannelIntegration } from '../integrations/tracing-channel/openai';
import { postgresChannelIntegration } from '../integrations/tracing-channel/postgres';
import { vercelAiChannelIntegration } from '../integrations/tracing-channel/vercel-ai';
export { detectOrchestrionSetup, isOrchestrionInjected } from './detect';
export { anthropicChannelIntegration, hapiChannelIntegration, ioredisChannelIntegration, lruMemoizerChannelIntegration, mysqlChannelIntegration, openaiChannelIntegration, postgresChannelIntegration, vercelAiChannelIntegration, };
export type { IORedisChannelIntegrationOptions, IORedisResponseHook } from '../integrations/tracing-channel/ioredis';
/**
* The canonical set of orchestrion diagnostics-channel integrations, keyed by their public
* (OTel-parity) factory name.
*
* Single source of truth: add a new channel integration here and every consumer — the `@sentry/node`
* opt-in helper (`experimentalUseDiagnosticsChannelInjection`) and its public
* `diagnosticsChannelInjectionIntegrations()` map — picks it up automatically, so there's no separate
* list to keep in sync.
*
* NOTE: `ioredisChannelIntegration` is intentionally NOT here. It only partially replaces the
* composite OTel `Redis` integration and needs the node SDK's redis cache `responseHook` (which
* can't live in `server-utils`), so `@sentry/node` wires it up separately.
*/
export declare const channelIntegrations: {
readonly postgresIntegration: (options?: {
ignoreConnectSpans?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "Postgres";
};
readonly mysqlIntegration: () => import("@sentry/core").Integration & {
name: "Mysql";
};
readonly lruMemoizerIntegration: () => import("@sentry/core").Integration & {
name: "LruMemoizer";
};
readonly openaiIntegration: (options?: import("@sentry/core").OpenAiOptions | undefined) => import("@sentry/core").Integration & {
name: "OpenAI";
};
readonly anthropicIntegration: (options?: import("@sentry/core").AnthropicAiOptions | undefined) => import("@sentry/core").Integration & {
name: "Anthropic_AI";
};
readonly vercelAiIntegration: (options?: {
recordInputs?: boolean;
recordOutputs?: boolean;
enableTruncation?: boolean;
} | undefined) => import("@sentry/core").Integration & {
name: "VercelAI";
};
readonly hapiIntegration: () => import("@sentry/core").Integration & {
name: "Hapi";
};
};
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AACpF,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAC;AAC7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAEvF,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,0BAA0B,GAC3B,CAAC;AACF,YAAY,EAAE,gCAAgC,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAErH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQtB,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/runtime/register.ts"],"names":[],"mappings":"AAOA,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,sBAAsB,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mCAAmC,IAAI,IAAI,CA4F1D"}
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/orchestrion/runtime/register.ts"],"names":[],"mappings":"AAOA,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,sBAAsB,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mCAAmC,IAAI,IAAI,CAiG1D"}

@@ -5,4 +5,11 @@ import type { Span } from '@sentry/core';

export declare function clearOperationId(data: VercelAiChannelMessage): void;
/**
* Drop the per-operation `callId` maps for a single id. The v6 orchestrion adapter uses this to clear a
* `streamText` operation only after its lazily-run model call settles — the operation's own span ends
* synchronously (when `streamText` returns) but the model call runs later as the stream is consumed, and
* it still needs the operation's `operationId`/`isStream` entry to name itself `ai.streamText.doStream`.
*/
export declare function clearOperationCallId(callId: string): void;
/** The lifecycle event types the `ai:telemetry` channel can carry. */
export type ChannelEventType = 'generateText' | 'streamText' | 'step' | 'languageModelCall' | 'executeTool' | 'embed' | 'rerank';
export type ChannelEventType = 'generateText' | 'streamText' | 'step' | 'languageModelCall' | 'executeTool' | 'embed' | 'embedMany' | 'rerank';
/**

@@ -29,5 +36,5 @@ * The context object the AI SDK passes through one tracing-channel call. It is the same object

*/
type VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;
export type VercelAiTracingChannelFactory = <T extends object>(name: string) => TracingChannel<T, T>;
/** Integration-level recording options, pinned at subscribe time so we never look the integration up per event. */
interface VercelAiChannelOptions {
export interface VercelAiChannelOptions {
recordInputs?: boolean;

@@ -63,3 +70,2 @@ recordOutputs?: boolean;

export declare function enrichSpanOnEnd(span: Span, data: VercelAiChannelMessage, channelOptions: VercelAiChannelOptions): void;
export {};
//# sourceMappingURL=vercel-ai-dc-subscriber.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"vercel-ai-dc-subscriber.d.ts","sourceRoot":"","sources":["../../../src/vercel-ai/vercel-ai-dc-subscriber.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAiBzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA6C/D,2GAA2G;AAC3G,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,CASnE;AA0CD,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,YAAY,GACZ,MAAM,GACN,mBAAmB,GACnB,aAAa,GACb,OAAO,GACP,QAAQ,CAAC;AAEb;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,KAAK,6BAA6B,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE9F,mHAAmH;AACnH,UAAU,sBAAsB;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAC7C,cAAc,EAAE,6BAA6B,EAC7C,OAAO,GAAE,sBAA2B,GACnC,IAAI,CAkBN;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,sBAAsB,EAC5B,cAAc,EAAE,sBAAsB,GACrC,IAAI,GAAG,SAAS,CA+ClB;AA4ED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,sBAAsB,EAC5B,cAAc,EAAE,sBAAsB,GACrC,IAAI,CAqFN"}
{"version":3,"file":"vercel-ai-dc-subscriber.d.ts","sourceRoot":"","sources":["../../../src/vercel-ai/vercel-ai-dc-subscriber.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAiBzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA6C/D,2GAA2G;AAC3G,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,CAQnE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGzD;AA0CD,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,YAAY,GACZ,MAAM,GACN,mBAAmB,GACnB,aAAa,GACb,OAAO,GACP,WAAW,GACX,QAAQ,CAAC;AAEb;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAErG,mHAAmH;AACnH,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAC7C,cAAc,EAAE,6BAA6B,EAC7C,OAAO,GAAE,sBAA2B,GACnC,IAAI,CAkBN;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,sBAAsB,EAC5B,cAAc,EAAE,sBAAsB,GACrC,IAAI,GAAG,SAAS,CAmDlB;AA4ED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,sBAAsB,EAC5B,cAAc,EAAE,sBAAsB,GACrC,IAAI,CAqFN"}
{
"name": "@sentry/server-utils",
"version": "10.63.0",
"version": "10.64.0",
"description": "Server Utilities for all Sentry JavaScript SDKs",

@@ -31,5 +31,5 @@ "repository": "git://github.com/getsentry/sentry-javascript.git",

"./orchestrion/config": {
"types": "./build/types/orchestrion/config.d.ts",
"import": "./build/esm/orchestrion/config.js",
"require": "./build/cjs/orchestrion/config.js"
"types": "./build/types/orchestrion/config/index.d.ts",
"import": "./build/esm/orchestrion/config/index.js",
"require": "./build/cjs/orchestrion/config/index.js"
},

@@ -58,3 +58,3 @@ "./orchestrion/register": {

"orchestrion/config": [
"build/types-ts3.8/orchestrion/config.d.ts"
"build/types-ts3.8/orchestrion/config/index.d.ts"
],

@@ -73,3 +73,3 @@ "orchestrion/register": [

"orchestrion/config": [
"build/types/orchestrion/config.d.ts"
"build/types/orchestrion/config/index.d.ts"
],

@@ -90,5 +90,5 @@ "orchestrion/register": [

"@apm-js-collab/code-transformer": "^0.15.0",
"@apm-js-collab/tracing-hooks": "^0.10.0",
"@sentry/conventions": "^0.12.0",
"@sentry/core": "10.63.0",
"@apm-js-collab/tracing-hooks": "^0.10.1",
"@sentry/conventions": "^0.15.1",
"@sentry/core": "10.64.0",
"magic-string": "~0.30.0"

@@ -95,0 +95,0 @@ },

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const SENTRY_INSTRUMENTATIONS = [
{
channelName: "query",
module: { name: "mysql", versionRange: ">=2.0.0 <3", filePath: "lib/Connection.js" },
// `Connection` in mysql v2 is a constructor function (NOT a class):
// `function Connection(options) { ... }`
// `Connection.prototype.query = function query(sql, values, cb) { ... }`
// orchestrion's `className`+`methodName` query only matches `class` declarations.
// The named function expression on the right-hand side of the prototype
// assignment is what we want — that's matched by `expressionName: 'query'`,
// which produces the esquery selector
// `AssignmentExpression[left.property.name="query"] > FunctionExpression[async]`.
// `Auto` so both `connection.query(sql, cb)` and `connection.query(sql)`
// (streamable, no callback) get channel events. The transform picks
// `wrapCallback` when the last arg is a function and `wrapPromise`
// otherwise — for mysql's no-callback path the latter publishes
// `start`/`end` synchronously around the original call and stores the
// returned `Query` emitter on `ctx.result`, which the integration uses to
// attach `'end'`/`'error'` listeners that finish the span.
functionQuery: { expressionName: "query", kind: "Auto" }
},
{
channelName: "load",
// `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0
module: { name: "lru-memoizer", versionRange: ">=2.1.0 <4", filePath: "lib/async.js" },
functionQuery: { functionName: "memoizedFunction", kind: "Callback" }
}
];
const INSTRUMENTED_MODULE_NAMES = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map((i) => i.module.name)));
function withoutInstrumentedExternals(external) {
if (!external) {
return void 0;
}
return external.filter(
(entry) => !INSTRUMENTED_MODULE_NAMES.some((name) => entry === name || entry.startsWith(`${name}/`))
);
}
exports.INSTRUMENTED_MODULE_NAMES = INSTRUMENTED_MODULE_NAMES;
exports.SENTRY_INSTRUMENTATIONS = SENTRY_INSTRUMENTATIONS;
exports.withoutInstrumentedExternals = withoutInstrumentedExternals;
//# sourceMappingURL=config.js.map
{"version":3,"file":"config.js","sources":["../../../src/orchestrion/config.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\n/**\n * The central list of channel injections orchestrion should perform.\n *\n * This module has NO side effects — it's the only thing both the runtime hook\n * (`runtime/import-hook.mjs`) and the bundler plugins (`bundler/vite.ts`, …)\n * import from. Adding a new instrumented method is one entry here plus one\n * subscriber in `integrations/<lib>/tracing-channel.ts`.\n *\n * `channelName` here is the unprefixed suffix; the actual diagnostics_channel\n * name is `orchestrion:${module.name}:${channelName}` (see `channels.ts`).\n */\nexport const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[] = [\n {\n channelName: 'query',\n module: { name: 'mysql', versionRange: '>=2.0.0 <3', filePath: 'lib/Connection.js' },\n // `Connection` in mysql v2 is a constructor function (NOT a class):\n // `function Connection(options) { ... }`\n // `Connection.prototype.query = function query(sql, values, cb) { ... }`\n // orchestrion's `className`+`methodName` query only matches `class` declarations.\n // The named function expression on the right-hand side of the prototype\n // assignment is what we want — that's matched by `expressionName: 'query'`,\n // which produces the esquery selector\n // `AssignmentExpression[left.property.name=\"query\"] > FunctionExpression[async]`.\n // `Auto` so both `connection.query(sql, cb)` and `connection.query(sql)`\n // (streamable, no callback) get channel events. The transform picks\n // `wrapCallback` when the last arg is a function and `wrapPromise`\n // otherwise — for mysql's no-callback path the latter publishes\n // `start`/`end` synchronously around the original call and stores the\n // returned `Query` emitter on `ctx.result`, which the integration uses to\n // attach `'end'`/`'error'` listeners that finish the span.\n functionQuery: { expressionName: 'query', kind: 'Auto' },\n },\n {\n channelName: 'load',\n // `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0\n module: { name: 'lru-memoizer', versionRange: '>=2.1.0 <4', filePath: 'lib/async.js' },\n functionQuery: { functionName: 'memoizedFunction', kind: 'Callback' },\n },\n];\n\n/**\n * The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`\n * (e.g. `['mysql']`).\n *\n * Bundler plugins MUST ensure these are actually bundled rather than\n * externalized: an externalized dependency is resolved from `node_modules` at\n * runtime and never passes through the code transform's `onLoad`, so its\n * diagnostics_channel calls are silently never injected.\n */\nexport const INSTRUMENTED_MODULE_NAMES: string[] = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map(i => i.module.name)));\n\n/**\n * Returns `external` with any instrumented packages removed, so a bundler that\n * uses an \"external\" denylist (esbuild, Bun, Rollup) still bundles — and thus\n * transforms — them. Matches an exact package name (`'mysql'`) or a subpath\n * (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`\n * is returned unchanged.\n *\n * (Vite uses an `ssr.noExternal` allowlist instead, so it consumes\n * `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)\n */\nexport function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined {\n if (!external) {\n return undefined;\n }\n return external.filter(\n entry => !INSTRUMENTED_MODULE_NAMES.some(name => entry === name || entry.startsWith(`${name}/`)),\n );\n}\n"],"names":[],"mappings":";;AAaO,MAAM,uBAAA,GAAmD;AAAA,EAC9D;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,SAAS,YAAA,EAAc,YAAA,EAAc,UAAU,mBAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBnF,aAAA,EAAe,EAAE,cAAA,EAAgB,OAAA,EAAS,MAAM,MAAA;AAAO,GACzD;AAAA,EACA;AAAA,IACE,WAAA,EAAa,MAAA;AAAA;AAAA,IAEb,QAAQ,EAAE,IAAA,EAAM,gBAAgB,YAAA,EAAc,YAAA,EAAc,UAAU,cAAA,EAAe;AAAA,IACrF,aAAA,EAAe,EAAE,YAAA,EAAc,kBAAA,EAAoB,MAAM,UAAA;AAAW;AAExE;AAWO,MAAM,yBAAA,GAAsC,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,uBAAA,CAAwB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,IAAI,CAAC,CAAC;AAY/G,SAAS,6BAA6B,QAAA,EAA+D;AAC1G,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,CAAS,MAAA;AAAA,IACd,CAAA,KAAA,KAAS,CAAC,yBAAA,CAA0B,IAAA,CAAK,CAAA,IAAA,KAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,CAAM,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAC;AAAA,GACjG;AACF;;;;;;"}
const SENTRY_INSTRUMENTATIONS = [
{
channelName: "query",
module: { name: "mysql", versionRange: ">=2.0.0 <3", filePath: "lib/Connection.js" },
// `Connection` in mysql v2 is a constructor function (NOT a class):
// `function Connection(options) { ... }`
// `Connection.prototype.query = function query(sql, values, cb) { ... }`
// orchestrion's `className`+`methodName` query only matches `class` declarations.
// The named function expression on the right-hand side of the prototype
// assignment is what we want — that's matched by `expressionName: 'query'`,
// which produces the esquery selector
// `AssignmentExpression[left.property.name="query"] > FunctionExpression[async]`.
// `Auto` so both `connection.query(sql, cb)` and `connection.query(sql)`
// (streamable, no callback) get channel events. The transform picks
// `wrapCallback` when the last arg is a function and `wrapPromise`
// otherwise — for mysql's no-callback path the latter publishes
// `start`/`end` synchronously around the original call and stores the
// returned `Query` emitter on `ctx.result`, which the integration uses to
// attach `'end'`/`'error'` listeners that finish the span.
functionQuery: { expressionName: "query", kind: "Auto" }
},
{
channelName: "load",
// `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0
module: { name: "lru-memoizer", versionRange: ">=2.1.0 <4", filePath: "lib/async.js" },
functionQuery: { functionName: "memoizedFunction", kind: "Callback" }
}
];
const INSTRUMENTED_MODULE_NAMES = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map((i) => i.module.name)));
function withoutInstrumentedExternals(external) {
if (!external) {
return void 0;
}
return external.filter(
(entry) => !INSTRUMENTED_MODULE_NAMES.some((name) => entry === name || entry.startsWith(`${name}/`))
);
}
export { INSTRUMENTED_MODULE_NAMES, SENTRY_INSTRUMENTATIONS, withoutInstrumentedExternals };
//# sourceMappingURL=config.js.map
{"version":3,"file":"config.js","sources":["../../../src/orchestrion/config.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';\n\n/**\n * The central list of channel injections orchestrion should perform.\n *\n * This module has NO side effects — it's the only thing both the runtime hook\n * (`runtime/import-hook.mjs`) and the bundler plugins (`bundler/vite.ts`, …)\n * import from. Adding a new instrumented method is one entry here plus one\n * subscriber in `integrations/<lib>/tracing-channel.ts`.\n *\n * `channelName` here is the unprefixed suffix; the actual diagnostics_channel\n * name is `orchestrion:${module.name}:${channelName}` (see `channels.ts`).\n */\nexport const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[] = [\n {\n channelName: 'query',\n module: { name: 'mysql', versionRange: '>=2.0.0 <3', filePath: 'lib/Connection.js' },\n // `Connection` in mysql v2 is a constructor function (NOT a class):\n // `function Connection(options) { ... }`\n // `Connection.prototype.query = function query(sql, values, cb) { ... }`\n // orchestrion's `className`+`methodName` query only matches `class` declarations.\n // The named function expression on the right-hand side of the prototype\n // assignment is what we want — that's matched by `expressionName: 'query'`,\n // which produces the esquery selector\n // `AssignmentExpression[left.property.name=\"query\"] > FunctionExpression[async]`.\n // `Auto` so both `connection.query(sql, cb)` and `connection.query(sql)`\n // (streamable, no callback) get channel events. The transform picks\n // `wrapCallback` when the last arg is a function and `wrapPromise`\n // otherwise — for mysql's no-callback path the latter publishes\n // `start`/`end` synchronously around the original call and stores the\n // returned `Query` emitter on `ctx.result`, which the integration uses to\n // attach `'end'`/`'error'` listeners that finish the span.\n functionQuery: { expressionName: 'query', kind: 'Auto' },\n },\n {\n channelName: 'load',\n // `>=2.1.0` only: the named `function memoizedFunction()` the selector targets exists from 2.1.0\n module: { name: 'lru-memoizer', versionRange: '>=2.1.0 <4', filePath: 'lib/async.js' },\n functionQuery: { functionName: 'memoizedFunction', kind: 'Callback' },\n },\n];\n\n/**\n * The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`\n * (e.g. `['mysql']`).\n *\n * Bundler plugins MUST ensure these are actually bundled rather than\n * externalized: an externalized dependency is resolved from `node_modules` at\n * runtime and never passes through the code transform's `onLoad`, so its\n * diagnostics_channel calls are silently never injected.\n */\nexport const INSTRUMENTED_MODULE_NAMES: string[] = Array.from(new Set(SENTRY_INSTRUMENTATIONS.map(i => i.module.name)));\n\n/**\n * Returns `external` with any instrumented packages removed, so a bundler that\n * uses an \"external\" denylist (esbuild, Bun, Rollup) still bundles — and thus\n * transforms — them. Matches an exact package name (`'mysql'`) or a subpath\n * (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`\n * is returned unchanged.\n *\n * (Vite uses an `ssr.noExternal` allowlist instead, so it consumes\n * `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)\n */\nexport function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined {\n if (!external) {\n return undefined;\n }\n return external.filter(\n entry => !INSTRUMENTED_MODULE_NAMES.some(name => entry === name || entry.startsWith(`${name}/`)),\n );\n}\n"],"names":[],"mappings":"AAaO,MAAM,uBAAA,GAAmD;AAAA,EAC9D;AAAA,IACE,WAAA,EAAa,OAAA;AAAA,IACb,QAAQ,EAAE,IAAA,EAAM,SAAS,YAAA,EAAc,YAAA,EAAc,UAAU,mBAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBnF,aAAA,EAAe,EAAE,cAAA,EAAgB,OAAA,EAAS,MAAM,MAAA;AAAO,GACzD;AAAA,EACA;AAAA,IACE,WAAA,EAAa,MAAA;AAAA;AAAA,IAEb,QAAQ,EAAE,IAAA,EAAM,gBAAgB,YAAA,EAAc,YAAA,EAAc,UAAU,cAAA,EAAe;AAAA,IACrF,aAAA,EAAe,EAAE,YAAA,EAAc,kBAAA,EAAoB,MAAM,UAAA;AAAW;AAExE;AAWO,MAAM,yBAAA,GAAsC,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,uBAAA,CAAwB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,IAAI,CAAC,CAAC;AAY/G,SAAS,6BAA6B,QAAA,EAA+D;AAC1G,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,CAAS,MAAA;AAAA,IACd,CAAA,KAAA,KAAS,CAAC,yBAAA,CAA0B,IAAA,CAAK,CAAA,IAAA,KAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,CAAM,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAC;AAAA,GACjG;AACF;;;;"}
import { InstrumentationConfig } from '@apm-js-collab/code-transformer';
/**
* The central list of channel injections orchestrion should perform.
*
* This module has NO side effects — it's the only thing both the runtime hook
* (`runtime/import-hook.mjs`) and the bundler plugins (`bundler/vite.ts`, …)
* import from. Adding a new instrumented method is one entry here plus one
* subscriber in `integrations/<lib>/tracing-channel.ts`.
*
* `channelName` here is the unprefixed suffix; the actual diagnostics_channel
* name is `orchestrion:${module.name}:${channelName}` (see `channels.ts`).
*/
export declare const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[];
/**
* The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`
* (e.g. `['mysql']`).
*
* Bundler plugins MUST ensure these are actually bundled rather than
* externalized: an externalized dependency is resolved from `node_modules` at
* runtime and never passes through the code transform's `onLoad`, so its
* diagnostics_channel calls are silently never injected.
*/
export declare const INSTRUMENTED_MODULE_NAMES: string[];
/**
* Returns `external` with any instrumented packages removed, so a bundler that
* uses an "external" denylist (esbuild, Bun, Rollup) still bundles — and thus
* transforms — them. Matches an exact package name (`'mysql'`) or a subpath
* (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`
* is returned unchanged.
*
* (Vite uses an `ssr.noExternal` allowlist instead, so it consumes
* `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)
*/
export declare function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined;
//# sourceMappingURL=config.d.ts.map
import type { InstrumentationConfig } from '@apm-js-collab/code-transformer';
/**
* The central list of channel injections orchestrion should perform.
*
* This module has NO side effects — it's the only thing both the runtime hook
* (`runtime/import-hook.mjs`) and the bundler plugins (`bundler/vite.ts`, …)
* import from. Adding a new instrumented method is one entry here plus one
* subscriber in `integrations/<lib>/tracing-channel.ts`.
*
* `channelName` here is the unprefixed suffix; the actual diagnostics_channel
* name is `orchestrion:${module.name}:${channelName}` (see `channels.ts`).
*/
export declare const SENTRY_INSTRUMENTATIONS: InstrumentationConfig[];
/**
* The unique set of package names instrumented by `SENTRY_INSTRUMENTATIONS`
* (e.g. `['mysql']`).
*
* Bundler plugins MUST ensure these are actually bundled rather than
* externalized: an externalized dependency is resolved from `node_modules` at
* runtime and never passes through the code transform's `onLoad`, so its
* diagnostics_channel calls are silently never injected.
*/
export declare const INSTRUMENTED_MODULE_NAMES: string[];
/**
* Returns `external` with any instrumented packages removed, so a bundler that
* uses an "external" denylist (esbuild, Bun, Rollup) still bundles — and thus
* transforms — them. Matches an exact package name (`'mysql'`) or a subpath
* (`'mysql/lib/...'`); wildcard/other patterns are left untouched. `undefined`
* is returned unchanged.
*
* (Vite uses an `ssr.noExternal` allowlist instead, so it consumes
* `INSTRUMENTED_MODULE_NAMES` directly rather than this helper.)
*/
export declare function withoutInstrumentedExternals(external: readonly string[] | undefined): string[] | undefined;
//# sourceMappingURL=config.d.ts.map
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/orchestrion/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,EAAE,qBAAqB,EA2B1D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,EAAyE,CAAC;AAExH;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAO1G"}