@sentry/node 10.37.0 → 10.39.0-alpha.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/index.js +29 -24
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/node-fetch.js +1 -1
- package/build/cjs/integrations/node-fetch.js.map +1 -1
- package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js +8 -8
- package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/fastify/index.js +1 -1
- package/build/cjs/integrations/tracing/fastify/index.js.map +1 -1
- package/build/cjs/integrations/tracing/google-genai/instrumentation.js +9 -9
- package/build/cjs/integrations/tracing/google-genai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/langchain/instrumentation.js +9 -9
- package/build/cjs/integrations/tracing/langchain/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/langgraph/instrumentation.js +6 -6
- package/build/cjs/integrations/tracing/langgraph/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/openai/instrumentation.js +11 -11
- package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/postgresjs.js +10 -10
- package/build/cjs/integrations/tracing/postgresjs.js.map +1 -1
- package/build/cjs/integrations/tracing/vercelai/instrumentation.js +9 -2
- package/build/cjs/integrations/tracing/vercelai/instrumentation.js.map +1 -1
- package/build/cjs/sdk/initOtel.js +1 -0
- package/build/cjs/sdk/initOtel.js.map +1 -1
- package/build/esm/index.js +2 -2
- package/build/esm/integrations/node-fetch.js +1 -1
- package/build/esm/integrations/node-fetch.js.map +1 -1
- package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js +8 -8
- package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/fastify/index.js +1 -1
- package/build/esm/integrations/tracing/fastify/index.js.map +1 -1
- package/build/esm/integrations/tracing/google-genai/instrumentation.js +9 -9
- package/build/esm/integrations/tracing/google-genai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/langchain/instrumentation.js +9 -9
- package/build/esm/integrations/tracing/langchain/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/langgraph/instrumentation.js +6 -6
- package/build/esm/integrations/tracing/langgraph/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/openai/instrumentation.js +11 -11
- package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/postgresjs.js +10 -10
- package/build/esm/integrations/tracing/postgresjs.js.map +1 -1
- package/build/esm/integrations/tracing/vercelai/instrumentation.js +9 -2
- package/build/esm/integrations/tracing/vercelai/instrumentation.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/sdk/initOtel.js +1 -0
- package/build/esm/sdk/initOtel.js.map +1 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/vercelai/instrumentation.d.ts.map +1 -1
- package/build/types/sdk/initOtel.d.ts.map +1 -1
- package/build/types-ts3.8/index.d.ts +2 -2
- package/package.json +5 -5
package/build/cjs/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const http = require('./integrations/http.js');
|
|
|
4
4
|
const nodeFetch = require('./integrations/node-fetch.js');
|
|
5
5
|
const fs = require('./integrations/fs.js');
|
|
6
6
|
const express = require('./integrations/tracing/express.js');
|
|
7
|
-
const index = require('./integrations/tracing/fastify/index.js');
|
|
7
|
+
const index$1 = require('./integrations/tracing/fastify/index.js');
|
|
8
8
|
const graphql = require('./integrations/tracing/graphql.js');
|
|
9
9
|
const kafka = require('./integrations/tracing/kafka.js');
|
|
10
10
|
const lrumemoizer = require('./integrations/tracing/lrumemoizer.js');
|
|
@@ -16,8 +16,8 @@ const redis = require('./integrations/tracing/redis.js');
|
|
|
16
16
|
const postgres = require('./integrations/tracing/postgres.js');
|
|
17
17
|
const postgresjs = require('./integrations/tracing/postgresjs.js');
|
|
18
18
|
const prisma = require('./integrations/tracing/prisma.js');
|
|
19
|
-
const index$
|
|
20
|
-
const index$
|
|
19
|
+
const index$5 = require('./integrations/tracing/hapi/index.js');
|
|
20
|
+
const index$6 = require('./integrations/tracing/hono/index.js');
|
|
21
21
|
const koa = require('./integrations/tracing/koa.js');
|
|
22
22
|
const connect = require('./integrations/tracing/connect.js');
|
|
23
23
|
const knex = require('./integrations/tracing/knex.js');
|
|
@@ -25,10 +25,10 @@ const tedious = require('./integrations/tracing/tedious.js');
|
|
|
25
25
|
const genericPool = require('./integrations/tracing/genericPool.js');
|
|
26
26
|
const dataloader = require('./integrations/tracing/dataloader.js');
|
|
27
27
|
const amqplib = require('./integrations/tracing/amqplib.js');
|
|
28
|
-
const index$
|
|
29
|
-
const index$
|
|
30
|
-
const index
|
|
31
|
-
const index$
|
|
28
|
+
const index$a = require('./integrations/tracing/vercelai/index.js');
|
|
29
|
+
const index$9 = require('./integrations/tracing/openai/index.js');
|
|
30
|
+
const index = require('./integrations/tracing/anthropic-ai/index.js');
|
|
31
|
+
const index$4 = require('./integrations/tracing/google-genai/index.js');
|
|
32
32
|
const index$7 = require('./integrations/tracing/langchain/index.js');
|
|
33
33
|
const index$8 = require('./integrations/tracing/langgraph/index.js');
|
|
34
34
|
const launchDarkly = require('./integrations/featureFlagShims/launchDarkly.js');
|
|
@@ -37,9 +37,9 @@ const statsig = require('./integrations/featureFlagShims/statsig.js');
|
|
|
37
37
|
const unleash = require('./integrations/featureFlagShims/unleash.js');
|
|
38
38
|
const growthbook = require('./integrations/featureFlagShims/growthbook.js');
|
|
39
39
|
const firebase = require('./integrations/tracing/firebase/firebase.js');
|
|
40
|
-
const index$
|
|
40
|
+
const index$3 = require('./sdk/index.js');
|
|
41
41
|
const initOtel = require('./sdk/initOtel.js');
|
|
42
|
-
const index$
|
|
42
|
+
const index$2 = require('./integrations/tracing/index.js');
|
|
43
43
|
const opentelemetry = require('@sentry/opentelemetry');
|
|
44
44
|
const core = require('@sentry/core');
|
|
45
45
|
const nodeCore = require('@sentry/node-core');
|
|
@@ -52,8 +52,8 @@ exports.fsIntegration = fs.fsIntegration;
|
|
|
52
52
|
exports.expressErrorHandler = express.expressErrorHandler;
|
|
53
53
|
exports.expressIntegration = express.expressIntegration;
|
|
54
54
|
exports.setupExpressErrorHandler = express.setupExpressErrorHandler;
|
|
55
|
-
exports.fastifyIntegration = index.fastifyIntegration;
|
|
56
|
-
exports.setupFastifyErrorHandler = index.setupFastifyErrorHandler;
|
|
55
|
+
exports.fastifyIntegration = index$1.fastifyIntegration;
|
|
56
|
+
exports.setupFastifyErrorHandler = index$1.setupFastifyErrorHandler;
|
|
57
57
|
exports.graphqlIntegration = graphql.graphqlIntegration;
|
|
58
58
|
exports.kafkaIntegration = kafka.kafkaIntegration;
|
|
59
59
|
exports.lruMemoizerIntegration = lrumemoizer.lruMemoizerIntegration;
|
|
@@ -65,10 +65,10 @@ exports.redisIntegration = redis.redisIntegration;
|
|
|
65
65
|
exports.postgresIntegration = postgres.postgresIntegration;
|
|
66
66
|
exports.postgresJsIntegration = postgresjs.postgresJsIntegration;
|
|
67
67
|
exports.prismaIntegration = prisma.prismaIntegration;
|
|
68
|
-
exports.hapiIntegration = index$
|
|
69
|
-
exports.setupHapiErrorHandler = index$
|
|
70
|
-
exports.honoIntegration = index$
|
|
71
|
-
exports.setupHonoErrorHandler = index$
|
|
68
|
+
exports.hapiIntegration = index$5.hapiIntegration;
|
|
69
|
+
exports.setupHapiErrorHandler = index$5.setupHapiErrorHandler;
|
|
70
|
+
exports.honoIntegration = index$6.honoIntegration;
|
|
71
|
+
exports.setupHonoErrorHandler = index$6.setupHonoErrorHandler;
|
|
72
72
|
exports.koaIntegration = koa.koaIntegration;
|
|
73
73
|
exports.setupKoaErrorHandler = koa.setupKoaErrorHandler;
|
|
74
74
|
exports.connectIntegration = connect.connectIntegration;
|
|
@@ -78,10 +78,10 @@ exports.tediousIntegration = tedious.tediousIntegration;
|
|
|
78
78
|
exports.genericPoolIntegration = genericPool.genericPoolIntegration;
|
|
79
79
|
exports.dataloaderIntegration = dataloader.dataloaderIntegration;
|
|
80
80
|
exports.amqplibIntegration = amqplib.amqplibIntegration;
|
|
81
|
-
exports.vercelAIIntegration = index$
|
|
82
|
-
exports.openAIIntegration = index$
|
|
83
|
-
exports.anthropicAIIntegration = index
|
|
84
|
-
exports.googleGenAIIntegration = index$
|
|
81
|
+
exports.vercelAIIntegration = index$a.vercelAIIntegration;
|
|
82
|
+
exports.openAIIntegration = index$9.openAIIntegration;
|
|
83
|
+
exports.anthropicAIIntegration = index.anthropicAIIntegration;
|
|
84
|
+
exports.googleGenAIIntegration = index$4.googleGenAIIntegration;
|
|
85
85
|
exports.langChainIntegration = index$7.langChainIntegration;
|
|
86
86
|
exports.langGraphIntegration = index$8.langGraphIntegration;
|
|
87
87
|
exports.buildLaunchDarklyFlagUsedHandler = launchDarkly.buildLaunchDarklyFlagUsedHandlerShim;
|
|
@@ -92,13 +92,13 @@ exports.statsigIntegration = statsig.statsigIntegrationShim;
|
|
|
92
92
|
exports.unleashIntegration = unleash.unleashIntegrationShim;
|
|
93
93
|
exports.growthbookIntegration = growthbook.growthbookIntegrationShim;
|
|
94
94
|
exports.firebaseIntegration = firebase.firebaseIntegration;
|
|
95
|
-
exports.getDefaultIntegrations = index$
|
|
96
|
-
exports.getDefaultIntegrationsWithoutPerformance = index$
|
|
97
|
-
exports.init = index$
|
|
98
|
-
exports.initWithoutDefaultIntegrations = index$
|
|
95
|
+
exports.getDefaultIntegrations = index$3.getDefaultIntegrations;
|
|
96
|
+
exports.getDefaultIntegrationsWithoutPerformance = index$3.getDefaultIntegrationsWithoutPerformance;
|
|
97
|
+
exports.init = index$3.init;
|
|
98
|
+
exports.initWithoutDefaultIntegrations = index$3.initWithoutDefaultIntegrations;
|
|
99
99
|
exports.initOpenTelemetry = initOtel.initOpenTelemetry;
|
|
100
100
|
exports.preloadOpenTelemetry = initOtel.preloadOpenTelemetry;
|
|
101
|
-
exports.getAutoPerformanceIntegrations = index$
|
|
101
|
+
exports.getAutoPerformanceIntegrations = index$2.getAutoPerformanceIntegrations;
|
|
102
102
|
exports.setNodeAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
|
|
103
103
|
exports.SDK_VERSION = core.SDK_VERSION;
|
|
104
104
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_OP = core.SEMANTIC_ATTRIBUTE_SENTRY_OP;
|
|
@@ -142,7 +142,11 @@ exports.getTraceData = core.getTraceData;
|
|
|
142
142
|
exports.getTraceMetaTags = core.getTraceMetaTags;
|
|
143
143
|
exports.httpHeadersToSpanAttributes = core.httpHeadersToSpanAttributes;
|
|
144
144
|
exports.inboundFiltersIntegration = core.inboundFiltersIntegration;
|
|
145
|
+
exports.instrumentAnthropicAiClient = core.instrumentAnthropicAiClient;
|
|
146
|
+
exports.instrumentGoogleGenAIClient = core.instrumentGoogleGenAIClient;
|
|
147
|
+
exports.instrumentLangGraph = core.instrumentLangGraph;
|
|
145
148
|
exports.instrumentOpenAiClient = core.instrumentOpenAiClient;
|
|
149
|
+
exports.instrumentStateGraphCompile = core.instrumentStateGraphCompile;
|
|
146
150
|
exports.instrumentSupabaseClient = core.instrumentSupabaseClient;
|
|
147
151
|
exports.isEnabled = core.isEnabled;
|
|
148
152
|
exports.isInitialized = core.isInitialized;
|
|
@@ -209,4 +213,5 @@ exports.processSessionIntegration = nodeCore.processSessionIntegration;
|
|
|
209
213
|
exports.spotlightIntegration = nodeCore.spotlightIntegration;
|
|
210
214
|
exports.systemErrorIntegration = nodeCore.systemErrorIntegration;
|
|
211
215
|
exports.validateOpenTelemetrySetup = nodeCore.validateOpenTelemetrySetup;
|
|
216
|
+
exports.withStreamSpan = nodeCore.withStreamSpan;
|
|
212
217
|
//# sourceMappingURL=index.js.map
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-fetch.js","sources":["../../../src/integrations/node-fetch.ts"],"sourcesContent":["import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici';\nimport { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n defineIntegration,\n getClient,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n stripDataUrlContent,\n} from '@sentry/core';\nimport type { NodeClient } from '@sentry/node-core';\nimport { generateInstrumentOnce, SentryNodeFetchInstrumentation } from '@sentry/node-core';\nimport type { NodeClientOptions } from '../types';\n\nconst INTEGRATION_NAME = 'NodeFetch';\n\ninterface NodeFetchOptions extends Pick<UndiciInstrumentationConfig, 'requestHook' | 'responseHook'> {\n /**\n * Whether breadcrumbs should be recorded for requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default UndiciInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for breadcrumbs & trace propagation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n}\n\nconst instrumentOtelNodeFetch = generateInstrumentOnce(\n INTEGRATION_NAME,\n UndiciInstrumentation,\n (options: NodeFetchOptions) => {\n return getConfigWithDefaults(options);\n },\n);\n\nconst instrumentSentryNodeFetch = generateInstrumentOnce(\n `${INTEGRATION_NAME}.sentry`,\n SentryNodeFetchInstrumentation,\n (options: NodeFetchOptions) => {\n return options;\n },\n);\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n return {\n name: 'NodeFetch',\n setupOnce() {\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n instrumentOtelNodeFetch(options);\n }\n\n // This is the Sentry-specific instrumentation that creates breadcrumbs & propagates traces\n // This must be registered after the OTEL one, to ensure that the core trace propagation logic takes presedence\n // Otherwise, the sentry-trace header may be set multiple times\n instrumentSentryNodeFetch(options);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n\n// Matching the behavior of the base instrumentation\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path
|
|
1
|
+
{"version":3,"file":"node-fetch.js","sources":["../../../src/integrations/node-fetch.ts"],"sourcesContent":["import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici';\nimport { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n defineIntegration,\n getClient,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n stripDataUrlContent,\n} from '@sentry/core';\nimport type { NodeClient } from '@sentry/node-core';\nimport { generateInstrumentOnce, SentryNodeFetchInstrumentation } from '@sentry/node-core';\nimport type { NodeClientOptions } from '../types';\n\nconst INTEGRATION_NAME = 'NodeFetch';\n\ninterface NodeFetchOptions extends Pick<UndiciInstrumentationConfig, 'requestHook' | 'responseHook'> {\n /**\n * Whether breadcrumbs should be recorded for requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default UndiciInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for breadcrumbs & trace propagation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n}\n\nconst instrumentOtelNodeFetch = generateInstrumentOnce(\n INTEGRATION_NAME,\n UndiciInstrumentation,\n (options: NodeFetchOptions) => {\n return getConfigWithDefaults(options);\n },\n);\n\nconst instrumentSentryNodeFetch = generateInstrumentOnce(\n `${INTEGRATION_NAME}.sentry`,\n SentryNodeFetchInstrumentation,\n (options: NodeFetchOptions) => {\n return options;\n },\n);\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n return {\n name: 'NodeFetch',\n setupOnce() {\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n instrumentOtelNodeFetch(options);\n }\n\n // This is the Sentry-specific instrumentation that creates breadcrumbs & propagates traces\n // This must be registered after the OTEL one, to ensure that the core trace propagation logic takes presedence\n // Otherwise, the sentry-trace header may be set multiple times\n instrumentSentryNodeFetch(options);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n\n// Matching the behavior of the base instrumentation\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path}`;\n }\n\n return `${url}${path}`;\n}\n\nfunction _shouldInstrumentSpans(options: NodeFetchOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled\n return typeof options.spans === 'boolean'\n ? options.spans\n : !clientOptions.skipOpenTelemetrySetup && hasSpansEnabled(clientOptions);\n}\n\nfunction getConfigWithDefaults(options: Partial<NodeFetchOptions> = {}): UndiciInstrumentationConfig {\n const instrumentationConfig = {\n requireParentforSpans: false,\n ignoreRequestHook: request => {\n const url = getAbsoluteUrl(request.origin, request.path);\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n const shouldIgnore = _ignoreOutgoingRequests && url && _ignoreOutgoingRequests(url);\n\n return !!shouldIgnore;\n },\n startSpanHook: request => {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n // Sanitize data URLs to prevent long base64 strings in span attributes\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n return {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n 'http.url': sanitizedUrl,\n [SEMANTIC_ATTRIBUTE_URL_FULL]: sanitizedUrl,\n [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: `${request.method || 'GET'} ${sanitizedUrl}`,\n };\n }\n\n return {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n };\n },\n requestHook: options.requestHook,\n responseHook: options.responseHook,\n } satisfies UndiciInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":["generateInstrumentOnce","UndiciInstrumentation","SentryNodeFetchInstrumentation","getClient","defineIntegration","hasSpansEnabled","stripDataUrlContent","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_URL_FULL","SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME"],"mappings":"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"}
|
|
@@ -28,8 +28,8 @@ class SentryAnthropicAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
28
28
|
/**
|
|
29
29
|
* Core patch logic applying instrumentation to the Anthropic AI client constructor.
|
|
30
30
|
*/
|
|
31
|
-
_patch(exports) {
|
|
32
|
-
const Original = exports.Anthropic;
|
|
31
|
+
_patch(exports$1) {
|
|
32
|
+
const Original = exports$1.Anthropic;
|
|
33
33
|
|
|
34
34
|
const config = this.getConfig();
|
|
35
35
|
|
|
@@ -68,10 +68,10 @@ class SentryAnthropicAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
68
68
|
// Constructor replacement - handle read-only properties
|
|
69
69
|
// The Anthropic property might have only a getter, so use defineProperty
|
|
70
70
|
try {
|
|
71
|
-
exports.Anthropic = WrappedAnthropic;
|
|
71
|
+
exports$1.Anthropic = WrappedAnthropic;
|
|
72
72
|
} catch (error) {
|
|
73
73
|
// If direct assignment fails, override the property descriptor
|
|
74
|
-
Object.defineProperty(exports, 'Anthropic', {
|
|
74
|
+
Object.defineProperty(exports$1, 'Anthropic', {
|
|
75
75
|
value: WrappedAnthropic,
|
|
76
76
|
writable: true,
|
|
77
77
|
configurable: true,
|
|
@@ -82,12 +82,12 @@ class SentryAnthropicAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
82
82
|
// Wrap the default export if it points to the original constructor
|
|
83
83
|
// Constructor replacement - handle read-only properties
|
|
84
84
|
// The Anthropic property might have only a getter, so use defineProperty
|
|
85
|
-
if (exports.default === Original) {
|
|
85
|
+
if (exports$1.default === Original) {
|
|
86
86
|
try {
|
|
87
|
-
exports.default = WrappedAnthropic;
|
|
87
|
+
exports$1.default = WrappedAnthropic;
|
|
88
88
|
} catch (error) {
|
|
89
89
|
// If direct assignment fails, override the property descriptor
|
|
90
|
-
Object.defineProperty(exports, 'default', {
|
|
90
|
+
Object.defineProperty(exports$1, 'default', {
|
|
91
91
|
value: WrappedAnthropic,
|
|
92
92
|
writable: true,
|
|
93
93
|
configurable: true,
|
|
@@ -95,7 +95,7 @@ class SentryAnthropicAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
-
return exports;
|
|
98
|
+
return exports$1;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/instrumentation.ts"],"sourcesContent":["import {\n InstrumentationBase,\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { AnthropicAiClient, AnthropicAiOptions } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n ANTHROPIC_AI_INTEGRATION_NAME,\n getClient,\n instrumentAnthropicAiClient,\n SDK_VERSION,\n} from '@sentry/core';\n\nconst supportedVersions = ['>=0.19.2 <1.0.0'];\n\ntype AnthropicAiInstrumentationOptions = InstrumentationConfig & AnthropicAiOptions;\n\n/**\n * Represents the patched shape of the Anthropic AI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n Anthropic: abstract new (...args: unknown[]) => AnthropicAiClient;\n}\n\n/**\n * Sentry Anthropic AI instrumentation using OpenTelemetry.\n */\nexport class SentryAnthropicAiInstrumentation extends InstrumentationBase<AnthropicAiInstrumentationOptions> {\n public constructor(config: AnthropicAiInstrumentationOptions = {}) {\n super('@sentry/instrumentation-anthropic-ai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@anthropic-ai/sdk',\n supportedVersions,\n this._patch.bind(this),\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Anthropic AI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.Anthropic;\n\n const config = this.getConfig();\n\n const WrappedAnthropic = function (this: unknown, ...args: unknown[]) {\n // Check if wrapping should be skipped (e.g., when LangChain is handling instrumentation)\n if (_INTERNAL_shouldSkipAiProviderWrapping(ANTHROPIC_AI_INTEGRATION_NAME)) {\n return Reflect.construct(Original, args) as AnthropicAiClient;\n }\n\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const recordInputs = config.recordInputs ?? defaultPii;\n const recordOutputs = config.recordOutputs ?? defaultPii;\n\n return instrumentAnthropicAiClient(instance as AnthropicAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => AnthropicAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedAnthropic, Original);\n Object.setPrototypeOf(WrappedAnthropic.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedAnthropic, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n try {\n exports.Anthropic = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'Anthropic', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","_INTERNAL_shouldSkipAiProviderWrapping","ANTHROPIC_AI_INTEGRATION_NAME","getClient","instrumentAnthropicAiClient"],"mappings":";;;;;AAeA,MAAM,iBAAA,GAAoB,CAAC,iBAAiB,CAAC;;AAY7C;AACA;AACA;AACO,MAAM,gCAAA,SAAyCA,mCAAmB,CAAoC;AAC7G,GAAS,WAAW,CAAC,MAAM,GAAsC,EAAE,EAAE;AACrE,IAAI,KAAK,CAAC,sCAAsC,EAAEC,gBAAW,EAAE,MAAM,CAAC;AACtE,EAAE;;AAEF;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAIC,mDAAmC;AAC1D,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5B,KAAK;AACL,IAAI,OAAO,MAAM;AACjB,EAAE;;AAEF;AACA;AACA;AACA,GAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/instrumentation.ts"],"sourcesContent":["import {\n InstrumentationBase,\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { AnthropicAiClient, AnthropicAiOptions } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n ANTHROPIC_AI_INTEGRATION_NAME,\n getClient,\n instrumentAnthropicAiClient,\n SDK_VERSION,\n} from '@sentry/core';\n\nconst supportedVersions = ['>=0.19.2 <1.0.0'];\n\ntype AnthropicAiInstrumentationOptions = InstrumentationConfig & AnthropicAiOptions;\n\n/**\n * Represents the patched shape of the Anthropic AI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n Anthropic: abstract new (...args: unknown[]) => AnthropicAiClient;\n}\n\n/**\n * Sentry Anthropic AI instrumentation using OpenTelemetry.\n */\nexport class SentryAnthropicAiInstrumentation extends InstrumentationBase<AnthropicAiInstrumentationOptions> {\n public constructor(config: AnthropicAiInstrumentationOptions = {}) {\n super('@sentry/instrumentation-anthropic-ai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@anthropic-ai/sdk',\n supportedVersions,\n this._patch.bind(this),\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Anthropic AI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.Anthropic;\n\n const config = this.getConfig();\n\n const WrappedAnthropic = function (this: unknown, ...args: unknown[]) {\n // Check if wrapping should be skipped (e.g., when LangChain is handling instrumentation)\n if (_INTERNAL_shouldSkipAiProviderWrapping(ANTHROPIC_AI_INTEGRATION_NAME)) {\n return Reflect.construct(Original, args) as AnthropicAiClient;\n }\n\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const recordInputs = config.recordInputs ?? defaultPii;\n const recordOutputs = config.recordOutputs ?? defaultPii;\n\n return instrumentAnthropicAiClient(instance as AnthropicAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => AnthropicAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedAnthropic, Original);\n Object.setPrototypeOf(WrappedAnthropic.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedAnthropic, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n try {\n exports.Anthropic = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'Anthropic', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","exports","_INTERNAL_shouldSkipAiProviderWrapping","ANTHROPIC_AI_INTEGRATION_NAME","getClient","instrumentAnthropicAiClient"],"mappings":";;;;;AAeA,MAAM,iBAAA,GAAoB,CAAC,iBAAiB,CAAC;;AAY7C;AACA;AACA;AACO,MAAM,gCAAA,SAAyCA,mCAAmB,CAAoC;AAC7G,GAAS,WAAW,CAAC,MAAM,GAAsC,EAAE,EAAE;AACrE,IAAI,KAAK,CAAC,sCAAsC,EAAEC,gBAAW,EAAE,MAAM,CAAC;AACtE,EAAE;;AAEF;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAIC,mDAAmC;AAC1D,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5B,KAAK;AACL,IAAI,OAAO,MAAM;AACjB,EAAE;;AAEF;AACA;AACA;AACA,GAAU,MAAM,CAACC,SAAO,EAAqD;AAC7E,IAAI,MAAM,QAAA,GAAWA,SAAO,CAAC,SAAS;;AAEtC,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;;AAEnC,IAAI,MAAM,mBAAmB,WAAyB,GAAG,IAAI,EAAa;AAC1E;AACA,MAAM,IAAIC,2CAAsC,CAACC,kCAA6B,CAAC,EAAE;AACjF,QAAQ,OAAO,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAA;AAC/C,MAAM;;AAEN,MAAM,MAAM,QAAA,GAAW,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC;AACxD,MAAM,MAAM,MAAA,GAASC,cAAS,EAAE;AAChC,MAAM,MAAM,UAAA,GAAa,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,cAAc,CAAC;;AAErE,MAAM,MAAM,YAAA,GAAe,MAAM,CAAC,YAAA,IAAgB,UAAU;AAC5D,MAAM,MAAM,aAAA,GAAgB,MAAM,CAAC,aAAA,IAAiB,UAAU;;AAE9D,MAAM,OAAOC,gCAA2B,CAAC,QAAA,GAA+B;AACxE,QAAQ,YAAY;AACpB,QAAQ,aAAa;AACrB,OAAO,CAAC;AACR,IAAI,CAAA;;AAEJ;AACA,IAAI,MAAM,CAAC,cAAc,CAAC,gBAAgB,EAAE,QAAQ,CAAC;AACrD,IAAI,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;;AAEzE,IAAI,KAAK,MAAM,GAAA,IAAO,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE;AAC5D,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC1D,QAAQ,MAAM,UAAA,GAAa,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,GAAG,CAAC;AACzE,QAAQ,IAAI,UAAU,EAAE;AACxB,UAAU,MAAM,CAAC,cAAc,CAAC,gBAAgB,EAAE,GAAG,EAAE,UAAU,CAAC;AAClE,QAAQ;AACR,MAAM;AACN,IAAI;;AAEJ;AACA;AACA,IAAI,IAAI;AACR,MAAMJ,SAAO,CAAC,SAAA,GAAY,gBAAgB;AAC1C,IAAI,CAAA,CAAE,OAAO,KAAK,EAAE;AACpB;AACA,MAAM,MAAM,CAAC,cAAc,CAACA,SAAO,EAAE,WAAW,EAAE;AAClD,QAAQ,KAAK,EAAE,gBAAgB;AAC/B,QAAQ,QAAQ,EAAE,IAAI;AACtB,QAAQ,YAAY,EAAE,IAAI;AAC1B,QAAQ,UAAU,EAAE,IAAI;AACxB,OAAO,CAAC;AACR,IAAI;;AAEJ;AACA;AACA;AACA,IAAI,IAAIA,SAAO,CAAC,OAAA,KAAY,QAAQ,EAAE;AACtC,MAAM,IAAI;AACV,QAAQA,SAAO,CAAC,OAAA,GAAU,gBAAgB;AAC1C,MAAM,CAAA,CAAE,OAAO,KAAK,EAAE;AACtB;AACA,QAAQ,MAAM,CAAC,cAAc,CAACA,SAAO,EAAE,SAAS,EAAE;AAClD,UAAU,KAAK,EAAE,gBAAgB;AACjC,UAAU,QAAQ,EAAE,IAAI;AACxB,UAAU,YAAY,EAAE,IAAI;AAC5B,UAAU,UAAU,EAAE,IAAI;AAC1B,SAAS,CAAC;AACV,MAAM;AACN,IAAI;AACJ,IAAI,OAAOA,SAAO;AAClB,EAAE;AACF;;;;"}
|
|
@@ -219,7 +219,7 @@ function addFastifySpanAttributes(span) {
|
|
|
219
219
|
return;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
const opPrefix = isHook ? 'hook' : isHandler ? 'middleware' : isRequestHandler ? '
|
|
222
|
+
const opPrefix = isHook ? 'hook' : isHandler ? 'middleware' : isRequestHandler ? 'request_handler' : '<unknown>';
|
|
223
223
|
|
|
224
224
|
span.setAttributes({
|
|
225
225
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.fastify',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/fastify/index.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { Instrumentation, InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getClient,\n getIsolationScope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport { FastifyOtelInstrumentation } from './fastify-otel/index';\nimport type { FastifyInstance, FastifyMinimal, FastifyReply, FastifyRequest } from './types';\nimport { FastifyInstrumentationV3 } from './v3/instrumentation';\n\n/**\n * Options for the Fastify integration.\n *\n * `shouldHandleError` - Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @example\n *\n * ```javascript\n * Sentry.init({\n * integrations: [\n * Sentry.fastifyIntegration({\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 500;\n * },\n * });\n * },\n * });\n * ```\n *\n */\ninterface FastifyIntegrationOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\ninterface FastifyHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n *\n * @example\n *\n *\n * ```javascript\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 400;\n * },\n * });\n * ```\n *\n *\n * If using TypeScript, you can cast the request and reply to get full type safety.\n *\n * ```typescript\n * import type { FastifyRequest, FastifyReply } from 'fastify';\n *\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(error, minimalRequest, minimalReply) {\n * const request = minimalRequest as FastifyRequest;\n * const reply = minimalReply as FastifyReply;\n * return reply.statusCode >= 500;\n * },\n * });\n * ```\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\nconst INTEGRATION_NAME = 'Fastify';\n\nexport const instrumentFastifyV3 = generateInstrumentOnce(\n `${INTEGRATION_NAME}.v3`,\n () => new FastifyInstrumentationV3(),\n);\n\nfunction getFastifyIntegration(): ReturnType<typeof _fastifyIntegration> | undefined {\n const client = getClient();\n if (!client) {\n return undefined;\n } else {\n return client.getIntegrationByName(INTEGRATION_NAME);\n }\n}\n\nfunction handleFastifyError(\n this: {\n diagnosticsChannelExists?: boolean;\n },\n error: Error,\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } },\n reply: FastifyReply,\n handlerOrigin: 'diagnostics-channel' | 'onError-hook',\n): void {\n const shouldHandleError = getFastifyIntegration()?.getShouldHandleError() || defaultShouldHandleError;\n // Diagnostics channel runs before the onError hook, so we can use it to check if the handler was already registered\n if (handlerOrigin === 'diagnostics-channel') {\n this.diagnosticsChannelExists = true;\n }\n\n if (this.diagnosticsChannelExists && handlerOrigin === 'onError-hook') {\n DEBUG_BUILD &&\n debug.warn(\n 'Fastify error handler was already registered via diagnostics channel.',\n 'You can safely remove `setupFastifyErrorHandler` call and set `shouldHandleError` on the integration options.',\n );\n\n // If the diagnostics channel already exists, we don't need to handle the error again\n return;\n }\n\n if (shouldHandleError(error, request, reply)) {\n captureException(error, { mechanism: { handled: false, type: 'auto.function.fastify' } });\n }\n}\n\nexport const instrumentFastify = generateInstrumentOnce(`${INTEGRATION_NAME}.v5`, () => {\n const fastifyOtelInstrumentationInstance = new FastifyOtelInstrumentation();\n const plugin = fastifyOtelInstrumentationInstance.plugin();\n\n // This message handler works for Fastify versions 3, 4 and 5\n diagnosticsChannel.subscribe('fastify.initialization', message => {\n const fastifyInstance = (message as { fastify?: FastifyInstance }).fastify;\n\n fastifyInstance?.register(plugin).after(err => {\n if (err) {\n DEBUG_BUILD && debug.error('Failed to setup Fastify instrumentation', err);\n } else {\n instrumentClient();\n\n if (fastifyInstance) {\n instrumentOnRequest(fastifyInstance);\n }\n }\n });\n });\n\n // This diagnostics channel only works on Fastify version 5\n // For versions 3 and 4, we use `setupFastifyErrorHandler` instead\n diagnosticsChannel.subscribe('tracing:fastify.request.handler:error', message => {\n const { error, request, reply } = message as {\n error: Error;\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } };\n reply: FastifyReply;\n };\n\n handleFastifyError.call(handleFastifyError, error, request, reply, 'diagnostics-channel');\n });\n\n // Returning this as unknown not to deal with the internal types of the FastifyOtelInstrumentation\n return fastifyOtelInstrumentationInstance as Instrumentation<InstrumentationConfig & FastifyIntegrationOptions>;\n});\n\nconst _fastifyIntegration = (({ shouldHandleError }: Partial<FastifyIntegrationOptions>) => {\n let _shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _shouldHandleError = shouldHandleError || defaultShouldHandleError;\n\n instrumentFastifyV3();\n instrumentFastify();\n },\n getShouldHandleError() {\n return _shouldHandleError;\n },\n setShouldHandleError(fn: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean): void {\n _shouldHandleError = fn;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Fastify](https://fastify.dev/).\n *\n * If you also want to capture errors, you need to call `setupFastifyErrorHandler(app)` after you set up your Fastify server.\n *\n * For more information, see the [fastify documentation](https://docs.sentry.io/platforms/javascript/guides/fastify/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.fastifyIntegration()],\n * })\n * ```\n */\nexport const fastifyIntegration = defineIntegration((options: Partial<FastifyIntegrationOptions> = {}) =>\n _fastifyIntegration(options),\n);\n\n/**\n * Default function to determine if an error should be sent to Sentry\n *\n * 3xx and 4xx errors are not sent by default.\n */\nfunction defaultShouldHandleError(_error: Error, _request: FastifyRequest, reply: FastifyReply): boolean {\n const statusCode = reply.statusCode;\n // 3xx and 4xx errors are not sent by default.\n return statusCode >= 500 || statusCode <= 299;\n}\n\n/**\n * Add an Fastify error handler to capture errors to Sentry.\n *\n * @param fastify The Fastify instance to which to add the error handler\n * @param options Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Fastify = require(\"fastify\");\n *\n * const app = Fastify();\n *\n * Sentry.setupFastifyErrorHandler(app);\n *\n * // Add your routes, etc.\n *\n * app.listen({ port: 3000 });\n * ```\n */\nexport function setupFastifyErrorHandler(fastify: FastifyMinimal, options?: Partial<FastifyHandlerOptions>): void {\n if (options?.shouldHandleError) {\n getFastifyIntegration()?.setShouldHandleError(options.shouldHandleError);\n }\n\n const plugin = Object.assign(\n function (fastify: FastifyInstance, _options: unknown, done: () => void): void {\n fastify.addHook('onError', async (request, reply, error) => {\n handleFastifyError.call(handleFastifyError, error, request, reply, 'onError-hook');\n });\n done();\n },\n {\n [Symbol.for('skip-override')]: true,\n [Symbol.for('fastify.display-name')]: 'sentry-fastify-error-handler',\n },\n );\n\n fastify.register(plugin);\n}\n\nfunction addFastifySpanAttributes(span: Span): void {\n const spanJSON = spanToJSON(span);\n const spanName = spanJSON.description;\n const attributes = spanJSON.data;\n\n const type = attributes['fastify.type'];\n\n const isHook = type === 'hook';\n const isHandler = type === spanName?.startsWith('handler -');\n // In @fastify/otel `request-handler` is separated by dash, not underscore\n const isRequestHandler = spanName === 'request' || type === 'request-handler';\n\n // If this is already set, or we have no fastify span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || (!isHandler && !isRequestHandler && !isHook)) {\n return;\n }\n\n const opPrefix = isHook ? 'hook' : isHandler ? 'middleware' : isRequestHandler ? 'request-handler' : '<unknown>';\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.fastify',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${opPrefix}.fastify`,\n });\n\n const attrName = attributes['fastify.name'] || attributes['plugin.name'] || attributes['hook.name'];\n if (typeof attrName === 'string') {\n // Try removing `fastify -> ` and `@fastify/otel -> ` prefixes\n // This is a bit of a hack, and not always working for all spans\n // But it's the best we can do without a proper API\n const updatedName = attrName.replace(/^fastify -> /, '').replace(/^@fastify\\/otel -> /, '');\n\n span.updateName(updatedName);\n }\n}\n\nfunction instrumentClient(): void {\n const client = getClient();\n if (client) {\n client.on('spanStart', (span: Span) => {\n addFastifySpanAttributes(span);\n });\n }\n}\n\nfunction instrumentOnRequest(fastify: FastifyInstance): void {\n fastify.addHook('onRequest', async (request: FastifyRequest & { opentelemetry?: () => { span?: Span } }, _reply) => {\n if (request.opentelemetry) {\n const { span } = request.opentelemetry();\n\n if (span) {\n addFastifySpanAttributes(span);\n }\n }\n\n const routeName = request.routeOptions?.url;\n const method = request.method || 'GET';\n\n getIsolationScope().setTransactionName(`${method} ${routeName}`);\n });\n}\n"],"names":["generateInstrumentOnce","FastifyInstrumentationV3","getClient","DEBUG_BUILD","debug","captureException","FastifyOtelInstrumentation","diagnosticsChannel","defineIntegration","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","getIsolationScope"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/fastify/index.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { Instrumentation, InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getClient,\n getIsolationScope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport { FastifyOtelInstrumentation } from './fastify-otel/index';\nimport type { FastifyInstance, FastifyMinimal, FastifyReply, FastifyRequest } from './types';\nimport { FastifyInstrumentationV3 } from './v3/instrumentation';\n\n/**\n * Options for the Fastify integration.\n *\n * `shouldHandleError` - Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @example\n *\n * ```javascript\n * Sentry.init({\n * integrations: [\n * Sentry.fastifyIntegration({\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 500;\n * },\n * });\n * },\n * });\n * ```\n *\n */\ninterface FastifyIntegrationOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\ninterface FastifyHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n *\n * @example\n *\n *\n * ```javascript\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 400;\n * },\n * });\n * ```\n *\n *\n * If using TypeScript, you can cast the request and reply to get full type safety.\n *\n * ```typescript\n * import type { FastifyRequest, FastifyReply } from 'fastify';\n *\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(error, minimalRequest, minimalReply) {\n * const request = minimalRequest as FastifyRequest;\n * const reply = minimalReply as FastifyReply;\n * return reply.statusCode >= 500;\n * },\n * });\n * ```\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\nconst INTEGRATION_NAME = 'Fastify';\n\nexport const instrumentFastifyV3 = generateInstrumentOnce(\n `${INTEGRATION_NAME}.v3`,\n () => new FastifyInstrumentationV3(),\n);\n\nfunction getFastifyIntegration(): ReturnType<typeof _fastifyIntegration> | undefined {\n const client = getClient();\n if (!client) {\n return undefined;\n } else {\n return client.getIntegrationByName(INTEGRATION_NAME);\n }\n}\n\nfunction handleFastifyError(\n this: {\n diagnosticsChannelExists?: boolean;\n },\n error: Error,\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } },\n reply: FastifyReply,\n handlerOrigin: 'diagnostics-channel' | 'onError-hook',\n): void {\n const shouldHandleError = getFastifyIntegration()?.getShouldHandleError() || defaultShouldHandleError;\n // Diagnostics channel runs before the onError hook, so we can use it to check if the handler was already registered\n if (handlerOrigin === 'diagnostics-channel') {\n this.diagnosticsChannelExists = true;\n }\n\n if (this.diagnosticsChannelExists && handlerOrigin === 'onError-hook') {\n DEBUG_BUILD &&\n debug.warn(\n 'Fastify error handler was already registered via diagnostics channel.',\n 'You can safely remove `setupFastifyErrorHandler` call and set `shouldHandleError` on the integration options.',\n );\n\n // If the diagnostics channel already exists, we don't need to handle the error again\n return;\n }\n\n if (shouldHandleError(error, request, reply)) {\n captureException(error, { mechanism: { handled: false, type: 'auto.function.fastify' } });\n }\n}\n\nexport const instrumentFastify = generateInstrumentOnce(`${INTEGRATION_NAME}.v5`, () => {\n const fastifyOtelInstrumentationInstance = new FastifyOtelInstrumentation();\n const plugin = fastifyOtelInstrumentationInstance.plugin();\n\n // This message handler works for Fastify versions 3, 4 and 5\n diagnosticsChannel.subscribe('fastify.initialization', message => {\n const fastifyInstance = (message as { fastify?: FastifyInstance }).fastify;\n\n fastifyInstance?.register(plugin).after(err => {\n if (err) {\n DEBUG_BUILD && debug.error('Failed to setup Fastify instrumentation', err);\n } else {\n instrumentClient();\n\n if (fastifyInstance) {\n instrumentOnRequest(fastifyInstance);\n }\n }\n });\n });\n\n // This diagnostics channel only works on Fastify version 5\n // For versions 3 and 4, we use `setupFastifyErrorHandler` instead\n diagnosticsChannel.subscribe('tracing:fastify.request.handler:error', message => {\n const { error, request, reply } = message as {\n error: Error;\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } };\n reply: FastifyReply;\n };\n\n handleFastifyError.call(handleFastifyError, error, request, reply, 'diagnostics-channel');\n });\n\n // Returning this as unknown not to deal with the internal types of the FastifyOtelInstrumentation\n return fastifyOtelInstrumentationInstance as Instrumentation<InstrumentationConfig & FastifyIntegrationOptions>;\n});\n\nconst _fastifyIntegration = (({ shouldHandleError }: Partial<FastifyIntegrationOptions>) => {\n let _shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _shouldHandleError = shouldHandleError || defaultShouldHandleError;\n\n instrumentFastifyV3();\n instrumentFastify();\n },\n getShouldHandleError() {\n return _shouldHandleError;\n },\n setShouldHandleError(fn: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean): void {\n _shouldHandleError = fn;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Fastify](https://fastify.dev/).\n *\n * If you also want to capture errors, you need to call `setupFastifyErrorHandler(app)` after you set up your Fastify server.\n *\n * For more information, see the [fastify documentation](https://docs.sentry.io/platforms/javascript/guides/fastify/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.fastifyIntegration()],\n * })\n * ```\n */\nexport const fastifyIntegration = defineIntegration((options: Partial<FastifyIntegrationOptions> = {}) =>\n _fastifyIntegration(options),\n);\n\n/**\n * Default function to determine if an error should be sent to Sentry\n *\n * 3xx and 4xx errors are not sent by default.\n */\nfunction defaultShouldHandleError(_error: Error, _request: FastifyRequest, reply: FastifyReply): boolean {\n const statusCode = reply.statusCode;\n // 3xx and 4xx errors are not sent by default.\n return statusCode >= 500 || statusCode <= 299;\n}\n\n/**\n * Add an Fastify error handler to capture errors to Sentry.\n *\n * @param fastify The Fastify instance to which to add the error handler\n * @param options Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Fastify = require(\"fastify\");\n *\n * const app = Fastify();\n *\n * Sentry.setupFastifyErrorHandler(app);\n *\n * // Add your routes, etc.\n *\n * app.listen({ port: 3000 });\n * ```\n */\nexport function setupFastifyErrorHandler(fastify: FastifyMinimal, options?: Partial<FastifyHandlerOptions>): void {\n if (options?.shouldHandleError) {\n getFastifyIntegration()?.setShouldHandleError(options.shouldHandleError);\n }\n\n const plugin = Object.assign(\n function (fastify: FastifyInstance, _options: unknown, done: () => void): void {\n fastify.addHook('onError', async (request, reply, error) => {\n handleFastifyError.call(handleFastifyError, error, request, reply, 'onError-hook');\n });\n done();\n },\n {\n [Symbol.for('skip-override')]: true,\n [Symbol.for('fastify.display-name')]: 'sentry-fastify-error-handler',\n },\n );\n\n fastify.register(plugin);\n}\n\nfunction addFastifySpanAttributes(span: Span): void {\n const spanJSON = spanToJSON(span);\n const spanName = spanJSON.description;\n const attributes = spanJSON.data;\n\n const type = attributes['fastify.type'];\n\n const isHook = type === 'hook';\n const isHandler = type === spanName?.startsWith('handler -');\n // In @fastify/otel `request-handler` is separated by dash, not underscore\n const isRequestHandler = spanName === 'request' || type === 'request-handler';\n\n // If this is already set, or we have no fastify span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || (!isHandler && !isRequestHandler && !isHook)) {\n return;\n }\n\n const opPrefix = isHook ? 'hook' : isHandler ? 'middleware' : isRequestHandler ? 'request_handler' : '<unknown>';\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.fastify',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${opPrefix}.fastify`,\n });\n\n const attrName = attributes['fastify.name'] || attributes['plugin.name'] || attributes['hook.name'];\n if (typeof attrName === 'string') {\n // Try removing `fastify -> ` and `@fastify/otel -> ` prefixes\n // This is a bit of a hack, and not always working for all spans\n // But it's the best we can do without a proper API\n const updatedName = attrName.replace(/^fastify -> /, '').replace(/^@fastify\\/otel -> /, '');\n\n span.updateName(updatedName);\n }\n}\n\nfunction instrumentClient(): void {\n const client = getClient();\n if (client) {\n client.on('spanStart', (span: Span) => {\n addFastifySpanAttributes(span);\n });\n }\n}\n\nfunction instrumentOnRequest(fastify: FastifyInstance): void {\n fastify.addHook('onRequest', async (request: FastifyRequest & { opentelemetry?: () => { span?: Span } }, _reply) => {\n if (request.opentelemetry) {\n const { span } = request.opentelemetry();\n\n if (span) {\n addFastifySpanAttributes(span);\n }\n }\n\n const routeName = request.routeOptions?.url;\n const method = request.method || 'GET';\n\n getIsolationScope().setTransactionName(`${method} ${routeName}`);\n });\n}\n"],"names":["generateInstrumentOnce","FastifyInstrumentationV3","getClient","DEBUG_BUILD","debug","captureException","FastifyOtelInstrumentation","diagnosticsChannel","defineIntegration","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","getIsolationScope"],"mappings":"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"}
|
|
@@ -24,8 +24,8 @@ class SentryGoogleGenAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
24
24
|
const module = new instrumentation.InstrumentationNodeModuleDefinition(
|
|
25
25
|
'@google/genai',
|
|
26
26
|
supportedVersions,
|
|
27
|
-
exports => this._patch(exports),
|
|
28
|
-
exports => exports,
|
|
27
|
+
exports$1 => this._patch(exports$1),
|
|
28
|
+
exports$1 => exports$1,
|
|
29
29
|
// In CJS, @google/genai re-exports from (dist/node/index.cjs) file.
|
|
30
30
|
// Patching only the root module sometimes misses the real implementation or
|
|
31
31
|
// gets overwritten when that file is loaded. We add a file-level patch so that
|
|
@@ -34,8 +34,8 @@ class SentryGoogleGenAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
34
34
|
new instrumentation.InstrumentationNodeModuleFile(
|
|
35
35
|
'@google/genai/dist/node/index.cjs',
|
|
36
36
|
supportedVersions,
|
|
37
|
-
exports => this._patch(exports),
|
|
38
|
-
exports => exports,
|
|
37
|
+
exports$1 => this._patch(exports$1),
|
|
38
|
+
exports$1 => exports$1,
|
|
39
39
|
),
|
|
40
40
|
],
|
|
41
41
|
);
|
|
@@ -45,12 +45,12 @@ class SentryGoogleGenAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
45
45
|
/**
|
|
46
46
|
* Core patch logic applying instrumentation to the Google GenAI client constructor.
|
|
47
47
|
*/
|
|
48
|
-
_patch(exports) {
|
|
49
|
-
const Original = exports.GoogleGenAI;
|
|
48
|
+
_patch(exports$1) {
|
|
49
|
+
const Original = exports$1.GoogleGenAI;
|
|
50
50
|
const config = this.getConfig();
|
|
51
51
|
|
|
52
52
|
if (typeof Original !== 'function') {
|
|
53
|
-
return exports;
|
|
53
|
+
return exports$1;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const WrappedGoogleGenAI = function ( ...args) {
|
|
@@ -87,9 +87,9 @@ class SentryGoogleGenAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// Replace google genai exports with the wrapped constructor
|
|
90
|
-
core.replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);
|
|
90
|
+
core.replaceExports(exports$1, 'GoogleGenAI', WrappedGoogleGenAI);
|
|
91
91
|
|
|
92
|
-
return exports;
|
|
92
|
+
return exports$1;
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/google-genai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n getClient,\n GOOGLE_GENAI_INTEGRATION_NAME,\n instrumentGoogleGenAIClient,\n replaceExports,\n SDK_VERSION,\n} from '@sentry/core';\n\nconst supportedVersions = ['>=0.10.0 <2'];\n\n/**\n * Represents the patched shape of the Google GenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n GoogleGenAI?: unknown;\n}\n\ntype GoogleGenAIInstrumentationOptions = GoogleGenAIOptions & InstrumentationConfig;\n\n/**\n * Sentry Google GenAI instrumentation using OpenTelemetry.\n */\nexport class SentryGoogleGenAiInstrumentation extends InstrumentationBase<GoogleGenAIInstrumentationOptions> {\n public constructor(config: GoogleGenAIInstrumentationOptions = {}) {\n super('@sentry/instrumentation-google-genai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@google/genai',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n // In CJS, @google/genai re-exports from (dist/node/index.cjs) file.\n // Patching only the root module sometimes misses the real implementation or\n // gets overwritten when that file is loaded. We add a file-level patch so that\n // _patch runs again on the concrete implementation\n [\n new InstrumentationNodeModuleFile(\n '@google/genai/dist/node/index.cjs',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n ),\n ],\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Google GenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.GoogleGenAI;\n const config = this.getConfig();\n\n if (typeof Original !== 'function') {\n return exports;\n }\n\n const WrappedGoogleGenAI = function (this: unknown, ...args: unknown[]): GoogleGenAIClient {\n // Check if wrapping should be skipped (e.g., when LangChain is handling instrumentation)\n if (_INTERNAL_shouldSkipAiProviderWrapping(GOOGLE_GENAI_INTEGRATION_NAME)) {\n return Reflect.construct(Original, args) as GoogleGenAIClient;\n }\n\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const typedConfig = config;\n const recordInputs = typedConfig?.recordInputs ?? defaultPii;\n const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;\n\n return instrumentGoogleGenAIClient(instance, {\n recordInputs,\n recordOutputs,\n });\n };\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedGoogleGenAI, Original);\n Object.setPrototypeOf(WrappedGoogleGenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedGoogleGenAI, key, descriptor);\n }\n }\n }\n\n // Replace google genai exports with the wrapped constructor\n replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);\n\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","_INTERNAL_shouldSkipAiProviderWrapping","GOOGLE_GENAI_INTEGRATION_NAME","getClient","instrumentGoogleGenAIClient","replaceExports"],"mappings":";;;;;AAgBA,MAAM,iBAAA,GAAoB,CAAC,aAAa,CAAC;;AAEzC;AACA;AACA;;AAQA;AACA;AACA;AACO,MAAM,gCAAA,SAAyCA,mCAAmB,CAAoC;AAC7G,GAAS,WAAW,CAAC,MAAM,GAAsC,EAAE,EAAE;AACrE,IAAI,KAAK,CAAC,sCAAsC,EAAEC,gBAAW,EAAE,MAAM,CAAC;AACtE,EAAE;;AAEF;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAIC,mDAAmC;AAC1D,MAAM,eAAe;AACrB,MAAM,iBAAiB;AACvB,
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/google-genai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';\nimport {\n _INTERNAL_shouldSkipAiProviderWrapping,\n getClient,\n GOOGLE_GENAI_INTEGRATION_NAME,\n instrumentGoogleGenAIClient,\n replaceExports,\n SDK_VERSION,\n} from '@sentry/core';\n\nconst supportedVersions = ['>=0.10.0 <2'];\n\n/**\n * Represents the patched shape of the Google GenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n GoogleGenAI?: unknown;\n}\n\ntype GoogleGenAIInstrumentationOptions = GoogleGenAIOptions & InstrumentationConfig;\n\n/**\n * Sentry Google GenAI instrumentation using OpenTelemetry.\n */\nexport class SentryGoogleGenAiInstrumentation extends InstrumentationBase<GoogleGenAIInstrumentationOptions> {\n public constructor(config: GoogleGenAIInstrumentationOptions = {}) {\n super('@sentry/instrumentation-google-genai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@google/genai',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n // In CJS, @google/genai re-exports from (dist/node/index.cjs) file.\n // Patching only the root module sometimes misses the real implementation or\n // gets overwritten when that file is loaded. We add a file-level patch so that\n // _patch runs again on the concrete implementation\n [\n new InstrumentationNodeModuleFile(\n '@google/genai/dist/node/index.cjs',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n ),\n ],\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Google GenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.GoogleGenAI;\n const config = this.getConfig();\n\n if (typeof Original !== 'function') {\n return exports;\n }\n\n const WrappedGoogleGenAI = function (this: unknown, ...args: unknown[]): GoogleGenAIClient {\n // Check if wrapping should be skipped (e.g., when LangChain is handling instrumentation)\n if (_INTERNAL_shouldSkipAiProviderWrapping(GOOGLE_GENAI_INTEGRATION_NAME)) {\n return Reflect.construct(Original, args) as GoogleGenAIClient;\n }\n\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const typedConfig = config;\n const recordInputs = typedConfig?.recordInputs ?? defaultPii;\n const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;\n\n return instrumentGoogleGenAIClient(instance, {\n recordInputs,\n recordOutputs,\n });\n };\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedGoogleGenAI, Original);\n Object.setPrototypeOf(WrappedGoogleGenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedGoogleGenAI, key, descriptor);\n }\n }\n }\n\n // Replace google genai exports with the wrapped constructor\n replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);\n\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","exports","InstrumentationNodeModuleFile","_INTERNAL_shouldSkipAiProviderWrapping","GOOGLE_GENAI_INTEGRATION_NAME","getClient","instrumentGoogleGenAIClient","replaceExports"],"mappings":"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"}
|
|
@@ -108,13 +108,13 @@ class SentryLangChainInstrumentation extends instrumentation.InstrumentationBase
|
|
|
108
108
|
packageName,
|
|
109
109
|
supportedVersions,
|
|
110
110
|
this._patch.bind(this),
|
|
111
|
-
exports => exports,
|
|
111
|
+
exports$1 => exports$1,
|
|
112
112
|
[
|
|
113
113
|
new instrumentation.InstrumentationNodeModuleFile(
|
|
114
114
|
`${packageName}/dist/index.cjs`,
|
|
115
115
|
supportedVersions,
|
|
116
116
|
this._patch.bind(this),
|
|
117
|
-
exports => exports,
|
|
117
|
+
exports$1 => exports$1,
|
|
118
118
|
),
|
|
119
119
|
],
|
|
120
120
|
),
|
|
@@ -127,14 +127,14 @@ class SentryLangChainInstrumentation extends instrumentation.InstrumentationBase
|
|
|
127
127
|
'langchain',
|
|
128
128
|
supportedVersions,
|
|
129
129
|
this._patch.bind(this),
|
|
130
|
-
exports => exports,
|
|
130
|
+
exports$1 => exports$1,
|
|
131
131
|
[
|
|
132
132
|
// To catch the CJS build that contains ConfigurableModel / initChatModel for v1
|
|
133
133
|
new instrumentation.InstrumentationNodeModuleFile(
|
|
134
134
|
'langchain/dist/chat_models/universal.cjs',
|
|
135
135
|
supportedVersions,
|
|
136
136
|
this._patch.bind(this),
|
|
137
|
-
exports => exports,
|
|
137
|
+
exports$1 => exports$1,
|
|
138
138
|
),
|
|
139
139
|
],
|
|
140
140
|
),
|
|
@@ -147,7 +147,7 @@ class SentryLangChainInstrumentation extends instrumentation.InstrumentationBase
|
|
|
147
147
|
* Core patch logic - patches chat model methods to inject Sentry callbacks
|
|
148
148
|
* This is called when a LangChain provider package is loaded
|
|
149
149
|
*/
|
|
150
|
-
_patch(exports) {
|
|
150
|
+
_patch(exports$1) {
|
|
151
151
|
// Skip AI provider wrapping now that LangChain is actually being used
|
|
152
152
|
// This prevents duplicate spans from Anthropic/OpenAI/GoogleGenAI standalone integrations
|
|
153
153
|
core._INTERNAL_skipAiProviderWrapping([
|
|
@@ -172,16 +172,16 @@ class SentryLangChainInstrumentation extends instrumentation.InstrumentationBase
|
|
|
172
172
|
|
|
173
173
|
// Patch Runnable methods to inject callbacks at request time
|
|
174
174
|
// This directly manipulates options.callbacks that LangChain uses
|
|
175
|
-
this._patchRunnableMethods(exports, sentryHandler);
|
|
175
|
+
this._patchRunnableMethods(exports$1, sentryHandler);
|
|
176
176
|
|
|
177
|
-
return exports;
|
|
177
|
+
return exports$1;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
181
|
* Patches chat model methods (invoke, stream, batch) to inject Sentry callbacks
|
|
182
182
|
* Finds a chat model class from the provider package exports and patches its prototype methods
|
|
183
183
|
*/
|
|
184
|
-
_patchRunnableMethods(exports, sentryHandler) {
|
|
184
|
+
_patchRunnableMethods(exports$1, sentryHandler) {
|
|
185
185
|
// Known chat model class names for each provider
|
|
186
186
|
const knownChatModelNames = [
|
|
187
187
|
'ChatAnthropic',
|
|
@@ -193,7 +193,7 @@ class SentryLangChainInstrumentation extends instrumentation.InstrumentationBase
|
|
|
193
193
|
'ConfigurableModel',
|
|
194
194
|
];
|
|
195
195
|
|
|
196
|
-
const exportsToPatch = (exports.universal_exports ?? exports) ;
|
|
196
|
+
const exportsToPatch = (exports$1.universal_exports ?? exports$1) ;
|
|
197
197
|
|
|
198
198
|
const chatModelClass = Object.values(exportsToPatch).find(exp => {
|
|
199
199
|
return typeof exp === 'function' && knownChatModelNames.includes(exp.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/langchain/instrumentation.ts"],"sourcesContent":["import {\n InstrumentationBase,\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { LangChainOptions } from '@sentry/core';\nimport {\n _INTERNAL_skipAiProviderWrapping,\n ANTHROPIC_AI_INTEGRATION_NAME,\n createLangChainCallbackHandler,\n getClient,\n GOOGLE_GENAI_INTEGRATION_NAME,\n OPENAI_INTEGRATION_NAME,\n SDK_VERSION,\n} from '@sentry/core';\n\nconst supportedVersions = ['>=0.1.0 <2.0.0'];\n\ntype LangChainInstrumentationOptions = InstrumentationConfig & LangChainOptions;\n\n/**\n * Represents the patched shape of LangChain provider package exports\n */\ninterface PatchedLangChainExports {\n [key: string]: unknown;\n}\n\n/**\n * Augments a callback handler list with Sentry's handler if not already present\n */\nfunction augmentCallbackHandlers(handlers: unknown, sentryHandler: unknown): unknown {\n // Handle null/undefined - return array with just our handler\n if (!handlers) {\n return [sentryHandler];\n }\n\n // If handlers is already an array\n if (Array.isArray(handlers)) {\n // Check if our handler is already in the list\n if (handlers.includes(sentryHandler)) {\n return handlers;\n }\n // Add our handler to the list\n return [...handlers, sentryHandler];\n }\n\n // If it's a single handler object, convert to array\n if (typeof handlers === 'object') {\n return [handlers, sentryHandler];\n }\n\n // Unknown type - return original\n return handlers;\n}\n\n/**\n * Wraps Runnable methods (invoke, stream, batch) to inject Sentry callbacks at request time\n * Uses a Proxy to intercept method calls and augment the options.callbacks\n */\nfunction wrapRunnableMethod(\n originalMethod: (...args: unknown[]) => unknown,\n sentryHandler: unknown,\n _methodName: string,\n): (...args: unknown[]) => unknown {\n return new Proxy(originalMethod, {\n apply(target, thisArg, args: unknown[]): unknown {\n // LangChain Runnable method signatures:\n // invoke(input, options?) - options contains callbacks\n // stream(input, options?) - options contains callbacks\n // batch(inputs, options?) - options contains callbacks\n\n // Options is typically the second argument\n const optionsIndex = 1;\n let options = args[optionsIndex] as Record<string, unknown> | undefined;\n\n // If options don't exist or aren't an object, create them\n if (!options || typeof options !== 'object' || Array.isArray(options)) {\n options = {};\n args[optionsIndex] = options;\n }\n\n // Inject our callback handler into options.callbacks (request time callbacks)\n const existingCallbacks = options.callbacks;\n const augmentedCallbacks = augmentCallbackHandlers(existingCallbacks, sentryHandler);\n options.callbacks = augmentedCallbacks;\n\n // Call original method with augmented options\n return Reflect.apply(target, thisArg, args);\n },\n }) as (...args: unknown[]) => unknown;\n}\n\n/**\n * Sentry LangChain instrumentation using OpenTelemetry.\n */\nexport class SentryLangChainInstrumentation extends InstrumentationBase<LangChainInstrumentationOptions> {\n public constructor(config: LangChainInstrumentationOptions = {}) {\n super('@sentry/instrumentation-langchain', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n * We patch the BaseChatModel class methods to inject callbacks\n *\n * We hook into provider packages (@langchain/anthropic, @langchain/openai, etc.)\n * because @langchain/core is often bundled and not loaded as a separate module\n */\n public init(): InstrumentationModuleDefinition | InstrumentationModuleDefinition[] {\n const modules: InstrumentationModuleDefinition[] = [];\n\n // Hook into common LangChain provider packages\n const providerPackages = [\n '@langchain/anthropic',\n '@langchain/openai',\n '@langchain/google-genai',\n '@langchain/mistralai',\n '@langchain/google-vertexai',\n '@langchain/groq',\n ];\n\n for (const packageName of providerPackages) {\n // In CJS, LangChain packages re-export from dist/index.cjs files.\n // Patching only the root module sometimes misses the real implementation or\n // gets overwritten when that file is loaded. We add a file-level patch so that\n // _patch runs again on the concrete implementation\n modules.push(\n new InstrumentationNodeModuleDefinition(\n packageName,\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n [\n new InstrumentationNodeModuleFile(\n `${packageName}/dist/index.cjs`,\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n ),\n ],\n ),\n );\n }\n\n // Hook into main 'langchain' package to catch initChatModel (v1+)\n modules.push(\n new InstrumentationNodeModuleDefinition(\n 'langchain',\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n [\n // To catch the CJS build that contains ConfigurableModel / initChatModel for v1\n new InstrumentationNodeModuleFile(\n 'langchain/dist/chat_models/universal.cjs',\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n ),\n ],\n ),\n );\n\n return modules;\n }\n\n /**\n * Core patch logic - patches chat model methods to inject Sentry callbacks\n * This is called when a LangChain provider package is loaded\n */\n private _patch(exports: PatchedLangChainExports): PatchedLangChainExports | void {\n // Skip AI provider wrapping now that LangChain is actually being used\n // This prevents duplicate spans from Anthropic/OpenAI/GoogleGenAI standalone integrations\n _INTERNAL_skipAiProviderWrapping([\n OPENAI_INTEGRATION_NAME,\n ANTHROPIC_AI_INTEGRATION_NAME,\n GOOGLE_GENAI_INTEGRATION_NAME,\n ]);\n\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const config = this.getConfig();\n\n const recordInputs = config?.recordInputs ?? defaultPii;\n const recordOutputs = config?.recordOutputs ?? defaultPii;\n\n // Create a shared handler instance\n const sentryHandler = createLangChainCallbackHandler({\n recordInputs,\n recordOutputs,\n });\n\n // Patch Runnable methods to inject callbacks at request time\n // This directly manipulates options.callbacks that LangChain uses\n this._patchRunnableMethods(exports, sentryHandler);\n\n return exports;\n }\n\n /**\n * Patches chat model methods (invoke, stream, batch) to inject Sentry callbacks\n * Finds a chat model class from the provider package exports and patches its prototype methods\n */\n private _patchRunnableMethods(exports: PatchedLangChainExports, sentryHandler: unknown): void {\n // Known chat model class names for each provider\n const knownChatModelNames = [\n 'ChatAnthropic',\n 'ChatOpenAI',\n 'ChatGoogleGenerativeAI',\n 'ChatMistralAI',\n 'ChatVertexAI',\n 'ChatGroq',\n 'ConfigurableModel',\n ];\n\n const exportsToPatch = (exports.universal_exports ?? exports) as Record<string, unknown>;\n\n const chatModelClass = Object.values(exportsToPatch).find(exp => {\n return typeof exp === 'function' && knownChatModelNames.includes(exp.name);\n }) as { prototype: unknown; name: string } | undefined;\n\n if (!chatModelClass) {\n return;\n }\n\n // Patch directly on chatModelClass.prototype\n const targetProto = chatModelClass.prototype as Record<string, unknown>;\n\n // Patch the methods (invoke, stream, batch)\n // All chat model instances will inherit these patched methods\n const methodsToPatch = ['invoke', 'stream', 'batch'] as const;\n\n for (const methodName of methodsToPatch) {\n const method = targetProto[methodName];\n if (typeof method === 'function') {\n targetProto[methodName] = wrapRunnableMethod(\n method as (...args: unknown[]) => unknown,\n sentryHandler,\n methodName,\n );\n }\n }\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","_INTERNAL_skipAiProviderWrapping","OPENAI_INTEGRATION_NAME","ANTHROPIC_AI_INTEGRATION_NAME","GOOGLE_GENAI_INTEGRATION_NAME","getClient","createLangChainCallbackHandler"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/langchain/instrumentation.ts"],"sourcesContent":["import {\n InstrumentationBase,\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { LangChainOptions } from '@sentry/core';\nimport {\n _INTERNAL_skipAiProviderWrapping,\n ANTHROPIC_AI_INTEGRATION_NAME,\n createLangChainCallbackHandler,\n getClient,\n GOOGLE_GENAI_INTEGRATION_NAME,\n OPENAI_INTEGRATION_NAME,\n SDK_VERSION,\n} from '@sentry/core';\n\nconst supportedVersions = ['>=0.1.0 <2.0.0'];\n\ntype LangChainInstrumentationOptions = InstrumentationConfig & LangChainOptions;\n\n/**\n * Represents the patched shape of LangChain provider package exports\n */\ninterface PatchedLangChainExports {\n [key: string]: unknown;\n}\n\n/**\n * Augments a callback handler list with Sentry's handler if not already present\n */\nfunction augmentCallbackHandlers(handlers: unknown, sentryHandler: unknown): unknown {\n // Handle null/undefined - return array with just our handler\n if (!handlers) {\n return [sentryHandler];\n }\n\n // If handlers is already an array\n if (Array.isArray(handlers)) {\n // Check if our handler is already in the list\n if (handlers.includes(sentryHandler)) {\n return handlers;\n }\n // Add our handler to the list\n return [...handlers, sentryHandler];\n }\n\n // If it's a single handler object, convert to array\n if (typeof handlers === 'object') {\n return [handlers, sentryHandler];\n }\n\n // Unknown type - return original\n return handlers;\n}\n\n/**\n * Wraps Runnable methods (invoke, stream, batch) to inject Sentry callbacks at request time\n * Uses a Proxy to intercept method calls and augment the options.callbacks\n */\nfunction wrapRunnableMethod(\n originalMethod: (...args: unknown[]) => unknown,\n sentryHandler: unknown,\n _methodName: string,\n): (...args: unknown[]) => unknown {\n return new Proxy(originalMethod, {\n apply(target, thisArg, args: unknown[]): unknown {\n // LangChain Runnable method signatures:\n // invoke(input, options?) - options contains callbacks\n // stream(input, options?) - options contains callbacks\n // batch(inputs, options?) - options contains callbacks\n\n // Options is typically the second argument\n const optionsIndex = 1;\n let options = args[optionsIndex] as Record<string, unknown> | undefined;\n\n // If options don't exist or aren't an object, create them\n if (!options || typeof options !== 'object' || Array.isArray(options)) {\n options = {};\n args[optionsIndex] = options;\n }\n\n // Inject our callback handler into options.callbacks (request time callbacks)\n const existingCallbacks = options.callbacks;\n const augmentedCallbacks = augmentCallbackHandlers(existingCallbacks, sentryHandler);\n options.callbacks = augmentedCallbacks;\n\n // Call original method with augmented options\n return Reflect.apply(target, thisArg, args);\n },\n }) as (...args: unknown[]) => unknown;\n}\n\n/**\n * Sentry LangChain instrumentation using OpenTelemetry.\n */\nexport class SentryLangChainInstrumentation extends InstrumentationBase<LangChainInstrumentationOptions> {\n public constructor(config: LangChainInstrumentationOptions = {}) {\n super('@sentry/instrumentation-langchain', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n * We patch the BaseChatModel class methods to inject callbacks\n *\n * We hook into provider packages (@langchain/anthropic, @langchain/openai, etc.)\n * because @langchain/core is often bundled and not loaded as a separate module\n */\n public init(): InstrumentationModuleDefinition | InstrumentationModuleDefinition[] {\n const modules: InstrumentationModuleDefinition[] = [];\n\n // Hook into common LangChain provider packages\n const providerPackages = [\n '@langchain/anthropic',\n '@langchain/openai',\n '@langchain/google-genai',\n '@langchain/mistralai',\n '@langchain/google-vertexai',\n '@langchain/groq',\n ];\n\n for (const packageName of providerPackages) {\n // In CJS, LangChain packages re-export from dist/index.cjs files.\n // Patching only the root module sometimes misses the real implementation or\n // gets overwritten when that file is loaded. We add a file-level patch so that\n // _patch runs again on the concrete implementation\n modules.push(\n new InstrumentationNodeModuleDefinition(\n packageName,\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n [\n new InstrumentationNodeModuleFile(\n `${packageName}/dist/index.cjs`,\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n ),\n ],\n ),\n );\n }\n\n // Hook into main 'langchain' package to catch initChatModel (v1+)\n modules.push(\n new InstrumentationNodeModuleDefinition(\n 'langchain',\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n [\n // To catch the CJS build that contains ConfigurableModel / initChatModel for v1\n new InstrumentationNodeModuleFile(\n 'langchain/dist/chat_models/universal.cjs',\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n ),\n ],\n ),\n );\n\n return modules;\n }\n\n /**\n * Core patch logic - patches chat model methods to inject Sentry callbacks\n * This is called when a LangChain provider package is loaded\n */\n private _patch(exports: PatchedLangChainExports): PatchedLangChainExports | void {\n // Skip AI provider wrapping now that LangChain is actually being used\n // This prevents duplicate spans from Anthropic/OpenAI/GoogleGenAI standalone integrations\n _INTERNAL_skipAiProviderWrapping([\n OPENAI_INTEGRATION_NAME,\n ANTHROPIC_AI_INTEGRATION_NAME,\n GOOGLE_GENAI_INTEGRATION_NAME,\n ]);\n\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const config = this.getConfig();\n\n const recordInputs = config?.recordInputs ?? defaultPii;\n const recordOutputs = config?.recordOutputs ?? defaultPii;\n\n // Create a shared handler instance\n const sentryHandler = createLangChainCallbackHandler({\n recordInputs,\n recordOutputs,\n });\n\n // Patch Runnable methods to inject callbacks at request time\n // This directly manipulates options.callbacks that LangChain uses\n this._patchRunnableMethods(exports, sentryHandler);\n\n return exports;\n }\n\n /**\n * Patches chat model methods (invoke, stream, batch) to inject Sentry callbacks\n * Finds a chat model class from the provider package exports and patches its prototype methods\n */\n private _patchRunnableMethods(exports: PatchedLangChainExports, sentryHandler: unknown): void {\n // Known chat model class names for each provider\n const knownChatModelNames = [\n 'ChatAnthropic',\n 'ChatOpenAI',\n 'ChatGoogleGenerativeAI',\n 'ChatMistralAI',\n 'ChatVertexAI',\n 'ChatGroq',\n 'ConfigurableModel',\n ];\n\n const exportsToPatch = (exports.universal_exports ?? exports) as Record<string, unknown>;\n\n const chatModelClass = Object.values(exportsToPatch).find(exp => {\n return typeof exp === 'function' && knownChatModelNames.includes(exp.name);\n }) as { prototype: unknown; name: string } | undefined;\n\n if (!chatModelClass) {\n return;\n }\n\n // Patch directly on chatModelClass.prototype\n const targetProto = chatModelClass.prototype as Record<string, unknown>;\n\n // Patch the methods (invoke, stream, batch)\n // All chat model instances will inherit these patched methods\n const methodsToPatch = ['invoke', 'stream', 'batch'] as const;\n\n for (const methodName of methodsToPatch) {\n const method = targetProto[methodName];\n if (typeof method === 'function') {\n targetProto[methodName] = wrapRunnableMethod(\n method as (...args: unknown[]) => unknown,\n sentryHandler,\n methodName,\n );\n }\n }\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","exports","InstrumentationNodeModuleFile","_INTERNAL_skipAiProviderWrapping","OPENAI_INTEGRATION_NAME","ANTHROPIC_AI_INTEGRATION_NAME","GOOGLE_GENAI_INTEGRATION_NAME","getClient","createLangChainCallbackHandler"],"mappings":"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"}
|