@sentry/core 10.50.0 → 10.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/client.js +27 -3
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/envelope.js +4 -1
- package/build/cjs/envelope.js.map +1 -1
- package/build/cjs/index.js +10 -5
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrument/console.js +3 -1
- package/build/cjs/instrument/console.js.map +1 -1
- package/build/cjs/instrument/fetch.js +6 -2
- package/build/cjs/instrument/fetch.js.map +1 -1
- package/build/cjs/instrument/handlers.js +11 -1
- package/build/cjs/instrument/handlers.js.map +1 -1
- package/build/cjs/integrations/console.js +3 -1
- package/build/cjs/integrations/console.js.map +1 -1
- package/build/cjs/integrations/extraerrordata.js +2 -2
- package/build/cjs/integrations/extraerrordata.js.map +1 -1
- package/build/cjs/integrations/postgresjs.js +10 -1
- package/build/cjs/integrations/postgresjs.js.map +1 -1
- package/build/cjs/integrations/requestdata.js +9 -5
- package/build/cjs/integrations/requestdata.js.map +1 -1
- package/build/cjs/integrations/supabase.js +39 -12
- package/build/cjs/integrations/supabase.js.map +1 -1
- package/build/cjs/logs/console-integration.js +3 -1
- package/build/cjs/logs/console-integration.js.map +1 -1
- package/build/cjs/server-runtime-client.js +20 -2
- package/build/cjs/server-runtime-client.js.map +1 -1
- package/build/cjs/tracing/ai/gen-ai-attributes.js +6 -0
- package/build/cjs/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/cjs/tracing/idleSpan.js +7 -1
- package/build/cjs/tracing/idleSpan.js.map +1 -1
- package/build/cjs/tracing/langchain/index.js +43 -8
- package/build/cjs/tracing/langchain/index.js.map +1 -1
- package/build/cjs/tracing/langchain/utils.js +44 -10
- package/build/cjs/tracing/langchain/utils.js.map +1 -1
- package/build/cjs/tracing/langgraph/index.js +105 -2
- package/build/cjs/tracing/langgraph/index.js.map +1 -1
- package/build/cjs/tracing/langgraph/utils.js +168 -0
- package/build/cjs/tracing/langgraph/utils.js.map +1 -1
- package/build/cjs/tracing/spans/captureSpan.js +125 -0
- package/build/cjs/tracing/spans/captureSpan.js.map +1 -1
- package/build/cjs/tracing/spans/envelope.js +13 -3
- package/build/cjs/tracing/spans/envelope.js.map +1 -1
- package/build/cjs/tracing/trace.js +1 -0
- package/build/cjs/tracing/trace.js.map +1 -1
- package/build/cjs/trpc.js +2 -3
- package/build/cjs/trpc.js.map +1 -1
- package/build/cjs/utils/isSentryRequestUrl.js +9 -1
- package/build/cjs/utils/isSentryRequestUrl.js.map +1 -1
- package/build/cjs/utils/normalizationHints.js +38 -0
- package/build/cjs/utils/normalizationHints.js.map +1 -0
- package/build/cjs/utils/normalize.js +7 -11
- package/build/cjs/utils/normalize.js.map +1 -1
- package/build/cjs/utils/object.js +1 -1
- package/build/cjs/utils/object.js.map +1 -1
- package/build/cjs/utils/request.js +63 -12
- package/build/cjs/utils/request.js.map +1 -1
- package/build/cjs/utils/should-ignore-span.js +27 -8
- package/build/cjs/utils/should-ignore-span.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/esm/client.js +27 -3
- package/build/esm/client.js.map +1 -1
- package/build/esm/envelope.js +4 -1
- package/build/esm/envelope.js.map +1 -1
- package/build/esm/index.js +3 -2
- package/build/esm/index.js.map +1 -1
- package/build/esm/instrument/console.js +3 -1
- package/build/esm/instrument/console.js.map +1 -1
- package/build/esm/instrument/fetch.js +6 -2
- package/build/esm/instrument/fetch.js.map +1 -1
- package/build/esm/instrument/handlers.js +11 -1
- package/build/esm/instrument/handlers.js.map +1 -1
- package/build/esm/integrations/console.js +3 -1
- package/build/esm/integrations/console.js.map +1 -1
- package/build/esm/integrations/extraerrordata.js +2 -2
- package/build/esm/integrations/extraerrordata.js.map +1 -1
- package/build/esm/integrations/postgresjs.js +10 -1
- package/build/esm/integrations/postgresjs.js.map +1 -1
- package/build/esm/integrations/requestdata.js +9 -5
- package/build/esm/integrations/requestdata.js.map +1 -1
- package/build/esm/integrations/supabase.js +39 -12
- package/build/esm/integrations/supabase.js.map +1 -1
- package/build/esm/logs/console-integration.js +3 -1
- package/build/esm/logs/console-integration.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server-runtime-client.js +20 -2
- package/build/esm/server-runtime-client.js.map +1 -1
- package/build/esm/tracing/ai/gen-ai-attributes.js +6 -1
- package/build/esm/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/esm/tracing/idleSpan.js +7 -1
- package/build/esm/tracing/idleSpan.js.map +1 -1
- package/build/esm/tracing/langchain/index.js +45 -10
- package/build/esm/tracing/langchain/index.js.map +1 -1
- package/build/esm/tracing/langchain/utils.js +44 -12
- package/build/esm/tracing/langchain/utils.js.map +1 -1
- package/build/esm/tracing/langgraph/index.js +107 -5
- package/build/esm/tracing/langgraph/index.js.map +1 -1
- package/build/esm/tracing/langgraph/utils.js +166 -2
- package/build/esm/tracing/langgraph/utils.js.map +1 -1
- package/build/esm/tracing/spans/captureSpan.js +126 -2
- package/build/esm/tracing/spans/captureSpan.js.map +1 -1
- package/build/esm/tracing/spans/envelope.js +13 -3
- package/build/esm/tracing/spans/envelope.js.map +1 -1
- package/build/esm/tracing/trace.js +1 -0
- package/build/esm/tracing/trace.js.map +1 -1
- package/build/esm/trpc.js +2 -3
- package/build/esm/trpc.js.map +1 -1
- package/build/esm/utils/isSentryRequestUrl.js +9 -1
- package/build/esm/utils/isSentryRequestUrl.js.map +1 -1
- package/build/esm/utils/normalizationHints.js +33 -0
- package/build/esm/utils/normalizationHints.js.map +1 -0
- package/build/esm/utils/normalize.js +7 -11
- package/build/esm/utils/normalize.js.map +1 -1
- package/build/esm/utils/object.js +1 -1
- package/build/esm/utils/object.js.map +1 -1
- package/build/esm/utils/request.js +63 -12
- package/build/esm/utils/request.js.map +1 -1
- package/build/esm/utils/should-ignore-span.js +27 -8
- package/build/esm/utils/should-ignore-span.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/types/client.d.ts +12 -1
- package/build/types/client.d.ts.map +1 -1
- package/build/types/envelope.d.ts.map +1 -1
- package/build/types/index.d.ts +4 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrument/console.d.ts +2 -1
- package/build/types/instrument/console.d.ts.map +1 -1
- package/build/types/instrument/fetch.d.ts +4 -2
- package/build/types/instrument/fetch.d.ts.map +1 -1
- package/build/types/instrument/handlers.d.ts +2 -2
- package/build/types/instrument/handlers.d.ts.map +1 -1
- package/build/types/integrations/console.d.ts.map +1 -1
- package/build/types/integrations/postgresjs.d.ts.map +1 -1
- package/build/types/integrations/supabase.d.ts.map +1 -1
- package/build/types/logs/console-integration.d.ts.map +1 -1
- package/build/types/server-runtime-client.d.ts +5 -0
- package/build/types/server-runtime-client.d.ts.map +1 -1
- package/build/types/tracing/idleSpan.d.ts.map +1 -1
- package/build/types/tracing/langchain/index.d.ts.map +1 -1
- package/build/types/tracing/langchain/types.d.ts +8 -0
- package/build/types/tracing/langchain/types.d.ts.map +1 -1
- package/build/types/tracing/langchain/utils.d.ts +2 -0
- package/build/types/tracing/langchain/utils.d.ts.map +1 -1
- package/build/types/tracing/langgraph/index.d.ts +4 -0
- package/build/types/tracing/langgraph/index.d.ts.map +1 -1
- package/build/types/tracing/langgraph/utils.d.ts +18 -2
- package/build/types/tracing/langgraph/utils.d.ts.map +1 -1
- package/build/types/tracing/spans/captureSpan.d.ts +10 -0
- package/build/types/tracing/spans/captureSpan.d.ts.map +1 -1
- package/build/types/tracing/spans/envelope.d.ts.map +1 -1
- package/build/types/trpc.d.ts.map +1 -1
- package/build/types/types-hoist/feedback/config.d.ts +20 -0
- package/build/types/types-hoist/feedback/config.d.ts.map +1 -1
- package/build/types/types-hoist/feedback/index.d.ts +2 -2
- package/build/types/types-hoist/feedback/index.d.ts.map +1 -1
- package/build/types/types-hoist/feedback/sendFeedback.d.ts +3 -0
- package/build/types/types-hoist/feedback/sendFeedback.d.ts.map +1 -1
- package/build/types/types-hoist/options.d.ts +37 -2
- package/build/types/types-hoist/options.d.ts.map +1 -1
- package/build/types/types-hoist/span.d.ts +5 -0
- package/build/types/types-hoist/span.d.ts.map +1 -1
- package/build/types/utils/normalizationHints.d.ts +9 -0
- package/build/types/utils/normalizationHints.d.ts.map +1 -0
- package/build/types/utils/normalize.d.ts.map +1 -1
- package/build/types/utils/object.d.ts +1 -1
- package/build/types/utils/object.d.ts.map +1 -1
- package/build/types/utils/request.d.ts.map +1 -1
- package/build/types/utils/should-ignore-span.d.ts +3 -1
- package/build/types/utils/should-ignore-span.d.ts.map +1 -1
- package/build/types-ts3.8/client.d.ts +12 -1
- package/build/types-ts3.8/index.d.ts +4 -2
- package/build/types-ts3.8/instrument/console.d.ts +2 -1
- package/build/types-ts3.8/instrument/fetch.d.ts +4 -2
- package/build/types-ts3.8/instrument/handlers.d.ts +2 -2
- package/build/types-ts3.8/server-runtime-client.d.ts +5 -0
- package/build/types-ts3.8/tracing/langchain/types.d.ts +8 -0
- package/build/types-ts3.8/tracing/langchain/utils.d.ts +2 -0
- package/build/types-ts3.8/tracing/langgraph/index.d.ts +4 -0
- package/build/types-ts3.8/tracing/langgraph/utils.d.ts +18 -2
- package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +10 -0
- package/build/types-ts3.8/types-hoist/feedback/config.d.ts +20 -0
- package/build/types-ts3.8/types-hoist/feedback/index.d.ts +2 -2
- package/build/types-ts3.8/types-hoist/feedback/sendFeedback.d.ts +3 -0
- package/build/types-ts3.8/types-hoist/options.d.ts +37 -2
- package/build/types-ts3.8/types-hoist/span.d.ts +5 -0
- package/build/types-ts3.8/utils/normalizationHints.d.ts +9 -0
- package/build/types-ts3.8/utils/object.d.ts +1 -1
- package/build/types-ts3.8/utils/should-ignore-span.d.ts +3 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idleSpan.js","sources":["../../../src/tracing/idleSpan.ts"],"sourcesContent":["import { getClient, getCurrentScope } from '../currentScopes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '../semanticAttributes';\nimport type { DynamicSamplingContext } from '../types-hoist/envelope';\nimport type { Span } from '../types-hoist/span';\nimport type { StartSpanOptions } from '../types-hoist/startSpanOptions';\nimport { debug } from '../utils/debug-logger';\nimport { hasSpansEnabled } from '../utils/hasSpansEnabled';\nimport { shouldIgnoreSpan } from '../utils/should-ignore-span';\nimport { _setSpanForScope } from '../utils/spanOnScope';\nimport {\n getActiveSpan,\n getSpanDescendants,\n removeChildSpanFromSpan,\n spanTimeInputToSeconds,\n spanToJSON,\n} from '../utils/spanUtils';\nimport { timestampInSeconds } from '../utils/time';\nimport { freezeDscOnSpan, getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';\nimport { SentryNonRecordingSpan } from './sentryNonRecordingSpan';\nimport { SentrySpan } from './sentrySpan';\nimport { SPAN_STATUS_ERROR, SPAN_STATUS_OK } from './spanstatus';\nimport { startInactiveSpan } from './trace';\n\nexport const TRACING_DEFAULTS = {\n idleTimeout: 1_000,\n finalTimeout: 30_000,\n childSpanTimeout: 15_000,\n};\n\nconst FINISH_REASON_HEARTBEAT_FAILED = 'heartbeatFailed';\nconst FINISH_REASON_IDLE_TIMEOUT = 'idleTimeout';\nconst FINISH_REASON_FINAL_TIMEOUT = 'finalTimeout';\nconst FINISH_REASON_EXTERNAL_FINISH = 'externalFinish';\nconst FINISH_REASON_CANCELLED = 'cancelled';\n\n// unused\nconst FINISH_REASON_DOCUMENT_HIDDEN = 'documentHidden';\n\n// unused in this file, but used in BrowserTracing\nconst FINISH_REASON_INTERRUPTED = 'interactionInterrupted';\n\ntype IdleSpanFinishReason =\n | typeof FINISH_REASON_CANCELLED\n | typeof FINISH_REASON_DOCUMENT_HIDDEN\n | typeof FINISH_REASON_EXTERNAL_FINISH\n | typeof FINISH_REASON_FINAL_TIMEOUT\n | typeof FINISH_REASON_HEARTBEAT_FAILED\n | typeof FINISH_REASON_IDLE_TIMEOUT\n | typeof FINISH_REASON_INTERRUPTED;\n\ninterface IdleSpanOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n */\n idleTimeout: number;\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n */\n finalTimeout: number;\n /**\n * The max. time a child span may run.\n * If the time since the last span was started exceeds this time, the idle span will finish.\n */\n childSpanTimeout?: number;\n /**\n * When set to `true`, will disable the idle timeout and child timeout\n * until the `idleSpanEnableAutoFinish` hook is emitted for the idle span.\n * The final timeout mechanism will not be affected by this option,\n * meaning the idle span will definitely be finished when the final timeout is\n * reached, no matter what this option is configured to.\n *\n * Defaults to `false`.\n */\n disableAutoFinish?: boolean;\n\n /** Allows to configure a hook that is called when the idle span is ended, before it is processed. */\n beforeSpanEnd?: (span: Span) => void;\n\n /**\n * If set to `true`, the idle span will be trimmed to the latest span end timestamp of its children.\n *\n * @default `true`.\n */\n trimIdleSpanEndTimestamp?: boolean;\n}\n\n/**\n * An idle span is a span that automatically finishes. It does this by tracking child spans as activities.\n * An idle span is always the active span.\n */\nexport function startIdleSpan(startSpanOptions: StartSpanOptions, options: Partial<IdleSpanOptions> = {}): Span {\n // Activities store a list of active spans\n const activities = new Map<string, boolean>();\n\n // We should not use heartbeat if we finished a span\n let _finished = false;\n\n // Timer that tracks idleTimeout\n let _idleTimeoutID: ReturnType<typeof setTimeout> | undefined;\n\n // Timer that tracks maxSpanTime for child spans\n let _childSpanTimeoutID: ReturnType<typeof setTimeout> | undefined;\n\n // The reason why the span was finished\n let _finishReason: IdleSpanFinishReason = FINISH_REASON_EXTERNAL_FINISH;\n\n let _autoFinishAllowed: boolean = !options.disableAutoFinish;\n\n const _cleanupHooks: (() => void)[] = [];\n\n const {\n idleTimeout = TRACING_DEFAULTS.idleTimeout,\n finalTimeout = TRACING_DEFAULTS.finalTimeout,\n childSpanTimeout = TRACING_DEFAULTS.childSpanTimeout,\n beforeSpanEnd,\n trimIdleSpanEndTimestamp = true,\n } = options;\n\n const client = getClient();\n\n if (!client || !hasSpansEnabled()) {\n const span = new SentryNonRecordingSpan();\n\n const dsc = {\n sample_rate: '0',\n sampled: 'false',\n ...getDynamicSamplingContextFromSpan(span),\n } satisfies Partial<DynamicSamplingContext>;\n freezeDscOnSpan(span, dsc);\n\n return span;\n }\n\n const scope = getCurrentScope();\n const previousActiveSpan = getActiveSpan();\n const span = _startIdleSpan(startSpanOptions);\n\n // We patch span.end to ensure we can run some things before the span is ended\n // eslint-disable-next-line @typescript-eslint/unbound-method\n span.end = new Proxy(span.end, {\n apply(target, thisArg, args: Parameters<Span['end']>) {\n if (beforeSpanEnd) {\n beforeSpanEnd(span);\n }\n\n // If the span is non-recording, nothing more to do here...\n // This is the case if tracing is enabled but this specific span was not sampled\n if (thisArg instanceof SentryNonRecordingSpan) {\n return;\n }\n\n // Just ensuring that this keeps working, even if we ever have more arguments here\n const [definedEndTimestamp, ...rest] = args;\n const timestamp = definedEndTimestamp || timestampInSeconds();\n const spanEndTimestamp = spanTimeInputToSeconds(timestamp);\n\n // Ensure we end with the last span timestamp, if possible\n const spans = getSpanDescendants(span).filter(child => child !== span);\n\n const spanJson = spanToJSON(span);\n\n // If we have no spans, we just end, nothing else to do here\n // Likewise, if users explicitly ended the span, we simply end the span without timestamp adjustment\n if (!spans.length || !trimIdleSpanEndTimestamp) {\n onIdleSpanEnded(spanEndTimestamp);\n return Reflect.apply(target, thisArg, [spanEndTimestamp, ...rest]);\n }\n\n const ignoreSpans = client.getOptions().ignoreSpans;\n\n const latestSpanEndTimestamp = spans?.reduce((acc: number | undefined, current) => {\n const currentSpanJson = spanToJSON(current);\n if (!currentSpanJson.timestamp) {\n return acc;\n }\n // Ignored spans will get dropped later (in the client) but since we already adjust\n // the idle span end timestamp here, we can already take to-be-ignored spans out of\n // the calculation here.\n if (ignoreSpans && shouldIgnoreSpan(currentSpanJson, ignoreSpans)) {\n return acc;\n }\n return acc ? Math.max(acc, currentSpanJson.timestamp) : currentSpanJson.timestamp;\n }, undefined);\n\n // In reality this should always exist here, but type-wise it may be undefined...\n const spanStartTimestamp = spanJson.start_timestamp;\n\n // The final endTimestamp should:\n // * Never be before the span start timestamp\n // * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp\n // * Otherwise be the passed end timestamp\n // Final timestamp can never be after finalTimeout\n const endTimestamp = Math.min(\n spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity,\n Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)),\n );\n\n onIdleSpanEnded(endTimestamp);\n return Reflect.apply(target, thisArg, [endTimestamp, ...rest]);\n },\n });\n\n /**\n * Cancels the existing idle timeout, if there is one.\n */\n function _cancelIdleTimeout(): void {\n if (_idleTimeoutID) {\n clearTimeout(_idleTimeoutID);\n _idleTimeoutID = undefined;\n }\n }\n\n /**\n * Cancels the existing child span timeout, if there is one.\n */\n function _cancelChildSpanTimeout(): void {\n if (_childSpanTimeoutID) {\n clearTimeout(_childSpanTimeoutID);\n _childSpanTimeoutID = undefined;\n }\n }\n\n /**\n * Restarts idle timeout, if there is no running idle timeout it will start one.\n */\n function _restartIdleTimeout(endTimestamp?: number): void {\n _cancelIdleTimeout();\n _idleTimeoutID = setTimeout(() => {\n if (!_finished && activities.size === 0 && _autoFinishAllowed) {\n _finishReason = FINISH_REASON_IDLE_TIMEOUT;\n span.end(endTimestamp);\n }\n }, idleTimeout);\n }\n\n /**\n * Restarts child span timeout, if there is none running it will start one.\n */\n function _restartChildSpanTimeout(endTimestamp?: number): void {\n _cancelChildSpanTimeout();\n _idleTimeoutID = setTimeout(() => {\n if (!_finished && _autoFinishAllowed) {\n _finishReason = FINISH_REASON_HEARTBEAT_FAILED;\n span.end(endTimestamp);\n }\n }, childSpanTimeout);\n }\n\n /**\n * Start tracking a specific activity.\n * @param spanId The span id that represents the activity\n */\n function _pushActivity(spanId: string): void {\n _cancelIdleTimeout();\n activities.set(spanId, true);\n\n const endTimestamp = timestampInSeconds();\n // We need to add the timeout here to have the real endtimestamp of the idle span\n // Remember timestampInSeconds is in seconds, timeout is in ms\n _restartChildSpanTimeout(endTimestamp + childSpanTimeout / 1000);\n }\n\n /**\n * Remove an activity from usage\n * @param spanId The span id that represents the activity\n */\n function _popActivity(spanId: string): void {\n if (activities.has(spanId)) {\n activities.delete(spanId);\n }\n\n if (activities.size === 0) {\n const endTimestamp = timestampInSeconds();\n // We need to add the timeout here to have the real endtimestamp of the idle span\n // Remember timestampInSeconds is in seconds, timeout is in ms\n _restartIdleTimeout(endTimestamp + idleTimeout / 1000);\n _cancelChildSpanTimeout();\n }\n }\n\n function onIdleSpanEnded(endTimestamp: number): void {\n _finished = true;\n activities.clear();\n\n _cleanupHooks.forEach(cleanup => cleanup());\n\n _setSpanForScope(scope, previousActiveSpan);\n\n const spanJSON = spanToJSON(span);\n\n const { start_timestamp: startTimestamp } = spanJSON;\n // This should never happen, but to make TS happy...\n if (!startTimestamp) {\n return;\n }\n\n const attributes = spanJSON.data;\n if (!attributes[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, _finishReason);\n }\n\n // Set span status to 'ok' if it hasn't been explicitly set to an error status\n const currentStatus = spanJSON.status;\n if (!currentStatus || currentStatus === 'unknown') {\n span.setStatus({ code: SPAN_STATUS_OK });\n }\n\n debug.log(`[Tracing] Idle span \"${spanJSON.op}\" finished`);\n\n const childSpans = getSpanDescendants(span).filter(child => child !== span);\n\n let discardedSpans = 0;\n childSpans.forEach(childSpan => {\n // We cancel all pending spans with status \"cancelled\" to indicate the idle span was finished early\n if (childSpan.isRecording()) {\n childSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n childSpan.end(endTimestamp);\n DEBUG_BUILD &&\n debug.log('[Tracing] Cancelling span since span ended early', JSON.stringify(childSpan, undefined, 2));\n }\n\n const childSpanJSON = spanToJSON(childSpan);\n const { timestamp: childEndTimestamp = 0, start_timestamp: childStartTimestamp = 0 } = childSpanJSON;\n\n const spanStartedBeforeIdleSpanEnd = childStartTimestamp <= endTimestamp;\n\n // Add a delta with idle timeout so that we prevent false positives\n const timeoutWithMarginOfError = (finalTimeout + idleTimeout) / 1000;\n const spanEndedBeforeFinalTimeout = childEndTimestamp - childStartTimestamp <= timeoutWithMarginOfError;\n\n if (DEBUG_BUILD) {\n const stringifiedSpan = JSON.stringify(childSpan, undefined, 2);\n if (!spanStartedBeforeIdleSpanEnd) {\n debug.log('[Tracing] Discarding span since it happened after idle span was finished', stringifiedSpan);\n } else if (!spanEndedBeforeFinalTimeout) {\n debug.log('[Tracing] Discarding span since it finished after idle span final timeout', stringifiedSpan);\n }\n }\n\n if (!spanEndedBeforeFinalTimeout || !spanStartedBeforeIdleSpanEnd) {\n removeChildSpanFromSpan(span, childSpan);\n discardedSpans++;\n }\n });\n\n if (discardedSpans > 0) {\n span.setAttribute('sentry.idle_span_discarded_spans', discardedSpans);\n }\n }\n\n _cleanupHooks.push(\n client.on('spanStart', startedSpan => {\n // If we already finished the idle span,\n // or if this is the idle span itself being started,\n // or if the started span has already been closed,\n // we don't care about it for activity\n if (\n _finished ||\n startedSpan === span ||\n !!spanToJSON(startedSpan).timestamp ||\n (startedSpan instanceof SentrySpan && startedSpan.isStandaloneSpan())\n ) {\n return;\n }\n\n const allSpans = getSpanDescendants(span);\n\n // If the span that was just started is a child of the idle span, we should track it\n if (allSpans.includes(startedSpan)) {\n _pushActivity(startedSpan.spanContext().spanId);\n }\n }),\n );\n\n _cleanupHooks.push(\n client.on('spanEnd', endedSpan => {\n if (_finished) {\n return;\n }\n\n _popActivity(endedSpan.spanContext().spanId);\n }),\n );\n\n _cleanupHooks.push(\n client.on('idleSpanEnableAutoFinish', spanToAllowAutoFinish => {\n if (spanToAllowAutoFinish === span) {\n _autoFinishAllowed = true;\n _restartIdleTimeout();\n\n if (activities.size) {\n _restartChildSpanTimeout();\n }\n }\n }),\n );\n\n // We only start the initial idle timeout if we are not delaying the auto finish\n if (!options.disableAutoFinish) {\n _restartIdleTimeout();\n }\n\n setTimeout(() => {\n if (!_finished) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });\n _finishReason = FINISH_REASON_FINAL_TIMEOUT;\n span.end();\n }\n }, finalTimeout);\n\n return span;\n}\n\nfunction _startIdleSpan(options: StartSpanOptions): Span {\n const span = startInactiveSpan(options);\n\n _setSpanForScope(getCurrentScope(), span);\n\n DEBUG_BUILD && debug.log('[Tracing] Started span is an idle span');\n\n return span;\n}\n"],"names":["getClient","hasSpansEnabled","SentryNonRecordingSpan","getDynamicSamplingContextFromSpan","freezeDscOnSpan","getCurrentScope","getActiveSpan","timestampInSeconds","spanTimeInputToSeconds","getSpanDescendants","spanToJSON","shouldIgnoreSpan","_setSpanForScope","SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON","SPAN_STATUS_OK","debug","SPAN_STATUS_ERROR","DEBUG_BUILD","removeChildSpanFromSpan","SentrySpan","startInactiveSpan"],"mappings":";;;;;;;;;;;;;;;;;AAwBO,MAAM,mBAAmB;AAChC,EAAE,WAAW,EAAE,IAAK;AACpB,EAAE,YAAY,EAAE,KAAM;AACtB,EAAE,gBAAgB,EAAE,KAAM;AAC1B;;AAEA,MAAM,8BAAA,GAAiC,iBAAiB;AACxD,MAAM,0BAAA,GAA6B,aAAa;AAChD,MAAM,2BAAA,GAA8B,cAAc;AAClD,MAAM,6BAAA,GAAgC,gBAAgB;;AAwDtD;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,gBAAgB,EAAoB,OAAO,GAA6B,EAAE,EAAQ;AAChH;AACA,EAAE,MAAM,UAAA,GAAa,IAAI,GAAG,EAAmB;;AAE/C;AACA,EAAE,IAAI,SAAA,GAAY,KAAK;;AAEvB;AACA,EAAE,IAAI,cAAc;;AAKpB;AACA,EAAE,IAAI,aAAa,GAAyB,6BAA6B;;AAEzE,EAAE,IAAI,kBAAkB,GAAY,CAAC,OAAO,CAAC,iBAAiB;;AAE9D,EAAE,MAAM,aAAa,GAAmB,EAAE;;AAE1C,EAAE,MAAM;AACR,IAAI,WAAA,GAAc,gBAAgB,CAAC,WAAW;AAC9C,IAAI,YAAA,GAAe,gBAAgB,CAAC,YAAY;AAChD,IAAI,gBAAA,GAAmB,gBAAgB,CAAC,gBAAgB;AACxD,IAAI,aAAa;AACjB,IAAI,wBAAA,GAA2B,IAAI;AACnC,GAAE,GAAI,OAAO;;AAEb,EAAE,MAAM,MAAA,GAASA,uBAAS,EAAE;;AAE5B,EAAE,IAAI,CAAC,MAAA,IAAU,CAACC,+BAAe,EAAE,EAAE;AACrC,IAAI,MAAM,IAAA,GAAO,IAAIC,6CAAsB,EAAE;;AAE7C,IAAI,MAAM,MAAM;AAChB,MAAM,WAAW,EAAE,GAAG;AACtB,MAAM,OAAO,EAAE,OAAO;AACtB,MAAM,GAAGC,wDAAiC,CAAC,IAAI,CAAC;AAChD,KAAI;AACJ,IAAIC,sCAAe,CAAC,IAAI,EAAE,GAAG,CAAC;;AAE9B,IAAI,OAAO,IAAI;AACf,EAAE;;AAEF,EAAE,MAAM,KAAA,GAAQC,6BAAe,EAAE;AACjC,EAAE,MAAM,kBAAA,GAAqBC,uBAAa,EAAE;AAC5C,EAAE,MAAM,IAAA,GAAO,cAAc,CAAC,gBAAgB,CAAC;;AAE/C;AACA;AACA,EAAE,IAAI,CAAC,GAAA,GAAM,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;AACjC,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAA2B;AAC1D,MAAM,IAAI,aAAa,EAAE;AACzB,QAAQ,aAAa,CAAC,IAAI,CAAC;AAC3B,MAAM;;AAEN;AACA;AACA,MAAM,IAAI,OAAA,YAAmBJ,6CAAsB,EAAE;AACrD,QAAQ;AACR,MAAM;;AAEN;AACA,MAAM,MAAM,CAAC,mBAAmB,EAAE,GAAG,IAAI,CAAA,GAAI,IAAI;AACjD,MAAM,MAAM,SAAA,GAAY,uBAAuBK,uBAAkB,EAAE;AACnE,MAAM,MAAM,gBAAA,GAAmBC,gCAAsB,CAAC,SAAS,CAAC;;AAEhE;AACA,MAAM,MAAM,KAAA,GAAQC,4BAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAA,IAAS,KAAA,KAAU,IAAI,CAAC;;AAE5E,MAAM,MAAM,QAAA,GAAWC,oBAAU,CAAC,IAAI,CAAC;;AAEvC;AACA;AACA,MAAM,IAAI,CAAC,KAAK,CAAC,MAAA,IAAU,CAAC,wBAAwB,EAAE;AACtD,QAAQ,eAAe,CAAC,gBAAgB,CAAC;AACzC,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC;AAC1E,MAAM;;AAEN,MAAM,MAAM,cAAc,MAAM,CAAC,UAAU,EAAE,CAAC,WAAW;;AAEzD,MAAM,MAAM,sBAAA,GAAyB,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,EAAsB,OAAO,KAAK;AACzF,QAAQ,MAAM,eAAA,GAAkBA,oBAAU,CAAC,OAAO,CAAC;AACnD,QAAQ,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;AACxC,UAAU,OAAO,GAAG;AACpB,QAAQ;AACR;AACA;AACA;AACA,QAAQ,IAAI,WAAA,IAAeC,iCAAgB,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE;AAC3E,UAAU,OAAO,GAAG;AACpB,QAAQ;AACR,QAAQ,OAAO,GAAA,GAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,CAAC,SAAS,CAAA,GAAI,eAAe,CAAC,SAAS;AACzF,MAAM,CAAC,EAAE,SAAS,CAAC;;AAEnB;AACA,MAAM,MAAM,kBAAA,GAAqB,QAAQ,CAAC,eAAe;;AAEzD;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,YAAA,GAAe,IAAI,CAAC,GAAG;AACnC,QAAQ,kBAAA,GAAqB,kBAAA,GAAqB,eAAe,IAAA,GAAO,QAAQ;AAChF,QAAQ,IAAI,CAAC,GAAG,CAAC,kBAAA,IAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,0BAA0B,QAAQ,CAAC,CAAC;AACjH,OAAO;;AAEP,MAAM,eAAe,CAAC,YAAY,CAAC;AACnC,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,CAAC;AACpE,IAAI,CAAC;AACL,GAAG,CAAC;;AAEJ;AACA;AACA;AACA,EAAE,SAAS,kBAAkB,GAAS;AACtC,IAAI,IAAI,cAAc,EAAE;AACxB,MAAM,YAAY,CAAC,cAAc,CAAC;AAClC,MAAM,cAAA,GAAiB,SAAS;AAChC,IAAI;AACJ,EAAE;;AAYF;AACA;AACA;AACA,EAAE,SAAS,mBAAmB,CAAC,YAAY,EAAiB;AAC5D,IAAI,kBAAkB,EAAE;AACxB,IAAI,iBAAiB,UAAU,CAAC,MAAM;AACtC,MAAM,IAAI,CAAC,SAAA,IAAa,UAAU,CAAC,IAAA,KAAS,CAAA,IAAK,kBAAkB,EAAE;AACrE,QAAQ,aAAA,GAAgB,0BAA0B;AAClD,QAAQ,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;AAC9B,MAAM;AACN,IAAI,CAAC,EAAE,WAAW,CAAC;AACnB,EAAE;;AAEF;AACA;AACA;AACA,EAAE,SAAS,wBAAwB,CAAC,YAAY,EAAiB;AAEjE,IAAI,iBAAiB,UAAU,CAAC,MAAM;AACtC,MAAM,IAAI,CAAC,SAAA,IAAa,kBAAkB,EAAE;AAC5C,QAAQ,aAAA,GAAgB,8BAA8B;AACtD,QAAQ,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;AAC9B,MAAM;AACN,IAAI,CAAC,EAAE,gBAAgB,CAAC;AACxB,EAAE;;AAEF;AACA;AACA;AACA;AACA,EAAE,SAAS,aAAa,CAAC,MAAM,EAAgB;AAC/C,IAAI,kBAAkB,EAAE;AACxB,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;;AAEhC,IAAI,MAAM,YAAA,GAAeJ,uBAAkB,EAAE;AAC7C;AACA;AACA,IAAI,wBAAwB,CAAC,YAAA,GAAe,gBAAA,GAAmB,IAAI,CAAC;AACpE,EAAE;;AAEF;AACA;AACA;AACA;AACA,EAAE,SAAS,YAAY,CAAC,MAAM,EAAgB;AAC9C,IAAI,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AAChC,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;AAC/B,IAAI;;AAEJ,IAAI,IAAI,UAAU,CAAC,IAAA,KAAS,CAAC,EAAE;AAC/B,MAAM,MAAM,YAAA,GAAeA,uBAAkB,EAAE;AAC/C;AACA;AACA,MAAM,mBAAmB,CAAC,YAAA,GAAe,WAAA,GAAc,IAAI,CAAC;AAE5D,IAAI;AACJ,EAAE;;AAEF,EAAE,SAAS,eAAe,CAAC,YAAY,EAAgB;AACvD,IAAI,SAAA,GAAY,IAAI;AACpB,IAAI,UAAU,CAAC,KAAK,EAAE;;AAEtB,IAAI,aAAa,CAAC,OAAO,CAAC,WAAW,OAAO,EAAE,CAAC;;AAE/C,IAAIK,4BAAgB,CAAC,KAAK,EAAE,kBAAkB,CAAC;;AAE/C,IAAI,MAAM,QAAA,GAAWF,oBAAU,CAAC,IAAI,CAAC;;AAErC,IAAI,MAAM,EAAE,eAAe,EAAE,cAAA,EAAe,GAAI,QAAQ;AACxD;AACA,IAAI,IAAI,CAAC,cAAc,EAAE;AACzB,MAAM;AACN,IAAI;;AAEJ,IAAI,MAAM,UAAA,GAAa,QAAQ,CAAC,IAAI;AACpC,IAAI,IAAI,CAAC,UAAU,CAACG,oEAAiD,CAAC,EAAE;AACxE,MAAM,IAAI,CAAC,YAAY,CAACA,oEAAiD,EAAE,aAAa,CAAC;AACzF,IAAI;;AAEJ;AACA,IAAI,MAAM,aAAA,GAAgB,QAAQ,CAAC,MAAM;AACzC,IAAI,IAAI,CAAC,aAAA,IAAiB,aAAA,KAAkB,SAAS,EAAE;AACvD,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAEC,yBAAA,EAAgB,CAAC;AAC9C,IAAI;;AAEJ,IAAIC,iBAAK,CAAC,GAAG,CAAC,CAAC,qBAAqB,EAAE,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;;AAE9D,IAAI,MAAM,UAAA,GAAaN,4BAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAA,IAAS,KAAA,KAAU,IAAI,CAAC;;AAE/E,IAAI,IAAI,cAAA,GAAiB,CAAC;AAC1B,IAAI,UAAU,CAAC,OAAO,CAAC,aAAa;AACpC;AACA,MAAM,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE;AACnC,QAAQ,SAAS,CAAC,SAAS,CAAC,EAAE,IAAI,EAAEO,4BAAiB,EAAE,OAAO,EAAE,WAAA,EAAa,CAAC;AAC9E,QAAQ,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC;AACnC,QAAQC,sBAAA;AACR,UAAUF,iBAAK,CAAC,GAAG,CAAC,kDAAkD,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AAChH,MAAM;;AAEN,MAAM,MAAM,aAAA,GAAgBL,oBAAU,CAAC,SAAS,CAAC;AACjD,MAAM,MAAM,EAAE,SAAS,EAAE,oBAAoB,CAAC,EAAE,eAAe,EAAE,mBAAA,GAAsB,CAAA,EAAE,GAAI,aAAa;;AAE1G,MAAM,MAAM,4BAAA,GAA+B,mBAAA,IAAuB,YAAY;;AAE9E;AACA,MAAM,MAAM,2BAA2B,CAAC,eAAe,WAAW,IAAI,IAAI;AAC1E,MAAM,MAAM,2BAAA,GAA8B,oBAAoB,mBAAA,IAAuB,wBAAwB;;AAE7G,MAAM,IAAIO,sBAAW,EAAE;AACvB,QAAQ,MAAM,eAAA,GAAkB,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;AACvE,QAAQ,IAAI,CAAC,4BAA4B,EAAE;AAC3C,UAAUF,iBAAK,CAAC,GAAG,CAAC,0EAA0E,EAAE,eAAe,CAAC;AAChH,QAAQ,OAAO,IAAI,CAAC,2BAA2B,EAAE;AACjD,UAAUA,iBAAK,CAAC,GAAG,CAAC,2EAA2E,EAAE,eAAe,CAAC;AACjH,QAAQ;AACR,MAAM;;AAEN,MAAM,IAAI,CAAC,+BAA+B,CAAC,4BAA4B,EAAE;AACzE,QAAQG,iCAAuB,CAAC,IAAI,EAAE,SAAS,CAAC;AAChD,QAAQ,cAAc,EAAE;AACxB,MAAM;AACN,IAAI,CAAC,CAAC;;AAEN,IAAI,IAAI,cAAA,GAAiB,CAAC,EAAE;AAC5B,MAAM,IAAI,CAAC,YAAY,CAAC,kCAAkC,EAAE,cAAc,CAAC;AAC3E,IAAI;AACJ,EAAE;;AAEF,EAAE,aAAa,CAAC,IAAI;AACpB,IAAI,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,eAAe;AAC1C;AACA;AACA;AACA;AACA,MAAM;AACN,QAAQ,SAAA;AACR,QAAQ,WAAA,KAAgB,IAAA;AACxB,QAAQ,CAAC,CAACR,oBAAU,CAAC,WAAW,CAAC,CAAC,SAAA;AAClC,SAAS,uBAAuBS,qBAAA,IAAc,WAAW,CAAC,gBAAgB,EAAE;AAC5E,QAAQ;AACR,QAAQ;AACR,MAAM;;AAEN,MAAM,MAAM,QAAA,GAAWV,4BAAkB,CAAC,IAAI,CAAC;;AAE/C;AACA,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;AAC1C,QAAQ,aAAa,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;AACvD,MAAM;AACN,IAAI,CAAC,CAAC;AACN,GAAG;;AAEH,EAAE,aAAa,CAAC,IAAI;AACpB,IAAI,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa;AACtC,MAAM,IAAI,SAAS,EAAE;AACrB,QAAQ;AACR,MAAM;;AAEN,MAAM,YAAY,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;AAClD,IAAI,CAAC,CAAC;AACN,GAAG;;AAEH,EAAE,aAAa,CAAC,IAAI;AACpB,IAAI,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,yBAAyB;AACnE,MAAM,IAAI,qBAAA,KAA0B,IAAI,EAAE;AAC1C,QAAQ,kBAAA,GAAqB,IAAI;AACjC,QAAQ,mBAAmB,EAAE;;AAE7B,QAAQ,IAAI,UAAU,CAAC,IAAI,EAAE;AAC7B,UAAU,wBAAwB,EAAE;AACpC,QAAQ;AACR,MAAM;AACN,IAAI,CAAC,CAAC;AACN,GAAG;;AAEH;AACA,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE;AAClC,IAAI,mBAAmB,EAAE;AACzB,EAAE;;AAEF,EAAE,UAAU,CAAC,MAAM;AACnB,IAAI,IAAI,CAAC,SAAS,EAAE;AACpB,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAEO,4BAAiB,EAAE,OAAO,EAAE,mBAAA,EAAqB,CAAC;AAC/E,MAAM,aAAA,GAAgB,2BAA2B;AACjD,MAAM,IAAI,CAAC,GAAG,EAAE;AAChB,IAAI;AACJ,EAAE,CAAC,EAAE,YAAY,CAAC;;AAElB,EAAE,OAAO,IAAI;AACb;;AAEA,SAAS,cAAc,CAAC,OAAO,EAA0B;AACzD,EAAE,MAAM,IAAA,GAAOI,uBAAiB,CAAC,OAAO,CAAC;;AAEzC,EAAER,4BAAgB,CAACP,6BAAe,EAAE,EAAE,IAAI,CAAC;;AAE3C,EAAEY,0BAAeF,iBAAK,CAAC,GAAG,CAAC,wCAAwC,CAAC;;AAEpE,EAAE,OAAO,IAAI;AACb;;;;;"}
|
|
1
|
+
{"version":3,"file":"idleSpan.js","sources":["../../../src/tracing/idleSpan.ts"],"sourcesContent":["import { getClient, getCurrentScope } from '../currentScopes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '../semanticAttributes';\nimport type { DynamicSamplingContext } from '../types-hoist/envelope';\nimport type { Span } from '../types-hoist/span';\nimport type { StartSpanOptions } from '../types-hoist/startSpanOptions';\nimport { debug } from '../utils/debug-logger';\nimport { hasSpansEnabled } from '../utils/hasSpansEnabled';\nimport { shouldIgnoreSpan } from '../utils/should-ignore-span';\nimport { _setSpanForScope } from '../utils/spanOnScope';\nimport {\n getActiveSpan,\n getSpanDescendants,\n removeChildSpanFromSpan,\n spanTimeInputToSeconds,\n spanToJSON,\n} from '../utils/spanUtils';\nimport { timestampInSeconds } from '../utils/time';\nimport { freezeDscOnSpan, getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';\nimport { SentryNonRecordingSpan } from './sentryNonRecordingSpan';\nimport { SentrySpan } from './sentrySpan';\nimport { SPAN_STATUS_ERROR, SPAN_STATUS_OK } from './spanstatus';\nimport { startInactiveSpan } from './trace';\n\nexport const TRACING_DEFAULTS = {\n idleTimeout: 1_000,\n finalTimeout: 30_000,\n childSpanTimeout: 15_000,\n};\n\nconst FINISH_REASON_HEARTBEAT_FAILED = 'heartbeatFailed';\nconst FINISH_REASON_IDLE_TIMEOUT = 'idleTimeout';\nconst FINISH_REASON_FINAL_TIMEOUT = 'finalTimeout';\nconst FINISH_REASON_EXTERNAL_FINISH = 'externalFinish';\nconst FINISH_REASON_CANCELLED = 'cancelled';\n\n// unused\nconst FINISH_REASON_DOCUMENT_HIDDEN = 'documentHidden';\n\n// unused in this file, but used in BrowserTracing\nconst FINISH_REASON_INTERRUPTED = 'interactionInterrupted';\n\ntype IdleSpanFinishReason =\n | typeof FINISH_REASON_CANCELLED\n | typeof FINISH_REASON_DOCUMENT_HIDDEN\n | typeof FINISH_REASON_EXTERNAL_FINISH\n | typeof FINISH_REASON_FINAL_TIMEOUT\n | typeof FINISH_REASON_HEARTBEAT_FAILED\n | typeof FINISH_REASON_IDLE_TIMEOUT\n | typeof FINISH_REASON_INTERRUPTED;\n\ninterface IdleSpanOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n */\n idleTimeout: number;\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n */\n finalTimeout: number;\n /**\n * The max. time a child span may run.\n * If the time since the last span was started exceeds this time, the idle span will finish.\n */\n childSpanTimeout?: number;\n /**\n * When set to `true`, will disable the idle timeout and child timeout\n * until the `idleSpanEnableAutoFinish` hook is emitted for the idle span.\n * The final timeout mechanism will not be affected by this option,\n * meaning the idle span will definitely be finished when the final timeout is\n * reached, no matter what this option is configured to.\n *\n * Defaults to `false`.\n */\n disableAutoFinish?: boolean;\n\n /** Allows to configure a hook that is called when the idle span is ended, before it is processed. */\n beforeSpanEnd?: (span: Span) => void;\n\n /**\n * If set to `true`, the idle span will be trimmed to the latest span end timestamp of its children.\n *\n * @default `true`.\n */\n trimIdleSpanEndTimestamp?: boolean;\n}\n\n/**\n * An idle span is a span that automatically finishes. It does this by tracking child spans as activities.\n * An idle span is always the active span.\n */\nexport function startIdleSpan(startSpanOptions: StartSpanOptions, options: Partial<IdleSpanOptions> = {}): Span {\n // Activities store a list of active spans\n const activities = new Map<string, boolean>();\n\n // We should not use heartbeat if we finished a span\n let _finished = false;\n\n // Timer that tracks idleTimeout\n let _idleTimeoutID: ReturnType<typeof setTimeout> | undefined;\n\n // Timer that tracks maxSpanTime for child spans\n let _childSpanTimeoutID: ReturnType<typeof setTimeout> | undefined;\n\n // The reason why the span was finished\n let _finishReason: IdleSpanFinishReason = FINISH_REASON_EXTERNAL_FINISH;\n\n let _autoFinishAllowed: boolean = !options.disableAutoFinish;\n\n const _cleanupHooks: (() => void)[] = [];\n\n const {\n idleTimeout = TRACING_DEFAULTS.idleTimeout,\n finalTimeout = TRACING_DEFAULTS.finalTimeout,\n childSpanTimeout = TRACING_DEFAULTS.childSpanTimeout,\n beforeSpanEnd,\n trimIdleSpanEndTimestamp = true,\n } = options;\n\n const client = getClient();\n\n if (!client || !hasSpansEnabled()) {\n const span = new SentryNonRecordingSpan();\n\n const dsc = {\n sample_rate: '0',\n sampled: 'false',\n ...getDynamicSamplingContextFromSpan(span),\n } satisfies Partial<DynamicSamplingContext>;\n freezeDscOnSpan(span, dsc);\n\n return span;\n }\n\n const scope = getCurrentScope();\n const previousActiveSpan = getActiveSpan();\n const span = _startIdleSpan(startSpanOptions);\n\n // We patch span.end to ensure we can run some things before the span is ended\n // eslint-disable-next-line @typescript-eslint/unbound-method\n span.end = new Proxy(span.end, {\n apply(target, thisArg, args: Parameters<Span['end']>) {\n if (beforeSpanEnd) {\n beforeSpanEnd(span);\n }\n\n // If the span is non-recording, nothing more to do here...\n // This is the case if tracing is enabled but this specific span was not sampled\n if (thisArg instanceof SentryNonRecordingSpan) {\n return;\n }\n\n // Just ensuring that this keeps working, even if we ever have more arguments here\n const [definedEndTimestamp, ...rest] = args;\n const timestamp = definedEndTimestamp || timestampInSeconds();\n const spanEndTimestamp = spanTimeInputToSeconds(timestamp);\n\n // Ensure we end with the last span timestamp, if possible\n const spans = getSpanDescendants(span).filter(child => child !== span);\n\n const spanJson = spanToJSON(span);\n\n // If we have no spans, we just end, nothing else to do here\n // Likewise, if users explicitly ended the span, we simply end the span without timestamp adjustment\n if (!spans.length || !trimIdleSpanEndTimestamp) {\n onIdleSpanEnded(spanEndTimestamp);\n return Reflect.apply(target, thisArg, [spanEndTimestamp, ...rest]);\n }\n\n const ignoreSpans = client.getOptions().ignoreSpans;\n\n const latestSpanEndTimestamp = spans?.reduce((acc: number | undefined, current) => {\n const currentSpanJson = spanToJSON(current);\n if (!currentSpanJson.timestamp) {\n return acc;\n }\n // Ignored spans will get dropped later (in the client) but since we already adjust\n // the idle span end timestamp here, we can already take to-be-ignored spans out of\n // the calculation here.\n if (\n ignoreSpans &&\n shouldIgnoreSpan(\n { description: currentSpanJson.description, op: currentSpanJson.op, attributes: currentSpanJson.data },\n ignoreSpans,\n )\n ) {\n return acc;\n }\n return acc ? Math.max(acc, currentSpanJson.timestamp) : currentSpanJson.timestamp;\n }, undefined);\n\n // In reality this should always exist here, but type-wise it may be undefined...\n const spanStartTimestamp = spanJson.start_timestamp;\n\n // The final endTimestamp should:\n // * Never be before the span start timestamp\n // * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp\n // * Otherwise be the passed end timestamp\n // Final timestamp can never be after finalTimeout\n const endTimestamp = Math.min(\n spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity,\n Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)),\n );\n\n onIdleSpanEnded(endTimestamp);\n return Reflect.apply(target, thisArg, [endTimestamp, ...rest]);\n },\n });\n\n /**\n * Cancels the existing idle timeout, if there is one.\n */\n function _cancelIdleTimeout(): void {\n if (_idleTimeoutID) {\n clearTimeout(_idleTimeoutID);\n _idleTimeoutID = undefined;\n }\n }\n\n /**\n * Cancels the existing child span timeout, if there is one.\n */\n function _cancelChildSpanTimeout(): void {\n if (_childSpanTimeoutID) {\n clearTimeout(_childSpanTimeoutID);\n _childSpanTimeoutID = undefined;\n }\n }\n\n /**\n * Restarts idle timeout, if there is no running idle timeout it will start one.\n */\n function _restartIdleTimeout(endTimestamp?: number): void {\n _cancelIdleTimeout();\n _idleTimeoutID = setTimeout(() => {\n if (!_finished && activities.size === 0 && _autoFinishAllowed) {\n _finishReason = FINISH_REASON_IDLE_TIMEOUT;\n span.end(endTimestamp);\n }\n }, idleTimeout);\n }\n\n /**\n * Restarts child span timeout, if there is none running it will start one.\n */\n function _restartChildSpanTimeout(endTimestamp?: number): void {\n _cancelChildSpanTimeout();\n _idleTimeoutID = setTimeout(() => {\n if (!_finished && _autoFinishAllowed) {\n _finishReason = FINISH_REASON_HEARTBEAT_FAILED;\n span.end(endTimestamp);\n }\n }, childSpanTimeout);\n }\n\n /**\n * Start tracking a specific activity.\n * @param spanId The span id that represents the activity\n */\n function _pushActivity(spanId: string): void {\n _cancelIdleTimeout();\n activities.set(spanId, true);\n\n const endTimestamp = timestampInSeconds();\n // We need to add the timeout here to have the real endtimestamp of the idle span\n // Remember timestampInSeconds is in seconds, timeout is in ms\n _restartChildSpanTimeout(endTimestamp + childSpanTimeout / 1000);\n }\n\n /**\n * Remove an activity from usage\n * @param spanId The span id that represents the activity\n */\n function _popActivity(spanId: string): void {\n if (activities.has(spanId)) {\n activities.delete(spanId);\n }\n\n if (activities.size === 0) {\n const endTimestamp = timestampInSeconds();\n // We need to add the timeout here to have the real endtimestamp of the idle span\n // Remember timestampInSeconds is in seconds, timeout is in ms\n _restartIdleTimeout(endTimestamp + idleTimeout / 1000);\n _cancelChildSpanTimeout();\n }\n }\n\n function onIdleSpanEnded(endTimestamp: number): void {\n _finished = true;\n activities.clear();\n\n _cleanupHooks.forEach(cleanup => cleanup());\n\n _setSpanForScope(scope, previousActiveSpan);\n\n const spanJSON = spanToJSON(span);\n\n const { start_timestamp: startTimestamp } = spanJSON;\n // This should never happen, but to make TS happy...\n if (!startTimestamp) {\n return;\n }\n\n const attributes = spanJSON.data;\n if (!attributes[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, _finishReason);\n }\n\n // Set span status to 'ok' if it hasn't been explicitly set to an error status\n const currentStatus = spanJSON.status;\n if (!currentStatus || currentStatus === 'unknown') {\n span.setStatus({ code: SPAN_STATUS_OK });\n }\n\n debug.log(`[Tracing] Idle span \"${spanJSON.op}\" finished`);\n\n const childSpans = getSpanDescendants(span).filter(child => child !== span);\n\n let discardedSpans = 0;\n childSpans.forEach(childSpan => {\n // We cancel all pending spans with status \"cancelled\" to indicate the idle span was finished early\n if (childSpan.isRecording()) {\n childSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n childSpan.end(endTimestamp);\n DEBUG_BUILD &&\n debug.log('[Tracing] Cancelling span since span ended early', JSON.stringify(childSpan, undefined, 2));\n }\n\n const childSpanJSON = spanToJSON(childSpan);\n const { timestamp: childEndTimestamp = 0, start_timestamp: childStartTimestamp = 0 } = childSpanJSON;\n\n const spanStartedBeforeIdleSpanEnd = childStartTimestamp <= endTimestamp;\n\n // Add a delta with idle timeout so that we prevent false positives\n const timeoutWithMarginOfError = (finalTimeout + idleTimeout) / 1000;\n const spanEndedBeforeFinalTimeout = childEndTimestamp - childStartTimestamp <= timeoutWithMarginOfError;\n\n if (DEBUG_BUILD) {\n const stringifiedSpan = JSON.stringify(childSpan, undefined, 2);\n if (!spanStartedBeforeIdleSpanEnd) {\n debug.log('[Tracing] Discarding span since it happened after idle span was finished', stringifiedSpan);\n } else if (!spanEndedBeforeFinalTimeout) {\n debug.log('[Tracing] Discarding span since it finished after idle span final timeout', stringifiedSpan);\n }\n }\n\n if (!spanEndedBeforeFinalTimeout || !spanStartedBeforeIdleSpanEnd) {\n removeChildSpanFromSpan(span, childSpan);\n discardedSpans++;\n }\n });\n\n if (discardedSpans > 0) {\n span.setAttribute('sentry.idle_span_discarded_spans', discardedSpans);\n }\n }\n\n _cleanupHooks.push(\n client.on('spanStart', startedSpan => {\n // If we already finished the idle span,\n // or if this is the idle span itself being started,\n // or if the started span has already been closed,\n // we don't care about it for activity\n if (\n _finished ||\n startedSpan === span ||\n !!spanToJSON(startedSpan).timestamp ||\n (startedSpan instanceof SentrySpan && startedSpan.isStandaloneSpan())\n ) {\n return;\n }\n\n const allSpans = getSpanDescendants(span);\n\n // If the span that was just started is a child of the idle span, we should track it\n if (allSpans.includes(startedSpan)) {\n _pushActivity(startedSpan.spanContext().spanId);\n }\n }),\n );\n\n _cleanupHooks.push(\n client.on('spanEnd', endedSpan => {\n if (_finished) {\n return;\n }\n\n _popActivity(endedSpan.spanContext().spanId);\n }),\n );\n\n _cleanupHooks.push(\n client.on('idleSpanEnableAutoFinish', spanToAllowAutoFinish => {\n if (spanToAllowAutoFinish === span) {\n _autoFinishAllowed = true;\n _restartIdleTimeout();\n\n if (activities.size) {\n _restartChildSpanTimeout();\n }\n }\n }),\n );\n\n // We only start the initial idle timeout if we are not delaying the auto finish\n if (!options.disableAutoFinish) {\n _restartIdleTimeout();\n }\n\n setTimeout(() => {\n if (!_finished) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });\n _finishReason = FINISH_REASON_FINAL_TIMEOUT;\n span.end();\n }\n }, finalTimeout);\n\n return span;\n}\n\nfunction _startIdleSpan(options: StartSpanOptions): Span {\n const span = startInactiveSpan(options);\n\n _setSpanForScope(getCurrentScope(), span);\n\n DEBUG_BUILD && debug.log('[Tracing] Started span is an idle span');\n\n return span;\n}\n"],"names":["getClient","hasSpansEnabled","SentryNonRecordingSpan","getDynamicSamplingContextFromSpan","freezeDscOnSpan","getCurrentScope","getActiveSpan","timestampInSeconds","spanTimeInputToSeconds","getSpanDescendants","spanToJSON","shouldIgnoreSpan","_setSpanForScope","SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON","SPAN_STATUS_OK","debug","SPAN_STATUS_ERROR","DEBUG_BUILD","removeChildSpanFromSpan","SentrySpan","startInactiveSpan"],"mappings":"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"}
|
|
@@ -9,6 +9,8 @@ const utils = require('../ai/utils.js');
|
|
|
9
9
|
const constants = require('./constants.js');
|
|
10
10
|
const utils$1 = require('./utils.js');
|
|
11
11
|
|
|
12
|
+
/* eslint-disable max-lines */
|
|
13
|
+
|
|
12
14
|
/**
|
|
13
15
|
* Creates a Sentry callback handler for LangChain
|
|
14
16
|
* Returns a plain object that LangChain will call via duck-typing
|
|
@@ -85,6 +87,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
85
87
|
name: `${operationName} ${modelName}`,
|
|
86
88
|
op: 'gen_ai.chat',
|
|
87
89
|
attributes: {
|
|
90
|
+
...utils$1.getAgentNameFromMetadata(metadata),
|
|
88
91
|
...attributes,
|
|
89
92
|
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',
|
|
90
93
|
},
|
|
@@ -102,7 +105,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
102
105
|
messages,
|
|
103
106
|
runId,
|
|
104
107
|
_parentRunId,
|
|
105
|
-
|
|
108
|
+
extraParams,
|
|
106
109
|
tags,
|
|
107
110
|
metadata,
|
|
108
111
|
_runName,
|
|
@@ -116,6 +119,12 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
116
119
|
invocationParams,
|
|
117
120
|
metadata,
|
|
118
121
|
);
|
|
122
|
+
|
|
123
|
+
const toolDefsJson = utils$1.extractToolDefinitions(extraParams);
|
|
124
|
+
if (toolDefsJson) {
|
|
125
|
+
attributes[genAiAttributes.GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = toolDefsJson;
|
|
126
|
+
}
|
|
127
|
+
|
|
119
128
|
const modelName = attributes[genAiAttributes.GEN_AI_REQUEST_MODEL_ATTRIBUTE];
|
|
120
129
|
const operationName = attributes[genAiAttributes.GEN_AI_OPERATION_NAME_ATTRIBUTE];
|
|
121
130
|
|
|
@@ -124,6 +133,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
124
133
|
name: `${operationName} ${modelName}`,
|
|
125
134
|
op: 'gen_ai.chat',
|
|
126
135
|
attributes: {
|
|
136
|
+
...utils$1.getAgentNameFromMetadata(metadata),
|
|
127
137
|
...attributes,
|
|
128
138
|
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',
|
|
129
139
|
},
|
|
@@ -176,17 +186,23 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
176
186
|
runId,
|
|
177
187
|
_parentRunId,
|
|
178
188
|
_tags,
|
|
179
|
-
|
|
189
|
+
metadata,
|
|
180
190
|
_runType,
|
|
181
191
|
runName,
|
|
182
192
|
) {
|
|
193
|
+
// Skip chain spans when inside an agent context (createReactAgent).
|
|
194
|
+
// The agent already creates an invoke_agent span; internal chain steps
|
|
195
|
+
// (ChannelWrite, Branch, prompt, etc.) are noise.
|
|
196
|
+
if (metadata?.__sentry_langgraph__) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
183
200
|
const chainName = runName || chain.name || 'unknown_chain';
|
|
184
201
|
const attributes = {
|
|
185
202
|
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',
|
|
186
203
|
'langchain.chain.name': chainName,
|
|
187
204
|
};
|
|
188
205
|
|
|
189
|
-
// Add inputs if recordInputs is enabled
|
|
190
206
|
if (recordInputs) {
|
|
191
207
|
attributes['langchain.chain.inputs'] = JSON.stringify(inputs);
|
|
192
208
|
}
|
|
@@ -238,14 +254,30 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
238
254
|
},
|
|
239
255
|
|
|
240
256
|
// Tool Start Handler
|
|
241
|
-
handleToolStart(
|
|
242
|
-
|
|
257
|
+
handleToolStart(
|
|
258
|
+
tool,
|
|
259
|
+
input,
|
|
260
|
+
runId,
|
|
261
|
+
_parentRunId,
|
|
262
|
+
_tags,
|
|
263
|
+
metadata,
|
|
264
|
+
runName,
|
|
265
|
+
) {
|
|
266
|
+
// Skip tool spans when inside an agent context (createReactAgent).
|
|
267
|
+
// Tool spans are created by wrapToolsWithSpans with richer attributes.
|
|
268
|
+
if (metadata?.__sentry_langgraph__) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// runName is set to tool.name by LangChain's StructuredTool.call()
|
|
273
|
+
const toolName = runName || tool.name || 'unknown_tool';
|
|
243
274
|
const attributes = {
|
|
275
|
+
...utils$1.getAgentNameFromMetadata(metadata),
|
|
244
276
|
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: constants.LANGCHAIN_ORIGIN,
|
|
277
|
+
[genAiAttributes.GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'execute_tool',
|
|
245
278
|
[genAiAttributes.GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,
|
|
246
279
|
};
|
|
247
280
|
|
|
248
|
-
// Add input if recordInputs is enabled
|
|
249
281
|
if (recordInputs) {
|
|
250
282
|
attributes[genAiAttributes.GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;
|
|
251
283
|
}
|
|
@@ -270,10 +302,13 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
270
302
|
handleToolEnd(output, runId) {
|
|
271
303
|
const span = spanMap.get(runId);
|
|
272
304
|
if (span?.isRecording()) {
|
|
273
|
-
// Add output if recordOutputs is enabled
|
|
274
305
|
if (recordOutputs) {
|
|
306
|
+
// LangChain tools may return ToolMessage objects — extract the content
|
|
307
|
+
const outputObj = output ;
|
|
308
|
+
const content =
|
|
309
|
+
outputObj && typeof outputObj === 'object' && 'content' in outputObj ? outputObj.content : output;
|
|
275
310
|
span.setAttributes({
|
|
276
|
-
[genAiAttributes.GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: JSON.stringify(
|
|
311
|
+
[genAiAttributes.GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: typeof content === 'string' ? content : JSON.stringify(content),
|
|
277
312
|
});
|
|
278
313
|
}
|
|
279
314
|
exitSpan(runId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/langchain/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_TOOL_INPUT_ATTRIBUTE,\n GEN_AI_TOOL_NAME_ATTRIBUTE,\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { resolveAIRecordingOptions, shouldEnableTruncation } from '../ai/utils';\nimport { LANGCHAIN_ORIGIN } from './constants';\nimport type {\n LangChainCallbackHandler,\n LangChainLLMResult,\n LangChainMessage,\n LangChainOptions,\n LangChainSerialized,\n} from './types';\nimport {\n extractChatModelRequestAttributes,\n extractLLMRequestAttributes,\n extractLlmResponseAttributes,\n getInvocationParams,\n} from './utils';\n\n/**\n * Creates a Sentry callback handler for LangChain\n * Returns a plain object that LangChain will call via duck-typing\n *\n * This is a stateful handler that tracks spans across multiple LangChain executions.\n */\nexport function createLangChainCallbackHandler(options: LangChainOptions = {}): LangChainCallbackHandler {\n const { recordInputs, recordOutputs } = resolveAIRecordingOptions(options);\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n\n // Internal state - single instance tracks all spans\n const spanMap = new Map<string, Span>();\n\n /**\n * Exit a span and clean up\n */\n const exitSpan = (runId: string): void => {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.end();\n spanMap.delete(runId);\n }\n };\n\n /**\n * Handler for LLM Start\n * This handler will be called by LangChain's callback handler when an LLM event is detected.\n */\n const handler: LangChainCallbackHandler = {\n // Required LangChain BaseCallbackHandler properties\n lc_serializable: false,\n lc_namespace: ['langchain_core', 'callbacks', 'sentry'],\n lc_secrets: undefined,\n lc_attributes: undefined,\n lc_aliases: undefined,\n lc_serializable_keys: undefined,\n lc_id: ['langchain_core', 'callbacks', 'sentry'],\n lc_kwargs: {},\n name: 'SentryCallbackHandler',\n\n // BaseCallbackHandlerInput boolean flags\n ignoreLLM: false,\n ignoreChain: false,\n ignoreAgent: false,\n ignoreRetriever: false,\n ignoreCustomEvent: false,\n raiseError: false,\n awaitHandlers: true,\n\n handleLLMStart(\n llm: unknown,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractLLMRequestAttributes(\n llm as LangChainSerialized,\n prompts,\n recordInputs,\n enableTruncation,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chat Model Start Handler\n handleChatModelStart(\n llm: unknown,\n messages: unknown,\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractChatModelRequestAttributes(\n llm as LangChainSerialized,\n messages as LangChainMessage[][],\n recordInputs,\n enableTruncation,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // LLM End Handler - note: handleLLMEnd with capital LLM (used by both LLMs and chat models!)\n handleLLMEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>,\n ) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n const attributes = extractLlmResponseAttributes(output as LangChainLLMResult, recordOutputs);\n if (attributes) {\n span.setAttributes(attributes);\n }\n exitSpan(runId);\n }\n },\n\n // LLM Error Handler - note: handleLLMError with capital LLM\n handleLLMError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.llm_error_handler`,\n },\n });\n },\n\n // Chain Start Handler\n handleChainStart(\n chain: { name?: string },\n inputs: Record<string, unknown>,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _metadata?: Record<string, unknown>,\n _runType?: string,\n runName?: string,\n ) {\n const chainName = runName || chain.name || 'unknown_chain';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',\n 'langchain.chain.name': chainName,\n };\n\n // Add inputs if recordInputs is enabled\n if (recordInputs) {\n attributes['langchain.chain.inputs'] = JSON.stringify(inputs);\n }\n\n startSpanManual(\n {\n name: `chain ${chainName}`,\n op: 'gen_ai.invoke_agent',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chain End Handler\n handleChainEnd(outputs: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add outputs if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'langchain.chain.outputs': JSON.stringify(outputs),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Chain Error Handler\n handleChainError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.chain_error_handler`,\n },\n });\n },\n\n // Tool Start Handler\n handleToolStart(tool: { name?: string }, input: string, runId: string, _parentRunId?: string) {\n const toolName = tool.name || 'unknown_tool';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,\n };\n\n // Add input if recordInputs is enabled\n if (recordInputs) {\n attributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;\n }\n\n startSpanManual(\n {\n name: `execute_tool ${toolName}`,\n op: 'gen_ai.execute_tool',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.execute_tool',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Tool End Handler\n handleToolEnd(output: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add output if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n [GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: JSON.stringify(output),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Tool Error Handler\n handleToolError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.tool_error_handler`,\n },\n });\n },\n\n // LangChain BaseCallbackHandler required methods\n copy() {\n return handler;\n },\n\n toJSON() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n\n toJSONNotImplemented() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n };\n\n return handler;\n}\n\nexport { instrumentLangChainEmbeddings } from './embeddings';\n"],"names":["resolveAIRecordingOptions","shouldEnableTruncation","getInvocationParams","extractLLMRequestAttributes","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_OP","extractChatModelRequestAttributes","extractLlmResponseAttributes","SPAN_STATUS_ERROR","captureException","LANGCHAIN_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_TOOL_NAME_ATTRIBUTE","GEN_AI_TOOL_INPUT_ATTRIBUTE","GEN_AI_TOOL_OUTPUT_ATTRIBUTE"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/langchain/index.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_TOOL_INPUT_ATTRIBUTE,\n GEN_AI_TOOL_NAME_ATTRIBUTE,\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { resolveAIRecordingOptions, shouldEnableTruncation } from '../ai/utils';\nimport { LANGCHAIN_ORIGIN } from './constants';\nimport type {\n LangChainCallbackHandler,\n LangChainLLMResult,\n LangChainMessage,\n LangChainOptions,\n LangChainSerialized,\n} from './types';\nimport {\n extractChatModelRequestAttributes,\n extractLLMRequestAttributes,\n extractLlmResponseAttributes,\n extractToolDefinitions,\n getAgentNameFromMetadata,\n getInvocationParams,\n} from './utils';\n\n/**\n * Creates a Sentry callback handler for LangChain\n * Returns a plain object that LangChain will call via duck-typing\n *\n * This is a stateful handler that tracks spans across multiple LangChain executions.\n */\nexport function createLangChainCallbackHandler(options: LangChainOptions = {}): LangChainCallbackHandler {\n const { recordInputs, recordOutputs } = resolveAIRecordingOptions(options);\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n\n // Internal state - single instance tracks all spans\n const spanMap = new Map<string, Span>();\n\n /**\n * Exit a span and clean up\n */\n const exitSpan = (runId: string): void => {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.end();\n spanMap.delete(runId);\n }\n };\n\n /**\n * Handler for LLM Start\n * This handler will be called by LangChain's callback handler when an LLM event is detected.\n */\n const handler: LangChainCallbackHandler = {\n // Required LangChain BaseCallbackHandler properties\n lc_serializable: false,\n lc_namespace: ['langchain_core', 'callbacks', 'sentry'],\n lc_secrets: undefined,\n lc_attributes: undefined,\n lc_aliases: undefined,\n lc_serializable_keys: undefined,\n lc_id: ['langchain_core', 'callbacks', 'sentry'],\n lc_kwargs: {},\n name: 'SentryCallbackHandler',\n\n // BaseCallbackHandlerInput boolean flags\n ignoreLLM: false,\n ignoreChain: false,\n ignoreAgent: false,\n ignoreRetriever: false,\n ignoreCustomEvent: false,\n raiseError: false,\n awaitHandlers: true,\n\n handleLLMStart(\n llm: unknown,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractLLMRequestAttributes(\n llm as LangChainSerialized,\n prompts,\n recordInputs,\n enableTruncation,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...getAgentNameFromMetadata(metadata),\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chat Model Start Handler\n handleChatModelStart(\n llm: unknown,\n messages: unknown,\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractChatModelRequestAttributes(\n llm as LangChainSerialized,\n messages as LangChainMessage[][],\n recordInputs,\n enableTruncation,\n invocationParams,\n metadata,\n );\n\n const toolDefsJson = extractToolDefinitions(extraParams);\n if (toolDefsJson) {\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = toolDefsJson;\n }\n\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...getAgentNameFromMetadata(metadata),\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // LLM End Handler - note: handleLLMEnd with capital LLM (used by both LLMs and chat models!)\n handleLLMEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>,\n ) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n const attributes = extractLlmResponseAttributes(output as LangChainLLMResult, recordOutputs);\n if (attributes) {\n span.setAttributes(attributes);\n }\n exitSpan(runId);\n }\n },\n\n // LLM Error Handler - note: handleLLMError with capital LLM\n handleLLMError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.llm_error_handler`,\n },\n });\n },\n\n // Chain Start Handler\n handleChainStart(\n chain: { name?: string },\n inputs: Record<string, unknown>,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n metadata?: Record<string, unknown>,\n _runType?: string,\n runName?: string,\n ) {\n // Skip chain spans when inside an agent context (createReactAgent).\n // The agent already creates an invoke_agent span; internal chain steps\n // (ChannelWrite, Branch, prompt, etc.) are noise.\n if (metadata?.__sentry_langgraph__) {\n return;\n }\n\n const chainName = runName || chain.name || 'unknown_chain';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',\n 'langchain.chain.name': chainName,\n };\n\n if (recordInputs) {\n attributes['langchain.chain.inputs'] = JSON.stringify(inputs);\n }\n\n startSpanManual(\n {\n name: `chain ${chainName}`,\n op: 'gen_ai.invoke_agent',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chain End Handler\n handleChainEnd(outputs: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add outputs if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'langchain.chain.outputs': JSON.stringify(outputs),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Chain Error Handler\n handleChainError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.chain_error_handler`,\n },\n });\n },\n\n // Tool Start Handler\n handleToolStart(\n tool: { name?: string },\n input: string,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n ) {\n // Skip tool spans when inside an agent context (createReactAgent).\n // Tool spans are created by wrapToolsWithSpans with richer attributes.\n if (metadata?.__sentry_langgraph__) {\n return;\n }\n\n // runName is set to tool.name by LangChain's StructuredTool.call()\n const toolName = runName || tool.name || 'unknown_tool';\n const attributes: Record<string, SpanAttributeValue> = {\n ...getAgentNameFromMetadata(metadata),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'execute_tool',\n [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,\n };\n\n if (recordInputs) {\n attributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;\n }\n\n startSpanManual(\n {\n name: `execute_tool ${toolName}`,\n op: 'gen_ai.execute_tool',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.execute_tool',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Tool End Handler\n handleToolEnd(output: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n if (recordOutputs) {\n // LangChain tools may return ToolMessage objects — extract the content\n const outputObj = output as Record<string, unknown> | undefined;\n const content =\n outputObj && typeof outputObj === 'object' && 'content' in outputObj ? outputObj.content : output;\n span.setAttributes({\n [GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: typeof content === 'string' ? content : JSON.stringify(content),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Tool Error Handler\n handleToolError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.tool_error_handler`,\n },\n });\n },\n\n // LangChain BaseCallbackHandler required methods\n copy() {\n return handler;\n },\n\n toJSON() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n\n toJSONNotImplemented() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n };\n\n return handler;\n}\n\nexport { instrumentLangChainEmbeddings } from './embeddings';\n"],"names":["resolveAIRecordingOptions","shouldEnableTruncation","getInvocationParams","extractLLMRequestAttributes","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","startSpanManual","getAgentNameFromMetadata","SEMANTIC_ATTRIBUTE_SENTRY_OP","extractChatModelRequestAttributes","extractToolDefinitions","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","extractLlmResponseAttributes","SPAN_STATUS_ERROR","captureException","LANGCHAIN_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_TOOL_NAME_ATTRIBUTE","GEN_AI_TOOL_INPUT_ATTRIBUTE","GEN_AI_TOOL_OUTPUT_ATTRIBUTE"],"mappings":"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"}
|
|
@@ -326,22 +326,28 @@ function extractChatModelRequestAttributes(
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
/**
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
* them as a JSON array on `gen_ai.response.tool_calls` for downstream consumers.
|
|
329
|
+
* Extracts tool calls from generations and records them on the span attributes.
|
|
330
|
+
* Prefers message.tool_calls (LangChain's normalized format). Falls back to
|
|
331
|
+
* scanning message.content for Anthropic-style tool_use items in older versions
|
|
332
|
+
* where tool_calls may not be populated.
|
|
334
333
|
*/
|
|
335
334
|
function addToolCallsAttributes(generations, attrs) {
|
|
336
335
|
const toolCalls = [];
|
|
337
336
|
const flatGenerations = generations.flat();
|
|
338
337
|
|
|
339
338
|
for (const gen of flatGenerations) {
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
339
|
+
const msg = gen.message ;
|
|
340
|
+
const msgToolCalls = msg?.tool_calls ;
|
|
341
|
+
if (Array.isArray(msgToolCalls) && msgToolCalls.length > 0) {
|
|
342
|
+
toolCalls.push(...msgToolCalls);
|
|
343
|
+
} else {
|
|
344
|
+
// Fallback for older LangChain versions: scan message.content for Anthropic-style tool_use
|
|
345
|
+
const content = gen.message?.content;
|
|
346
|
+
if (Array.isArray(content)) {
|
|
347
|
+
for (const item of content) {
|
|
348
|
+
const t = item ;
|
|
349
|
+
if (t.type === 'tool_use') toolCalls.push(t);
|
|
350
|
+
}
|
|
345
351
|
}
|
|
346
352
|
}
|
|
347
353
|
}
|
|
@@ -476,9 +482,37 @@ function extractLlmResponseAttributes(
|
|
|
476
482
|
return attrs;
|
|
477
483
|
}
|
|
478
484
|
|
|
485
|
+
function getAgentNameFromMetadata(metadata) {
|
|
486
|
+
const attrs = {};
|
|
487
|
+
// lc_agent_name is injected by instrumentCompiledGraphInvoke (langgraph integration)
|
|
488
|
+
const agentName = metadata?.lc_agent_name;
|
|
489
|
+
if (typeof agentName === 'string') {
|
|
490
|
+
attrs[genAiAttributes.GEN_AI_AGENT_NAME_ATTRIBUTE] = agentName;
|
|
491
|
+
}
|
|
492
|
+
return attrs;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function extractToolDefinitions(extraParams) {
|
|
496
|
+
const tools =
|
|
497
|
+
(extraParams?.invocation_params )?.tools ??
|
|
498
|
+
(extraParams?.options )?.tools;
|
|
499
|
+
if (!Array.isArray(tools) || tools.length === 0) return undefined;
|
|
500
|
+
const toolDefs = tools.map((tool) => {
|
|
501
|
+
const fn = tool.function ;
|
|
502
|
+
return {
|
|
503
|
+
type: 'function',
|
|
504
|
+
name: tool.name ?? fn?.name ?? '',
|
|
505
|
+
description: tool.description ?? fn?.description,
|
|
506
|
+
};
|
|
507
|
+
});
|
|
508
|
+
return JSON.stringify(toolDefs);
|
|
509
|
+
}
|
|
510
|
+
|
|
479
511
|
exports.extractChatModelRequestAttributes = extractChatModelRequestAttributes;
|
|
480
512
|
exports.extractLLMRequestAttributes = extractLLMRequestAttributes;
|
|
481
513
|
exports.extractLlmResponseAttributes = extractLlmResponseAttributes;
|
|
514
|
+
exports.extractToolDefinitions = extractToolDefinitions;
|
|
515
|
+
exports.getAgentNameFromMetadata = getAgentNameFromMetadata;
|
|
482
516
|
exports.getInvocationParams = getInvocationParams;
|
|
483
517
|
exports.normalizeLangChainMessages = normalizeLangChainMessages;
|
|
484
518
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../src/tracing/langchain/utils.ts"],"sourcesContent":["import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport type { SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_STREAM_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { isContentMedia, stripInlineMediaFromSingleMessage } from '../ai/mediaStripping';\nimport { extractSystemInstructions, getJsonString, getTruncatedJsonString } from '../ai/utils';\nimport { LANGCHAIN_ORIGIN, ROLE_MAP } from './constants';\nimport type { LangChainLLMResult, LangChainMessage, LangChainSerialized } from './types';\n\n/**\n * Assigns an attribute only when the value is neither `undefined` nor `null`.\n *\n * We keep this tiny helper because call sites are repetitive and easy to miswrite.\n * It also preserves falsy-but-valid values like `0` and `\"\"`.\n */\nconst setIfDefined = (target: Record<string, SpanAttributeValue>, key: string, value: unknown): void => {\n if (value != null) target[key] = value as SpanAttributeValue;\n};\n\n/**\n * Like `setIfDefined`, but converts the value with `Number()` and skips only when the\n * result is `NaN`. This ensures numeric 0 makes it through (unlike truthy checks).\n */\nconst setNumberIfDefined = (target: Record<string, SpanAttributeValue>, key: string, value: unknown): void => {\n const n = Number(value);\n if (!Number.isNaN(n)) target[key] = n;\n};\n\n/**\n * Converts a value to a string. Avoids double-quoted JSON strings where a plain\n * string is desired, but still handles objects/arrays safely.\n */\nfunction asString(v: unknown): string {\n if (typeof v === 'string') return v;\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n\n/**\n * Converts message content to a string, stripping inline media (base64 images, audio, etc.)\n * from multimodal content before stringification so downstream media stripping can't miss it.\n *\n * @example\n * // String content passes through unchanged:\n * normalizeContent(\"Hello\") // => \"Hello\"\n *\n * // Multimodal array content — media is replaced with \"[Blob substitute]\" before JSON.stringify:\n * normalizeContent([\n * { type: \"text\", text: \"What color?\" },\n * { type: \"image_url\", image_url: { url: \"data:image/png;base64,iVBOR...\" } }\n * ])\n * // => '[{\"type\":\"text\",\"text\":\"What color?\"},{\"type\":\"image_url\",\"image_url\":{\"url\":\"[Blob substitute]\"}}]'\n *\n * // Without this, asString() would JSON.stringify the raw array and the base64 blob\n * // would end up in span attributes, since downstream stripping only works on objects.\n */\nfunction normalizeContent(v: unknown): string {\n if (Array.isArray(v)) {\n try {\n const stripped = v.map(part =>\n part && typeof part === 'object' && isContentMedia(part) ? stripInlineMediaFromSingleMessage(part) : part,\n );\n return JSON.stringify(stripped);\n } catch {\n return String(v);\n }\n }\n return asString(v);\n}\n\n/**\n * Normalizes a single role token to our canonical set.\n *\n * @param role Incoming role value (free-form, any casing)\n * @returns Canonical role: 'user' | 'assistant' | 'system' | 'function' | 'tool' | <passthrough>\n */\nfunction normalizeMessageRole(role: string): string {\n const normalized = role.toLowerCase();\n return ROLE_MAP[normalized] ?? normalized;\n}\n\n/**\n * Infers a role from a LangChain message constructor name.\n *\n * Checks for substrings like \"System\", \"Human\", \"AI\", etc.\n */\nfunction normalizeRoleNameFromCtor(name: string): string {\n if (name.includes('System')) return 'system';\n if (name.includes('Human')) return 'user';\n if (name.includes('AI') || name.includes('Assistant')) return 'assistant';\n if (name.includes('Function')) return 'function';\n if (name.includes('Tool')) return 'tool';\n return 'user';\n}\n\n/**\n * Returns invocation params from a LangChain `tags` object.\n *\n * LangChain often passes runtime parameters (model, temperature, etc.) via the\n * `tags.invocation_params` bag. If `tags` is an array (LangChain sometimes uses\n * string tags), we return `undefined`.\n *\n * @param tags LangChain tags (string[] or record)\n * @returns The `invocation_params` object, if present\n */\nexport function getInvocationParams(tags?: string[] | Record<string, unknown>): Record<string, unknown> | undefined {\n if (!tags || Array.isArray(tags)) return undefined;\n return tags.invocation_params as Record<string, unknown> | undefined;\n}\n\n/**\n * Normalizes a heterogeneous set of LangChain messages to `{ role, content }`.\n *\n * Why so many branches? LangChain messages can arrive in several shapes:\n * - Message classes with `_getType()` (most reliable)\n * - Classes with meaningful constructor names (e.g. `SystemMessage`)\n * - Plain objects with `type`, or `{ role, content }`\n * - Serialized format with `{ lc: 1, id: [...], kwargs: { content } }`\n * We preserve the prioritization to minimize behavioral drift.\n *\n * @param messages Mixed LangChain messages\n * @returns Array of normalized `{ role, content }`\n */\nexport function normalizeLangChainMessages(messages: LangChainMessage[]): Array<{ role: string; content: string }> {\n return messages.map(message => {\n // 1) Prefer _getType() when present\n const maybeGetType = (message as { _getType?: () => string })._getType;\n if (typeof maybeGetType === 'function') {\n const messageType = maybeGetType.call(message);\n return {\n role: normalizeMessageRole(messageType),\n content: normalizeContent(message.content),\n };\n }\n\n // 2) Serialized LangChain format (lc: 1) - check before constructor name\n // This is more reliable than constructor.name which can be lost during serialization\n if (message.lc === 1 && message.kwargs) {\n const id = message.id;\n const messageType = Array.isArray(id) && id.length > 0 ? id[id.length - 1] : '';\n const role = typeof messageType === 'string' ? normalizeRoleNameFromCtor(messageType) : 'user';\n\n return {\n role: normalizeMessageRole(role),\n content: normalizeContent(message.kwargs?.content),\n };\n }\n\n // 3) Then objects with `type`\n if (message.type) {\n const role = String(message.type).toLowerCase();\n return {\n role: normalizeMessageRole(role),\n content: normalizeContent(message.content),\n };\n }\n\n // 4) Then objects with `{ role, content }` - check before constructor name\n // Plain objects have constructor.name=\"Object\" which would incorrectly default to \"user\"\n if (message.role) {\n return {\n role: normalizeMessageRole(String(message.role)),\n content: normalizeContent(message.content),\n };\n }\n\n // 5) Then try constructor name (SystemMessage / HumanMessage / ...)\n // Only use this if we haven't matched a more specific case\n const ctor = (message as { constructor?: { name?: string } }).constructor?.name;\n if (ctor && ctor !== 'Object') {\n return {\n role: normalizeMessageRole(normalizeRoleNameFromCtor(ctor)),\n content: normalizeContent(message.content),\n };\n }\n\n // 6) Fallback: treat as user text\n return {\n role: 'user',\n content: normalizeContent(message.content),\n };\n });\n}\n\n/**\n * Extracts request attributes common to both LLM and ChatModel invocations.\n *\n * Source precedence:\n * 1) `invocationParams` (highest)\n * 2) `langSmithMetadata`\n *\n * Numeric values are set even when 0 (e.g. `temperature: 0`), but skipped if `NaN`.\n */\nfunction extractCommonRequestAttributes(\n serialized: LangChainSerialized,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n const attrs: Record<string, SpanAttributeValue> = {};\n\n // Get kwargs if available (from constructor type)\n const kwargs = 'kwargs' in serialized ? serialized.kwargs : undefined;\n\n const temperature = invocationParams?.temperature ?? langSmithMetadata?.ls_temperature ?? kwargs?.temperature;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE, temperature);\n\n const maxTokens = invocationParams?.max_tokens ?? langSmithMetadata?.ls_max_tokens ?? kwargs?.max_tokens;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, maxTokens);\n\n const topP = invocationParams?.top_p ?? kwargs?.top_p;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_TOP_P_ATTRIBUTE, topP);\n\n const frequencyPenalty = invocationParams?.frequency_penalty;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE, frequencyPenalty);\n\n const presencePenalty = invocationParams?.presence_penalty;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE, presencePenalty);\n\n // LangChain uses `stream`. We only set the attribute if the key actually exists\n // (some callbacks report `false` even on streamed requests, this stems from LangChain's callback handler).\n if (invocationParams && 'stream' in invocationParams) {\n setIfDefined(attrs, GEN_AI_REQUEST_STREAM_ATTRIBUTE, Boolean(invocationParams.stream));\n }\n\n return attrs;\n}\n\n/**\n * Small helper to assemble boilerplate attributes shared by both request extractors.\n * Always uses 'chat' as the operation type for all LLM and chat model operations.\n */\nfunction baseRequestAttributes(\n system: unknown,\n modelName: unknown,\n serialized: LangChainSerialized,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n return {\n [GEN_AI_SYSTEM_ATTRIBUTE]: asString(system ?? 'langchain'),\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'chat',\n [GEN_AI_REQUEST_MODEL_ATTRIBUTE]: asString(modelName),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n ...extractCommonRequestAttributes(serialized, invocationParams, langSmithMetadata),\n };\n}\n\n/**\n * Extracts attributes for plain LLM invocations (string prompts).\n *\n * - Operation is tagged as `chat` following OpenTelemetry semantic conventions.\n * LangChain LLM operations are treated as chat operations.\n * - When `recordInputs` is true, string prompts are wrapped into `{role:\"user\"}`\n * messages to align with the chat schema used elsewhere.\n */\nexport function extractLLMRequestAttributes(\n llm: LangChainSerialized,\n prompts: string[],\n recordInputs: boolean,\n enableTruncation: boolean,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n const system = langSmithMetadata?.ls_provider;\n const modelName = invocationParams?.model ?? langSmithMetadata?.ls_model_name ?? 'unknown';\n\n const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata);\n\n if (recordInputs && Array.isArray(prompts) && prompts.length > 0) {\n setIfDefined(attrs, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, prompts.length);\n const messages = prompts.map(p => ({ role: 'user', content: p }));\n setIfDefined(\n attrs,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n enableTruncation ? getTruncatedJsonString(messages) : getJsonString(messages),\n );\n }\n\n return attrs;\n}\n\n/**\n * Extracts attributes for ChatModel invocations (array-of-arrays of messages).\n *\n * - Operation is tagged as `chat` following OpenTelemetry semantic conventions.\n * LangChain chat model operations are chat operations.\n * - We flatten LangChain's `LangChainMessage[][]` and normalize shapes into a\n * consistent `{ role, content }` array when `recordInputs` is true.\n * - Provider system value falls back to `serialized.id?.[2]`.\n */\nexport function extractChatModelRequestAttributes(\n llm: LangChainSerialized,\n langChainMessages: LangChainMessage[][],\n recordInputs: boolean,\n enableTruncation: boolean,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n const system = langSmithMetadata?.ls_provider ?? llm.id?.[2];\n const modelName = invocationParams?.model ?? langSmithMetadata?.ls_model_name ?? 'unknown';\n\n const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata);\n\n if (recordInputs && Array.isArray(langChainMessages) && langChainMessages.length > 0) {\n const normalized = normalizeLangChainMessages(langChainMessages.flat());\n\n const { systemInstructions, filteredMessages } = extractSystemInstructions(normalized);\n\n if (systemInstructions) {\n setIfDefined(attrs, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n setIfDefined(attrs, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredLength);\n\n setIfDefined(\n attrs,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n enableTruncation ? getTruncatedJsonString(filteredMessages) : getJsonString(filteredMessages),\n );\n }\n\n return attrs;\n}\n\n/**\n * Scans generations for Anthropic-style `tool_use` items and records them.\n *\n * LangChain represents some provider messages (e.g., Anthropic) with a `message.content`\n * array that may include objects `{ type: 'tool_use', ... }`. We collect and attach\n * them as a JSON array on `gen_ai.response.tool_calls` for downstream consumers.\n */\nfunction addToolCallsAttributes(generations: LangChainMessage[][], attrs: Record<string, SpanAttributeValue>): void {\n const toolCalls: unknown[] = [];\n const flatGenerations = generations.flat();\n\n for (const gen of flatGenerations) {\n const content = gen.message?.content;\n if (Array.isArray(content)) {\n for (const item of content) {\n const t = item as { type: string };\n if (t.type === 'tool_use') toolCalls.push(t);\n }\n }\n }\n\n if (toolCalls.length > 0) {\n setIfDefined(attrs, GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, asString(toolCalls));\n }\n}\n\n/**\n * Adds token usage attributes, supporting both OpenAI (`tokenUsage`) and Anthropic (`usage`) formats.\n * - Preserve zero values (0 tokens) by avoiding truthy checks.\n * - Compute a total for Anthropic when not explicitly provided.\n * - Include cache token metrics when present.\n */\nfunction addTokenUsageAttributes(\n llmOutput: LangChainLLMResult['llmOutput'],\n attrs: Record<string, SpanAttributeValue>,\n): void {\n if (!llmOutput) return;\n\n const tokenUsage = llmOutput.tokenUsage as\n | { promptTokens?: number; completionTokens?: number; totalTokens?: number }\n | undefined;\n const anthropicUsage = llmOutput.usage as\n | {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n }\n | undefined;\n\n if (tokenUsage) {\n setNumberIfDefined(attrs, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, tokenUsage.promptTokens);\n setNumberIfDefined(attrs, GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, tokenUsage.completionTokens);\n setNumberIfDefined(attrs, GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, tokenUsage.totalTokens);\n } else if (anthropicUsage) {\n setNumberIfDefined(attrs, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, anthropicUsage.input_tokens);\n setNumberIfDefined(attrs, GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, anthropicUsage.output_tokens);\n\n // Compute total when not provided by the provider.\n const input = Number(anthropicUsage.input_tokens);\n const output = Number(anthropicUsage.output_tokens);\n const total = (Number.isNaN(input) ? 0 : input) + (Number.isNaN(output) ? 0 : output);\n if (total > 0) setNumberIfDefined(attrs, GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, total);\n\n // Extra Anthropic cache metrics (present only when caching is enabled)\n if (anthropicUsage.cache_creation_input_tokens !== undefined)\n setNumberIfDefined(\n attrs,\n GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE,\n anthropicUsage.cache_creation_input_tokens,\n );\n if (anthropicUsage.cache_read_input_tokens !== undefined)\n setNumberIfDefined(attrs, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE, anthropicUsage.cache_read_input_tokens);\n }\n}\n\n/**\n * Extracts response-related attributes based on a `LangChainLLMResult`.\n *\n * - Records finish reasons when present on generations (e.g., OpenAI)\n * - When `recordOutputs` is true, captures textual response content and any\n * tool calls.\n * - Also propagates model name (`model_name` or `model`), response `id`, and\n * `stop_reason` (for providers that use it).\n */\nexport function extractLlmResponseAttributes(\n llmResult: LangChainLLMResult,\n recordOutputs: boolean,\n): Record<string, SpanAttributeValue> | undefined {\n if (!llmResult) return;\n\n const attrs: Record<string, SpanAttributeValue> = {};\n\n if (Array.isArray(llmResult.generations)) {\n const finishReasons = llmResult.generations\n .flat()\n .map(g => {\n // v1 uses generationInfo.finish_reason\n if (g.generationInfo?.finish_reason) {\n return g.generationInfo.finish_reason;\n }\n // v0.3+ uses generation_info.finish_reason\n if (g.generation_info?.finish_reason) {\n return g.generation_info.finish_reason;\n }\n return null;\n })\n .filter((r): r is string => typeof r === 'string');\n\n if (finishReasons.length > 0) {\n setIfDefined(attrs, GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE, asString(finishReasons));\n }\n\n // Tool calls metadata (names, IDs) are not PII, so capture them regardless of recordOutputs\n addToolCallsAttributes(llmResult.generations as LangChainMessage[][], attrs);\n\n if (recordOutputs) {\n const texts = llmResult.generations\n .flat()\n .map(gen => gen.text ?? gen.message?.content)\n .filter(t => typeof t === 'string');\n\n if (texts.length > 0) {\n setIfDefined(attrs, GEN_AI_RESPONSE_TEXT_ATTRIBUTE, asString(texts));\n }\n }\n }\n\n addTokenUsageAttributes(llmResult.llmOutput, attrs);\n\n const llmOutput = llmResult.llmOutput;\n\n // Extract from v1 generations structure if available\n const firstGeneration = llmResult.generations?.[0]?.[0];\n const v1Message = firstGeneration?.message;\n\n // Provider model identifier: `model_name` (OpenAI-style) or `model` (others)\n // v1 stores this in message.response_metadata.model_name\n const modelName = llmOutput?.model_name ?? llmOutput?.model ?? v1Message?.response_metadata?.model_name;\n if (modelName) setIfDefined(attrs, GEN_AI_RESPONSE_MODEL_ATTRIBUTE, modelName);\n\n // Response ID: v1 stores this in message.id\n const responseId = llmOutput?.id ?? v1Message?.id;\n if (responseId) {\n setIfDefined(attrs, GEN_AI_RESPONSE_ID_ATTRIBUTE, responseId);\n }\n\n // Stop reason: v1 stores this in message.response_metadata.finish_reason\n const stopReason = llmOutput?.stop_reason ?? v1Message?.response_metadata?.finish_reason;\n if (stopReason) {\n setIfDefined(attrs, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE, asString(stopReason));\n }\n\n return attrs;\n}\n"],"names":["isContentMedia","stripInlineMediaFromSingleMessage","ROLE_MAP","GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_STREAM_ATTRIBUTE","GEN_AI_SYSTEM_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","LANGCHAIN_ORIGIN","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","getTruncatedJsonString","getJsonString","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/tracing/langchain/utils.ts"],"sourcesContent":["import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport type { SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_AGENT_NAME_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_STREAM_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { isContentMedia, stripInlineMediaFromSingleMessage } from '../ai/mediaStripping';\nimport { extractSystemInstructions, getJsonString, getTruncatedJsonString } from '../ai/utils';\nimport { LANGCHAIN_ORIGIN, ROLE_MAP } from './constants';\nimport type { LangChainLLMResult, LangChainMessage, LangChainSerialized } from './types';\n\n/**\n * Assigns an attribute only when the value is neither `undefined` nor `null`.\n *\n * We keep this tiny helper because call sites are repetitive and easy to miswrite.\n * It also preserves falsy-but-valid values like `0` and `\"\"`.\n */\nconst setIfDefined = (target: Record<string, SpanAttributeValue>, key: string, value: unknown): void => {\n if (value != null) target[key] = value as SpanAttributeValue;\n};\n\n/**\n * Like `setIfDefined`, but converts the value with `Number()` and skips only when the\n * result is `NaN`. This ensures numeric 0 makes it through (unlike truthy checks).\n */\nconst setNumberIfDefined = (target: Record<string, SpanAttributeValue>, key: string, value: unknown): void => {\n const n = Number(value);\n if (!Number.isNaN(n)) target[key] = n;\n};\n\n/**\n * Converts a value to a string. Avoids double-quoted JSON strings where a plain\n * string is desired, but still handles objects/arrays safely.\n */\nfunction asString(v: unknown): string {\n if (typeof v === 'string') return v;\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n\n/**\n * Converts message content to a string, stripping inline media (base64 images, audio, etc.)\n * from multimodal content before stringification so downstream media stripping can't miss it.\n *\n * @example\n * // String content passes through unchanged:\n * normalizeContent(\"Hello\") // => \"Hello\"\n *\n * // Multimodal array content — media is replaced with \"[Blob substitute]\" before JSON.stringify:\n * normalizeContent([\n * { type: \"text\", text: \"What color?\" },\n * { type: \"image_url\", image_url: { url: \"data:image/png;base64,iVBOR...\" } }\n * ])\n * // => '[{\"type\":\"text\",\"text\":\"What color?\"},{\"type\":\"image_url\",\"image_url\":{\"url\":\"[Blob substitute]\"}}]'\n *\n * // Without this, asString() would JSON.stringify the raw array and the base64 blob\n * // would end up in span attributes, since downstream stripping only works on objects.\n */\nfunction normalizeContent(v: unknown): string {\n if (Array.isArray(v)) {\n try {\n const stripped = v.map(part =>\n part && typeof part === 'object' && isContentMedia(part) ? stripInlineMediaFromSingleMessage(part) : part,\n );\n return JSON.stringify(stripped);\n } catch {\n return String(v);\n }\n }\n return asString(v);\n}\n\n/**\n * Normalizes a single role token to our canonical set.\n *\n * @param role Incoming role value (free-form, any casing)\n * @returns Canonical role: 'user' | 'assistant' | 'system' | 'function' | 'tool' | <passthrough>\n */\nfunction normalizeMessageRole(role: string): string {\n const normalized = role.toLowerCase();\n return ROLE_MAP[normalized] ?? normalized;\n}\n\n/**\n * Infers a role from a LangChain message constructor name.\n *\n * Checks for substrings like \"System\", \"Human\", \"AI\", etc.\n */\nfunction normalizeRoleNameFromCtor(name: string): string {\n if (name.includes('System')) return 'system';\n if (name.includes('Human')) return 'user';\n if (name.includes('AI') || name.includes('Assistant')) return 'assistant';\n if (name.includes('Function')) return 'function';\n if (name.includes('Tool')) return 'tool';\n return 'user';\n}\n\n/**\n * Returns invocation params from a LangChain `tags` object.\n *\n * LangChain often passes runtime parameters (model, temperature, etc.) via the\n * `tags.invocation_params` bag. If `tags` is an array (LangChain sometimes uses\n * string tags), we return `undefined`.\n *\n * @param tags LangChain tags (string[] or record)\n * @returns The `invocation_params` object, if present\n */\nexport function getInvocationParams(tags?: string[] | Record<string, unknown>): Record<string, unknown> | undefined {\n if (!tags || Array.isArray(tags)) return undefined;\n return tags.invocation_params as Record<string, unknown> | undefined;\n}\n\n/**\n * Normalizes a heterogeneous set of LangChain messages to `{ role, content }`.\n *\n * Why so many branches? LangChain messages can arrive in several shapes:\n * - Message classes with `_getType()` (most reliable)\n * - Classes with meaningful constructor names (e.g. `SystemMessage`)\n * - Plain objects with `type`, or `{ role, content }`\n * - Serialized format with `{ lc: 1, id: [...], kwargs: { content } }`\n * We preserve the prioritization to minimize behavioral drift.\n *\n * @param messages Mixed LangChain messages\n * @returns Array of normalized `{ role, content }`\n */\nexport function normalizeLangChainMessages(messages: LangChainMessage[]): Array<{ role: string; content: string }> {\n return messages.map(message => {\n // 1) Prefer _getType() when present\n const maybeGetType = (message as { _getType?: () => string })._getType;\n if (typeof maybeGetType === 'function') {\n const messageType = maybeGetType.call(message);\n return {\n role: normalizeMessageRole(messageType),\n content: normalizeContent(message.content),\n };\n }\n\n // 2) Serialized LangChain format (lc: 1) - check before constructor name\n // This is more reliable than constructor.name which can be lost during serialization\n if (message.lc === 1 && message.kwargs) {\n const id = message.id;\n const messageType = Array.isArray(id) && id.length > 0 ? id[id.length - 1] : '';\n const role = typeof messageType === 'string' ? normalizeRoleNameFromCtor(messageType) : 'user';\n\n return {\n role: normalizeMessageRole(role),\n content: normalizeContent(message.kwargs?.content),\n };\n }\n\n // 3) Then objects with `type`\n if (message.type) {\n const role = String(message.type).toLowerCase();\n return {\n role: normalizeMessageRole(role),\n content: normalizeContent(message.content),\n };\n }\n\n // 4) Then objects with `{ role, content }` - check before constructor name\n // Plain objects have constructor.name=\"Object\" which would incorrectly default to \"user\"\n if (message.role) {\n return {\n role: normalizeMessageRole(String(message.role)),\n content: normalizeContent(message.content),\n };\n }\n\n // 5) Then try constructor name (SystemMessage / HumanMessage / ...)\n // Only use this if we haven't matched a more specific case\n const ctor = (message as { constructor?: { name?: string } }).constructor?.name;\n if (ctor && ctor !== 'Object') {\n return {\n role: normalizeMessageRole(normalizeRoleNameFromCtor(ctor)),\n content: normalizeContent(message.content),\n };\n }\n\n // 6) Fallback: treat as user text\n return {\n role: 'user',\n content: normalizeContent(message.content),\n };\n });\n}\n\n/**\n * Extracts request attributes common to both LLM and ChatModel invocations.\n *\n * Source precedence:\n * 1) `invocationParams` (highest)\n * 2) `langSmithMetadata`\n *\n * Numeric values are set even when 0 (e.g. `temperature: 0`), but skipped if `NaN`.\n */\nfunction extractCommonRequestAttributes(\n serialized: LangChainSerialized,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n const attrs: Record<string, SpanAttributeValue> = {};\n\n // Get kwargs if available (from constructor type)\n const kwargs = 'kwargs' in serialized ? serialized.kwargs : undefined;\n\n const temperature = invocationParams?.temperature ?? langSmithMetadata?.ls_temperature ?? kwargs?.temperature;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE, temperature);\n\n const maxTokens = invocationParams?.max_tokens ?? langSmithMetadata?.ls_max_tokens ?? kwargs?.max_tokens;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, maxTokens);\n\n const topP = invocationParams?.top_p ?? kwargs?.top_p;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_TOP_P_ATTRIBUTE, topP);\n\n const frequencyPenalty = invocationParams?.frequency_penalty;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE, frequencyPenalty);\n\n const presencePenalty = invocationParams?.presence_penalty;\n setNumberIfDefined(attrs, GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE, presencePenalty);\n\n // LangChain uses `stream`. We only set the attribute if the key actually exists\n // (some callbacks report `false` even on streamed requests, this stems from LangChain's callback handler).\n if (invocationParams && 'stream' in invocationParams) {\n setIfDefined(attrs, GEN_AI_REQUEST_STREAM_ATTRIBUTE, Boolean(invocationParams.stream));\n }\n\n return attrs;\n}\n\n/**\n * Small helper to assemble boilerplate attributes shared by both request extractors.\n * Always uses 'chat' as the operation type for all LLM and chat model operations.\n */\nfunction baseRequestAttributes(\n system: unknown,\n modelName: unknown,\n serialized: LangChainSerialized,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n return {\n [GEN_AI_SYSTEM_ATTRIBUTE]: asString(system ?? 'langchain'),\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'chat',\n [GEN_AI_REQUEST_MODEL_ATTRIBUTE]: asString(modelName),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n ...extractCommonRequestAttributes(serialized, invocationParams, langSmithMetadata),\n };\n}\n\n/**\n * Extracts attributes for plain LLM invocations (string prompts).\n *\n * - Operation is tagged as `chat` following OpenTelemetry semantic conventions.\n * LangChain LLM operations are treated as chat operations.\n * - When `recordInputs` is true, string prompts are wrapped into `{role:\"user\"}`\n * messages to align with the chat schema used elsewhere.\n */\nexport function extractLLMRequestAttributes(\n llm: LangChainSerialized,\n prompts: string[],\n recordInputs: boolean,\n enableTruncation: boolean,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n const system = langSmithMetadata?.ls_provider;\n const modelName = invocationParams?.model ?? langSmithMetadata?.ls_model_name ?? 'unknown';\n\n const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata);\n\n if (recordInputs && Array.isArray(prompts) && prompts.length > 0) {\n setIfDefined(attrs, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, prompts.length);\n const messages = prompts.map(p => ({ role: 'user', content: p }));\n setIfDefined(\n attrs,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n enableTruncation ? getTruncatedJsonString(messages) : getJsonString(messages),\n );\n }\n\n return attrs;\n}\n\n/**\n * Extracts attributes for ChatModel invocations (array-of-arrays of messages).\n *\n * - Operation is tagged as `chat` following OpenTelemetry semantic conventions.\n * LangChain chat model operations are chat operations.\n * - We flatten LangChain's `LangChainMessage[][]` and normalize shapes into a\n * consistent `{ role, content }` array when `recordInputs` is true.\n * - Provider system value falls back to `serialized.id?.[2]`.\n */\nexport function extractChatModelRequestAttributes(\n llm: LangChainSerialized,\n langChainMessages: LangChainMessage[][],\n recordInputs: boolean,\n enableTruncation: boolean,\n invocationParams?: Record<string, unknown>,\n langSmithMetadata?: Record<string, unknown>,\n): Record<string, SpanAttributeValue> {\n const system = langSmithMetadata?.ls_provider ?? llm.id?.[2];\n const modelName = invocationParams?.model ?? langSmithMetadata?.ls_model_name ?? 'unknown';\n\n const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata);\n\n if (recordInputs && Array.isArray(langChainMessages) && langChainMessages.length > 0) {\n const normalized = normalizeLangChainMessages(langChainMessages.flat());\n\n const { systemInstructions, filteredMessages } = extractSystemInstructions(normalized);\n\n if (systemInstructions) {\n setIfDefined(attrs, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n setIfDefined(attrs, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredLength);\n\n setIfDefined(\n attrs,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n enableTruncation ? getTruncatedJsonString(filteredMessages) : getJsonString(filteredMessages),\n );\n }\n\n return attrs;\n}\n\n/**\n * Extracts tool calls from generations and records them on the span attributes.\n * Prefers message.tool_calls (LangChain's normalized format). Falls back to\n * scanning message.content for Anthropic-style tool_use items in older versions\n * where tool_calls may not be populated.\n */\nfunction addToolCallsAttributes(generations: LangChainMessage[][], attrs: Record<string, SpanAttributeValue>): void {\n const toolCalls: unknown[] = [];\n const flatGenerations = generations.flat();\n\n for (const gen of flatGenerations) {\n const msg = gen.message as Record<string, unknown> | undefined;\n const msgToolCalls = msg?.tool_calls as unknown[] | undefined;\n if (Array.isArray(msgToolCalls) && msgToolCalls.length > 0) {\n toolCalls.push(...msgToolCalls);\n } else {\n // Fallback for older LangChain versions: scan message.content for Anthropic-style tool_use\n const content = gen.message?.content;\n if (Array.isArray(content)) {\n for (const item of content) {\n const t = item as Record<string, unknown>;\n if (t.type === 'tool_use') toolCalls.push(t);\n }\n }\n }\n }\n\n if (toolCalls.length > 0) {\n setIfDefined(attrs, GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, asString(toolCalls));\n }\n}\n\n/**\n * Adds token usage attributes, supporting both OpenAI (`tokenUsage`) and Anthropic (`usage`) formats.\n * - Preserve zero values (0 tokens) by avoiding truthy checks.\n * - Compute a total for Anthropic when not explicitly provided.\n * - Include cache token metrics when present.\n */\nfunction addTokenUsageAttributes(\n llmOutput: LangChainLLMResult['llmOutput'],\n attrs: Record<string, SpanAttributeValue>,\n): void {\n if (!llmOutput) return;\n\n const tokenUsage = llmOutput.tokenUsage as\n | { promptTokens?: number; completionTokens?: number; totalTokens?: number }\n | undefined;\n const anthropicUsage = llmOutput.usage as\n | {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n }\n | undefined;\n\n if (tokenUsage) {\n setNumberIfDefined(attrs, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, tokenUsage.promptTokens);\n setNumberIfDefined(attrs, GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, tokenUsage.completionTokens);\n setNumberIfDefined(attrs, GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, tokenUsage.totalTokens);\n } else if (anthropicUsage) {\n setNumberIfDefined(attrs, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, anthropicUsage.input_tokens);\n setNumberIfDefined(attrs, GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, anthropicUsage.output_tokens);\n\n // Compute total when not provided by the provider.\n const input = Number(anthropicUsage.input_tokens);\n const output = Number(anthropicUsage.output_tokens);\n const total = (Number.isNaN(input) ? 0 : input) + (Number.isNaN(output) ? 0 : output);\n if (total > 0) setNumberIfDefined(attrs, GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, total);\n\n // Extra Anthropic cache metrics (present only when caching is enabled)\n if (anthropicUsage.cache_creation_input_tokens !== undefined)\n setNumberIfDefined(\n attrs,\n GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE,\n anthropicUsage.cache_creation_input_tokens,\n );\n if (anthropicUsage.cache_read_input_tokens !== undefined)\n setNumberIfDefined(attrs, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE, anthropicUsage.cache_read_input_tokens);\n }\n}\n\n/**\n * Extracts response-related attributes based on a `LangChainLLMResult`.\n *\n * - Records finish reasons when present on generations (e.g., OpenAI)\n * - When `recordOutputs` is true, captures textual response content and any\n * tool calls.\n * - Also propagates model name (`model_name` or `model`), response `id`, and\n * `stop_reason` (for providers that use it).\n */\nexport function extractLlmResponseAttributes(\n llmResult: LangChainLLMResult,\n recordOutputs: boolean,\n): Record<string, SpanAttributeValue> | undefined {\n if (!llmResult) return;\n\n const attrs: Record<string, SpanAttributeValue> = {};\n\n if (Array.isArray(llmResult.generations)) {\n const finishReasons = llmResult.generations\n .flat()\n .map(g => {\n // v1 uses generationInfo.finish_reason\n if (g.generationInfo?.finish_reason) {\n return g.generationInfo.finish_reason;\n }\n // v0.3+ uses generation_info.finish_reason\n if (g.generation_info?.finish_reason) {\n return g.generation_info.finish_reason;\n }\n return null;\n })\n .filter((r): r is string => typeof r === 'string');\n\n if (finishReasons.length > 0) {\n setIfDefined(attrs, GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE, asString(finishReasons));\n }\n\n // Tool calls metadata (names, IDs) are not PII, so capture them regardless of recordOutputs\n addToolCallsAttributes(llmResult.generations as LangChainMessage[][], attrs);\n\n if (recordOutputs) {\n const texts = llmResult.generations\n .flat()\n .map(gen => gen.text ?? gen.message?.content)\n .filter(t => typeof t === 'string');\n\n if (texts.length > 0) {\n setIfDefined(attrs, GEN_AI_RESPONSE_TEXT_ATTRIBUTE, asString(texts));\n }\n }\n }\n\n addTokenUsageAttributes(llmResult.llmOutput, attrs);\n\n const llmOutput = llmResult.llmOutput;\n\n // Extract from v1 generations structure if available\n const firstGeneration = llmResult.generations?.[0]?.[0];\n const v1Message = firstGeneration?.message;\n\n // Provider model identifier: `model_name` (OpenAI-style) or `model` (others)\n // v1 stores this in message.response_metadata.model_name\n const modelName = llmOutput?.model_name ?? llmOutput?.model ?? v1Message?.response_metadata?.model_name;\n if (modelName) setIfDefined(attrs, GEN_AI_RESPONSE_MODEL_ATTRIBUTE, modelName);\n\n // Response ID: v1 stores this in message.id\n const responseId = llmOutput?.id ?? v1Message?.id;\n if (responseId) {\n setIfDefined(attrs, GEN_AI_RESPONSE_ID_ATTRIBUTE, responseId);\n }\n\n // Stop reason: v1 stores this in message.response_metadata.finish_reason\n const stopReason = llmOutput?.stop_reason ?? v1Message?.response_metadata?.finish_reason;\n if (stopReason) {\n setIfDefined(attrs, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE, asString(stopReason));\n }\n\n return attrs;\n}\n\nexport function getAgentNameFromMetadata(metadata?: Record<string, unknown>): Record<string, SpanAttributeValue> {\n const attrs: Record<string, SpanAttributeValue> = {};\n // lc_agent_name is injected by instrumentCompiledGraphInvoke (langgraph integration)\n const agentName = metadata?.lc_agent_name;\n if (typeof agentName === 'string') {\n attrs[GEN_AI_AGENT_NAME_ATTRIBUTE] = agentName;\n }\n return attrs;\n}\n\nexport function extractToolDefinitions(extraParams?: Record<string, unknown>): string | undefined {\n const tools =\n (extraParams?.invocation_params as Record<string, unknown>)?.tools ??\n (extraParams?.options as Record<string, unknown>)?.tools;\n if (!Array.isArray(tools) || tools.length === 0) return undefined;\n const toolDefs = tools.map((tool: Record<string, unknown>) => {\n const fn = tool.function as Record<string, unknown> | undefined;\n return {\n type: 'function',\n name: tool.name ?? fn?.name ?? '',\n description: tool.description ?? fn?.description,\n };\n });\n return JSON.stringify(toolDefs);\n}\n"],"names":["isContentMedia","stripInlineMediaFromSingleMessage","ROLE_MAP","GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_STREAM_ATTRIBUTE","GEN_AI_SYSTEM_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","LANGCHAIN_ORIGIN","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","getTruncatedJsonString","getJsonString","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE","GEN_AI_AGENT_NAME_ATTRIBUTE"],"mappings":"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"}
|