@sentry/node 10.25.0 → 10.27.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 +9 -7
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js +5 -0
- package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/google-genai/instrumentation.js +5 -2
- package/build/cjs/integrations/tracing/google-genai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/index.js +20 -15
- package/build/cjs/integrations/tracing/index.js.map +1 -1
- package/build/cjs/integrations/tracing/langchain/index.js +4 -0
- package/build/cjs/integrations/tracing/langchain/index.js.map +1 -1
- package/build/cjs/integrations/tracing/langchain/instrumentation.js +8 -2
- package/build/cjs/integrations/tracing/langchain/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/langgraph/index.js +93 -0
- package/build/cjs/integrations/tracing/langgraph/index.js.map +1 -0
- package/build/cjs/integrations/tracing/langgraph/instrumentation.js +78 -0
- package/build/cjs/integrations/tracing/langgraph/instrumentation.js.map +1 -0
- package/build/cjs/integrations/tracing/openai/instrumentation.js +23 -5
- package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -1
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js +6 -1
- package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/google-genai/instrumentation.js +6 -3
- package/build/esm/integrations/tracing/google-genai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/index.js +9 -4
- package/build/esm/integrations/tracing/index.js.map +1 -1
- package/build/esm/integrations/tracing/langchain/index.js +4 -0
- package/build/esm/integrations/tracing/langchain/index.js.map +1 -1
- package/build/esm/integrations/tracing/langchain/instrumentation.js +9 -3
- package/build/esm/integrations/tracing/langchain/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/langgraph/index.js +90 -0
- package/build/esm/integrations/tracing/langgraph/index.js.map +1 -0
- package/build/esm/integrations/tracing/langgraph/instrumentation.js +76 -0
- package/build/esm/integrations/tracing/langgraph/instrumentation.js.map +1 -0
- package/build/esm/integrations/tracing/openai/instrumentation.js +24 -6
- package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts.map +1 -1
- package/build/types/integrations/tracing/google-genai/instrumentation.d.ts.map +1 -1
- package/build/types/integrations/tracing/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/langchain/index.d.ts +4 -0
- package/build/types/integrations/tracing/langchain/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/langchain/instrumentation.d.ts.map +1 -1
- package/build/types/integrations/tracing/langgraph/index.d.ts +74 -0
- package/build/types/integrations/tracing/langgraph/index.d.ts.map +1 -0
- package/build/types/integrations/tracing/langgraph/instrumentation.d.ts +19 -0
- package/build/types/integrations/tracing/langgraph/instrumentation.d.ts.map +1 -0
- package/build/types/integrations/tracing/openai/instrumentation.d.ts +5 -1
- package/build/types/integrations/tracing/openai/instrumentation.d.ts.map +1 -1
- package/build/types-ts3.8/index.d.ts +1 -0
- package/build/types-ts3.8/integrations/tracing/langchain/index.d.ts +4 -0
- package/build/types-ts3.8/integrations/tracing/langgraph/index.d.ts +74 -0
- package/build/types-ts3.8/integrations/tracing/langgraph/instrumentation.d.ts +19 -0
- package/build/types-ts3.8/integrations/tracing/openai/instrumentation.d.ts +5 -1
- package/package.json +33 -33
package/build/cjs/index.js
CHANGED
|
@@ -30,15 +30,16 @@ const index$4 = require('./integrations/tracing/openai/index.js');
|
|
|
30
30
|
const index$5 = require('./integrations/tracing/anthropic-ai/index.js');
|
|
31
31
|
const index$6 = require('./integrations/tracing/google-genai/index.js');
|
|
32
32
|
const index$7 = require('./integrations/tracing/langchain/index.js');
|
|
33
|
+
const index$8 = require('./integrations/tracing/langgraph/index.js');
|
|
33
34
|
const launchDarkly = require('./integrations/featureFlagShims/launchDarkly.js');
|
|
34
35
|
const openFeature = require('./integrations/featureFlagShims/openFeature.js');
|
|
35
36
|
const statsig = require('./integrations/featureFlagShims/statsig.js');
|
|
36
37
|
const unleash = require('./integrations/featureFlagShims/unleash.js');
|
|
37
38
|
const growthbook = require('./integrations/featureFlagShims/growthbook.js');
|
|
38
39
|
const firebase = require('./integrations/tracing/firebase/firebase.js');
|
|
39
|
-
const index$
|
|
40
|
+
const index$9 = require('./sdk/index.js');
|
|
40
41
|
const initOtel = require('./sdk/initOtel.js');
|
|
41
|
-
const index$
|
|
42
|
+
const index$a = require('./integrations/tracing/index.js');
|
|
42
43
|
const opentelemetry = require('@sentry/opentelemetry');
|
|
43
44
|
const core = require('@sentry/core');
|
|
44
45
|
const nodeCore = require('@sentry/node-core');
|
|
@@ -82,6 +83,7 @@ exports.openAIIntegration = index$4.openAIIntegration;
|
|
|
82
83
|
exports.anthropicAIIntegration = index$5.anthropicAIIntegration;
|
|
83
84
|
exports.googleGenAIIntegration = index$6.googleGenAIIntegration;
|
|
84
85
|
exports.langChainIntegration = index$7.langChainIntegration;
|
|
86
|
+
exports.langGraphIntegration = index$8.langGraphIntegration;
|
|
85
87
|
exports.buildLaunchDarklyFlagUsedHandler = launchDarkly.buildLaunchDarklyFlagUsedHandlerShim;
|
|
86
88
|
exports.launchDarklyIntegration = launchDarkly.launchDarklyIntegrationShim;
|
|
87
89
|
exports.OpenFeatureIntegrationHook = openFeature.OpenFeatureIntegrationHookShim;
|
|
@@ -90,13 +92,13 @@ exports.statsigIntegration = statsig.statsigIntegrationShim;
|
|
|
90
92
|
exports.unleashIntegration = unleash.unleashIntegrationShim;
|
|
91
93
|
exports.growthbookIntegration = growthbook.growthbookIntegrationShim;
|
|
92
94
|
exports.firebaseIntegration = firebase.firebaseIntegration;
|
|
93
|
-
exports.getDefaultIntegrations = index$
|
|
94
|
-
exports.getDefaultIntegrationsWithoutPerformance = index$
|
|
95
|
-
exports.init = index$
|
|
96
|
-
exports.initWithoutDefaultIntegrations = index$
|
|
95
|
+
exports.getDefaultIntegrations = index$9.getDefaultIntegrations;
|
|
96
|
+
exports.getDefaultIntegrationsWithoutPerformance = index$9.getDefaultIntegrationsWithoutPerformance;
|
|
97
|
+
exports.init = index$9.init;
|
|
98
|
+
exports.initWithoutDefaultIntegrations = index$9.initWithoutDefaultIntegrations;
|
|
97
99
|
exports.initOpenTelemetry = initOtel.initOpenTelemetry;
|
|
98
100
|
exports.preloadOpenTelemetry = initOtel.preloadOpenTelemetry;
|
|
99
|
-
exports.getAutoPerformanceIntegrations = index$
|
|
101
|
+
exports.getAutoPerformanceIntegrations = index$a.getAutoPerformanceIntegrations;
|
|
100
102
|
exports.setNodeAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
|
|
101
103
|
exports.SDK_VERSION = core.SDK_VERSION;
|
|
102
104
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_OP = core.SEMANTIC_ATTRIBUTE_SENTRY_OP;
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -34,6 +34,11 @@ class SentryAnthropicAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
34
34
|
const config = this.getConfig();
|
|
35
35
|
|
|
36
36
|
const WrappedAnthropic = function ( ...args) {
|
|
37
|
+
// Check if wrapping should be skipped (e.g., when LangChain is handling instrumentation)
|
|
38
|
+
if (core._INTERNAL_shouldSkipAiProviderWrapping(core.ANTHROPIC_AI_INTEGRATION_NAME)) {
|
|
39
|
+
return Reflect.construct(Original, args) ;
|
|
40
|
+
}
|
|
41
|
+
|
|
37
42
|
const instance = Reflect.construct(Original, args);
|
|
38
43
|
const client = core.getClient();
|
|
39
44
|
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { AnthropicAiClient, AnthropicAiOptions } from '@sentry/core';\nimport {
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\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":"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"}
|
|
@@ -54,14 +54,17 @@ class SentryGoogleGenAiInstrumentation extends instrumentation.InstrumentationBa
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const WrappedGoogleGenAI = function ( ...args) {
|
|
57
|
+
// Check if wrapping should be skipped (e.g., when LangChain is handling instrumentation)
|
|
58
|
+
if (core._INTERNAL_shouldSkipAiProviderWrapping(core.GOOGLE_GENAI_INTEGRATION_NAME)) {
|
|
59
|
+
return Reflect.construct(Original, args) ;
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
const instance = Reflect.construct(Original, args);
|
|
58
63
|
const client = core.getClient();
|
|
59
64
|
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
|
|
60
65
|
|
|
61
66
|
const typedConfig = config;
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
63
67
|
const recordInputs = typedConfig?.recordInputs ?? defaultPii;
|
|
64
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
65
68
|
const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;
|
|
66
69
|
|
|
67
70
|
return core.instrumentGoogleGenAIClient(instance, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/google-genai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';\nimport {
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/google-genai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n type InstrumentationModuleDefinition,\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":";;;;;AAiBA,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,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACrC,MAAM,OAAA,IAAW,OAAO;AACxB;AACA;AACA;AACA;AACA,MAAM;AACN,QAAQ,IAAIC,6CAA6B;AACzC,UAAU,mCAAmC;AAC7C,UAAU,iBAAiB;AAC3B,UAAU,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACzC,UAAU,OAAA,IAAW,OAAO;AAC5B,SAAS;AACT,OAAO;AACP,KAAK;AACL,IAAI,OAAO,MAAM;AACjB,EAAE;;AAEF;AACA;AACA;AACA,GAAU,MAAM,CAAC,OAAO,EAAqD;AAC7E,IAAI,MAAM,QAAA,GAAW,OAAO,CAAC,WAAW;AACxC,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;;AAEnC,IAAI,IAAI,OAAO,QAAA,KAAa,UAAU,EAAE;AACxC,MAAM,OAAO,OAAO;AACpB,IAAI;;AAEJ,IAAI,MAAM,qBAAqB,WAAyB,GAAG,IAAI,EAAgC;AAC/F;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,WAAA,GAAc,MAAM;AAChC,MAAM,MAAM,YAAA,GAAe,WAAW,EAAE,YAAA,IAAgB,UAAU;AAClE,MAAM,MAAM,aAAA,GAAgB,WAAW,EAAE,aAAA,IAAiB,UAAU;;AAEpE,MAAM,OAAOC,gCAA2B,CAAC,QAAQ,EAAE;AACnD,QAAQ,YAAY;AACpB,QAAQ,aAAa;AACrB,OAAO,CAAC;AACR,IAAI,CAAC;;AAEL;AACA,IAAI,MAAM,CAAC,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC;AACvD,IAAI,MAAM,CAAC,cAAc,CAAC,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;;AAE3E,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,kBAAkB,EAAE,GAAG,EAAE,UAAU,CAAC;AACpE,QAAQ;AACR,MAAM;AACN,IAAI;;AAEJ;AACA,IAAIC,mBAAc,CAAC,OAAO,EAAE,aAAa,EAAE,kBAAkB,CAAC;;AAE9D,IAAI,OAAO,OAAO;AAClB,EAAE;AACF;;;;"}
|
|
@@ -2,31 +2,32 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
const http = require('../http.js');
|
|
4
4
|
const amqplib = require('./amqplib.js');
|
|
5
|
-
const index$
|
|
5
|
+
const index$6 = require('./anthropic-ai/index.js');
|
|
6
6
|
const connect = require('./connect.js');
|
|
7
7
|
const express = require('./express.js');
|
|
8
8
|
const index = require('./fastify/index.js');
|
|
9
9
|
const firebase = require('./firebase/firebase.js');
|
|
10
10
|
const genericPool = require('./genericPool.js');
|
|
11
|
-
const index$
|
|
11
|
+
const index$7 = require('./google-genai/index.js');
|
|
12
12
|
const graphql = require('./graphql.js');
|
|
13
13
|
const index$1 = require('./hapi/index.js');
|
|
14
14
|
const index$2 = require('./hono/index.js');
|
|
15
15
|
const kafka = require('./kafka.js');
|
|
16
16
|
const koa = require('./koa.js');
|
|
17
|
-
const index$
|
|
17
|
+
const index$3 = require('./langchain/index.js');
|
|
18
|
+
const index$8 = require('./langgraph/index.js');
|
|
18
19
|
const lrumemoizer = require('./lrumemoizer.js');
|
|
19
20
|
const mongo = require('./mongo.js');
|
|
20
21
|
const mongoose = require('./mongoose.js');
|
|
21
22
|
const mysql = require('./mysql.js');
|
|
22
23
|
const mysql2 = require('./mysql2.js');
|
|
23
|
-
const index$
|
|
24
|
+
const index$5 = require('./openai/index.js');
|
|
24
25
|
const postgres = require('./postgres.js');
|
|
25
26
|
const postgresjs = require('./postgresjs.js');
|
|
26
27
|
const prisma = require('./prisma.js');
|
|
27
28
|
const redis = require('./redis.js');
|
|
28
29
|
const tedious = require('./tedious.js');
|
|
29
|
-
const index$
|
|
30
|
+
const index$4 = require('./vercelai/index.js');
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.
|
|
@@ -52,13 +53,16 @@ function getAutoPerformanceIntegrations() {
|
|
|
52
53
|
kafka.kafkaIntegration(),
|
|
53
54
|
amqplib.amqplibIntegration(),
|
|
54
55
|
lrumemoizer.lruMemoizerIntegration(),
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
// AI providers
|
|
57
|
+
// LangChain must come first to disable AI provider integrations before they instrument
|
|
58
|
+
index$3.langChainIntegration(),
|
|
59
|
+
index$8.langGraphIntegration(),
|
|
60
|
+
index$4.vercelAIIntegration(),
|
|
61
|
+
index$5.openAIIntegration(),
|
|
62
|
+
index$6.anthropicAIIntegration(),
|
|
63
|
+
index$7.googleGenAIIntegration(),
|
|
57
64
|
postgresjs.postgresJsIntegration(),
|
|
58
65
|
firebase.firebaseIntegration(),
|
|
59
|
-
index$5.anthropicAIIntegration(),
|
|
60
|
-
index$6.googleGenAIIntegration(),
|
|
61
|
-
index$7.langChainIntegration(),
|
|
62
66
|
];
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -90,13 +94,14 @@ function getOpenTelemetryInstrumentationToPreload() {
|
|
|
90
94
|
tedious.instrumentTedious,
|
|
91
95
|
genericPool.instrumentGenericPool,
|
|
92
96
|
amqplib.instrumentAmqplib,
|
|
93
|
-
index$3.
|
|
94
|
-
index$4.
|
|
97
|
+
index$3.instrumentLangChain,
|
|
98
|
+
index$4.instrumentVercelAi,
|
|
99
|
+
index$5.instrumentOpenAi,
|
|
95
100
|
postgresjs.instrumentPostgresJs,
|
|
96
101
|
firebase.instrumentFirebase,
|
|
97
|
-
index$
|
|
98
|
-
index$
|
|
99
|
-
index$
|
|
102
|
+
index$6.instrumentAnthropicAi,
|
|
103
|
+
index$7.instrumentGoogleGenAI,
|
|
104
|
+
index$8.instrumentLangGraph,
|
|
100
105
|
];
|
|
101
106
|
}
|
|
102
107
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { honoIntegration, instrumentHono } from './hono';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLangChain, langChainIntegration } from './langchain';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n honoIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { honoIntegration, instrumentHono } from './hono';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLangChain, langChainIntegration } from './langchain';\nimport { instrumentLangGraph, langGraphIntegration } from './langgraph';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n honoIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n // AI providers\n // LangChain must come first to disable AI provider integrations before they instrument\n langChainIntegration(),\n langGraphIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentHono,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentLangChain,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n instrumentLangGraph,\n ];\n}\n"],"names":["expressIntegration","fastifyIntegration","graphqlIntegration","honoIntegration","mongoIntegration","mongooseIntegration","mysqlIntegration","mysql2Integration","redisIntegration","postgresIntegration","prismaIntegration","hapiIntegration","koaIntegration","connectIntegration","tediousIntegration","genericPoolIntegration","kafkaIntegration","amqplibIntegration","lruMemoizerIntegration","langChainIntegration","langGraphIntegration","vercelAIIntegration","openAIIntegration","anthropicAIIntegration","googleGenAIIntegration","postgresJsIntegration","firebaseIntegration","instrumentSentryHttp","instrumentOtelHttp","instrumentExpress","instrumentConnect","instrumentFastify","instrumentFastifyV3","instrumentHapi","instrumentHono","instrumentKafka","instrumentKoa","instrumentLruMemoizer","instrumentMongo","instrumentMongoose","instrumentMysql","instrumentMysql2","instrumentPostgres","instrumentGraphql","instrumentRedis","instrumentTedious","instrumentGenericPool","instrumentAmqplib","instrumentLangChain","instrumentVercelAi","instrumentOpenAi","instrumentPostgresJs","instrumentFirebase","instrumentAnthropicAi","instrumentGoogleGenAI","instrumentLangGraph"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAIA,0BAAkB,EAAE;AACxB,IAAIC,wBAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,kBAAc,EAAE;AACpB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B;AACA;AACA,IAAIC,4BAAoB,EAAE;AAC1B,IAAIC,4BAAoB,EAAE;AAC1B,IAAIC,2BAAmB,EAAE;AACzB,IAAIC,yBAAiB,EAAE;AACvB,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,gCAAqB,EAAE;AAC3B,IAAIC,4BAAmB,EAAE;AACzB,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAIC,yBAAoB;AACxB,IAAIC,uBAAkB;AACtB,IAAIC,yBAAiB;AACrB,IAAIC,yBAAiB;AACrB,IAAIC,uBAAiB;AACrB,IAAIC,yBAAmB;AACvB,IAAIC,sBAAc;AAClB,IAAIC,sBAAc;AAClB,IAAIC,qBAAe;AACnB,IAAIC,iBAAa;AACjB,IAAIC,iCAAqB;AACzB,IAAIC,qBAAe;AACnB,IAAIC,2BAAkB;AACtB,IAAIC,qBAAe;AACnB,IAAIC,uBAAgB;AACpB,IAAIC,2BAAkB;AACtB,IAAIT,sBAAc;AAClB,IAAIU,yBAAiB;AACrB,IAAIC,qBAAe;AACnB,IAAIC,yBAAiB;AACrB,IAAIC,iCAAqB;AACzB,IAAIC,yBAAiB;AACrB,IAAIC,2BAAmB;AACvB,IAAIC,0BAAkB;AACtB,IAAIC,wBAAgB;AACpB,IAAIC,+BAAoB;AACxB,IAAIC,2BAAkB;AACtB,IAAIC,6BAAqB;AACzB,IAAIC,6BAAqB;AACzB,IAAIC,2BAAmB;AACvB,GAAG;AACH;;;;;"}
|
|
@@ -26,6 +26,10 @@ const _langChainIntegration = ((options = {}) => {
|
|
|
26
26
|
* When configured, this integration automatically instruments LangChain runnable instances
|
|
27
27
|
* to capture telemetry data by injecting Sentry callback handlers into all LangChain calls.
|
|
28
28
|
*
|
|
29
|
+
* **Important:** This integration automatically skips wrapping the OpenAI, Anthropic, and Google GenAI
|
|
30
|
+
* providers to prevent duplicate spans when using LangChain with these AI providers.
|
|
31
|
+
* LangChain handles the instrumentation for all underlying AI providers.
|
|
32
|
+
*
|
|
29
33
|
* @example
|
|
30
34
|
* ```javascript
|
|
31
35
|
* import * as Sentry from '@sentry/node';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/langchain/index.ts"],"sourcesContent":["import type { IntegrationFn, LangChainOptions } from '@sentry/core';\nimport { defineIntegration, LANGCHAIN_INTEGRATION_NAME } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryLangChainInstrumentation } from './instrumentation';\n\nexport const instrumentLangChain = generateInstrumentOnce<LangChainOptions>(\n LANGCHAIN_INTEGRATION_NAME,\n options => new SentryLangChainInstrumentation(options),\n);\n\nconst _langChainIntegration = ((options: LangChainOptions = {}) => {\n return {\n name: LANGCHAIN_INTEGRATION_NAME,\n setupOnce() {\n instrumentLangChain(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for LangChain.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments LangChain runnable instances\n * to capture telemetry data by injecting Sentry callback handlers into all LangChain calls.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n * import { ChatOpenAI } from '@langchain/openai';\n *\n * Sentry.init({\n * integrations: [Sentry.langChainIntegration()],\n * sendDefaultPii: true, // Enable to record inputs/outputs\n * });\n *\n * // LangChain calls are automatically instrumented\n * const model = new ChatOpenAI();\n * await model.invoke(\"What is the capital of France?\");\n * ```\n *\n * ## Manual Callback Handler\n *\n * You can also manually add the Sentry callback handler alongside other callbacks:\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n * import { ChatOpenAI } from '@langchain/openai';\n *\n * const sentryHandler = Sentry.createLangChainCallbackHandler({\n * recordInputs: true,\n * recordOutputs: true\n * });\n *\n * const model = new ChatOpenAI();\n * await model.invoke(\n * \"What is the capital of France?\",\n * { callbacks: [sentryHandler, myOtherCallback] }\n * );\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record input messages/prompts (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.langChainIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.langChainIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n * ## Supported Events\n *\n * The integration captures the following LangChain lifecycle events:\n * - LLM/Chat Model: start, end, error\n * - Chain: start, end, error\n * - Tool: start, end, error\n *\n */\nexport const langChainIntegration = defineIntegration(_langChainIntegration);\n"],"names":["generateInstrumentOnce","LANGCHAIN_INTEGRATION_NAME","SentryLangChainInstrumentation","defineIntegration"],"mappings":";;;;;;AAKO,MAAM,mBAAA,GAAsBA,+BAAsB;AACzD,EAAEC,+BAA0B;AAC5B,EAAE,WAAW,IAAIC,8CAA8B,CAAC,OAAO,CAAC;AACxD;;AAEA,MAAM,qBAAA,IAAyB,CAAC,OAAO,GAAqB,EAAE,KAAK;AACnE,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,+BAA0B;AACpC,IAAI,SAAS,GAAG;AAChB,MAAM,mBAAmB,CAAC,OAAO,CAAC;AAClC,IAAI,CAAC;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,oBAAA,GAAuBE,sBAAiB,CAAC,qBAAqB;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/langchain/index.ts"],"sourcesContent":["import type { IntegrationFn, LangChainOptions } from '@sentry/core';\nimport { defineIntegration, LANGCHAIN_INTEGRATION_NAME } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryLangChainInstrumentation } from './instrumentation';\n\nexport const instrumentLangChain = generateInstrumentOnce<LangChainOptions>(\n LANGCHAIN_INTEGRATION_NAME,\n options => new SentryLangChainInstrumentation(options),\n);\n\nconst _langChainIntegration = ((options: LangChainOptions = {}) => {\n return {\n name: LANGCHAIN_INTEGRATION_NAME,\n setupOnce() {\n instrumentLangChain(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for LangChain.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments LangChain runnable instances\n * to capture telemetry data by injecting Sentry callback handlers into all LangChain calls.\n *\n * **Important:** This integration automatically skips wrapping the OpenAI, Anthropic, and Google GenAI\n * providers to prevent duplicate spans when using LangChain with these AI providers.\n * LangChain handles the instrumentation for all underlying AI providers.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n * import { ChatOpenAI } from '@langchain/openai';\n *\n * Sentry.init({\n * integrations: [Sentry.langChainIntegration()],\n * sendDefaultPii: true, // Enable to record inputs/outputs\n * });\n *\n * // LangChain calls are automatically instrumented\n * const model = new ChatOpenAI();\n * await model.invoke(\"What is the capital of France?\");\n * ```\n *\n * ## Manual Callback Handler\n *\n * You can also manually add the Sentry callback handler alongside other callbacks:\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n * import { ChatOpenAI } from '@langchain/openai';\n *\n * const sentryHandler = Sentry.createLangChainCallbackHandler({\n * recordInputs: true,\n * recordOutputs: true\n * });\n *\n * const model = new ChatOpenAI();\n * await model.invoke(\n * \"What is the capital of France?\",\n * { callbacks: [sentryHandler, myOtherCallback] }\n * );\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record input messages/prompts (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.langChainIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.langChainIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n * ## Supported Events\n *\n * The integration captures the following LangChain lifecycle events:\n * - LLM/Chat Model: start, end, error\n * - Chain: start, end, error\n * - Tool: start, end, error\n *\n */\nexport const langChainIntegration = defineIntegration(_langChainIntegration);\n"],"names":["generateInstrumentOnce","LANGCHAIN_INTEGRATION_NAME","SentryLangChainInstrumentation","defineIntegration"],"mappings":";;;;;;AAKO,MAAM,mBAAA,GAAsBA,+BAAsB;AACzD,EAAEC,+BAA0B;AAC5B,EAAE,WAAW,IAAIC,8CAA8B,CAAC,OAAO,CAAC;AACxD;;AAEA,MAAM,qBAAA,IAAyB,CAAC,OAAO,GAAqB,EAAE,KAAK;AACnE,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,+BAA0B;AACpC,IAAI,SAAS,GAAG;AAChB,MAAM,mBAAmB,CAAC,OAAO,CAAC;AAClC,IAAI,CAAC;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,oBAAA,GAAuBE,sBAAiB,CAAC,qBAAqB;;;;;"}
|
|
@@ -129,14 +129,20 @@ class SentryLangChainInstrumentation extends instrumentation.InstrumentationBase
|
|
|
129
129
|
* This is called when a LangChain provider package is loaded
|
|
130
130
|
*/
|
|
131
131
|
_patch(exports) {
|
|
132
|
+
// Skip AI provider wrapping now that LangChain is actually being used
|
|
133
|
+
// This prevents duplicate spans from Anthropic/OpenAI/GoogleGenAI standalone integrations
|
|
134
|
+
core._INTERNAL_skipAiProviderWrapping([
|
|
135
|
+
core.OPENAI_INTEGRATION_NAME,
|
|
136
|
+
core.ANTHROPIC_AI_INTEGRATION_NAME,
|
|
137
|
+
core.GOOGLE_GENAI_INTEGRATION_NAME,
|
|
138
|
+
]);
|
|
139
|
+
|
|
132
140
|
const client = core.getClient();
|
|
133
141
|
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
|
|
134
142
|
|
|
135
143
|
const config = this.getConfig();
|
|
136
144
|
|
|
137
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
138
145
|
const recordInputs = config?.recordInputs ?? defaultPii;
|
|
139
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
140
146
|
const recordOutputs = config?.recordOutputs ?? defaultPii;
|
|
141
147
|
|
|
142
148
|
// Create a shared handler instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/langchain/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { LangChainOptions } from '@sentry/core';\nimport { createLangChainCallbackHandler, getClient, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=0.1.0 <1.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 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 const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const config = this.getConfig();\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordInputs = config?.recordInputs ?? defaultPii;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\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 ];\n\n // Find a chat model class in the exports by checking known class names\n const chatModelClass = Object.values(exports).find(exp => {\n if (typeof exp !== 'function') {\n return false;\n }\n return 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","getClient","createLangChainCallbackHandler"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/langchain/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\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 <1.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 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 ];\n\n // Find a chat model class in the exports by checking known class names\n const chatModelClass = Object.values(exports).find(exp => {\n if (typeof exp !== 'function') {\n return false;\n }\n return 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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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const nodeCore = require('@sentry/node-core');
|
|
5
|
+
const instrumentation = require('./instrumentation.js');
|
|
6
|
+
|
|
7
|
+
const instrumentLangGraph = nodeCore.generateInstrumentOnce(
|
|
8
|
+
core.LANGGRAPH_INTEGRATION_NAME,
|
|
9
|
+
options => new instrumentation.SentryLangGraphInstrumentation(options),
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const _langGraphIntegration = ((options = {}) => {
|
|
13
|
+
return {
|
|
14
|
+
name: core.LANGGRAPH_INTEGRATION_NAME,
|
|
15
|
+
setupOnce() {
|
|
16
|
+
instrumentLangGraph(options);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}) ;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Adds Sentry tracing instrumentation for LangGraph.
|
|
23
|
+
*
|
|
24
|
+
* This integration is enabled by default.
|
|
25
|
+
*
|
|
26
|
+
* When configured, this integration automatically instruments LangGraph StateGraph and compiled graph instances
|
|
27
|
+
* to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```javascript
|
|
31
|
+
* import * as Sentry from '@sentry/node';
|
|
32
|
+
*
|
|
33
|
+
* Sentry.init({
|
|
34
|
+
* integrations: [Sentry.langGraphIntegration()],
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* ## Options
|
|
39
|
+
*
|
|
40
|
+
* - `recordInputs`: Whether to record input messages (default: respects `sendDefaultPii` client option)
|
|
41
|
+
* - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)
|
|
42
|
+
*
|
|
43
|
+
* ### Default Behavior
|
|
44
|
+
*
|
|
45
|
+
* By default, the integration will:
|
|
46
|
+
* - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options
|
|
47
|
+
* - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```javascript
|
|
51
|
+
* // Record inputs and outputs when sendDefaultPii is false
|
|
52
|
+
* Sentry.init({
|
|
53
|
+
* integrations: [
|
|
54
|
+
* Sentry.langGraphIntegration({
|
|
55
|
+
* recordInputs: true,
|
|
56
|
+
* recordOutputs: true
|
|
57
|
+
* })
|
|
58
|
+
* ],
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* // Never record inputs/outputs regardless of sendDefaultPii
|
|
62
|
+
* Sentry.init({
|
|
63
|
+
* sendDefaultPii: true,
|
|
64
|
+
* integrations: [
|
|
65
|
+
* Sentry.langGraphIntegration({
|
|
66
|
+
* recordInputs: false,
|
|
67
|
+
* recordOutputs: false
|
|
68
|
+
* })
|
|
69
|
+
* ],
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* ## Captured Operations
|
|
74
|
+
*
|
|
75
|
+
* The integration captures the following LangGraph operations:
|
|
76
|
+
* - **Agent Creation** (`StateGraph.compile()`) - Creates a `gen_ai.create_agent` span
|
|
77
|
+
* - **Agent Invocation** (`CompiledGraph.invoke()`) - Creates a `gen_ai.invoke_agent` span
|
|
78
|
+
*
|
|
79
|
+
* ## Captured Data
|
|
80
|
+
*
|
|
81
|
+
* When `recordInputs` and `recordOutputs` are enabled, the integration captures:
|
|
82
|
+
* - Input messages from the graph state
|
|
83
|
+
* - Output messages and LLM responses
|
|
84
|
+
* - Tool calls made during agent execution
|
|
85
|
+
* - Agent and graph names
|
|
86
|
+
* - Available tools configured in the graph
|
|
87
|
+
*
|
|
88
|
+
*/
|
|
89
|
+
const langGraphIntegration = core.defineIntegration(_langGraphIntegration);
|
|
90
|
+
|
|
91
|
+
exports.instrumentLangGraph = instrumentLangGraph;
|
|
92
|
+
exports.langGraphIntegration = langGraphIntegration;
|
|
93
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/langgraph/index.ts"],"sourcesContent":["import type { IntegrationFn, LangGraphOptions } from '@sentry/core';\nimport { defineIntegration, LANGGRAPH_INTEGRATION_NAME } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryLangGraphInstrumentation } from './instrumentation';\n\nexport const instrumentLangGraph = generateInstrumentOnce<LangGraphOptions>(\n LANGGRAPH_INTEGRATION_NAME,\n options => new SentryLangGraphInstrumentation(options),\n);\n\nconst _langGraphIntegration = ((options: LangGraphOptions = {}) => {\n return {\n name: LANGGRAPH_INTEGRATION_NAME,\n setupOnce() {\n instrumentLangGraph(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for LangGraph.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments LangGraph StateGraph and compiled graph instances\n * to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n *\n * Sentry.init({\n * integrations: [Sentry.langGraphIntegration()],\n * });\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record input messages (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.langGraphIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.langGraphIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n * ## Captured Operations\n *\n * The integration captures the following LangGraph operations:\n * - **Agent Creation** (`StateGraph.compile()`) - Creates a `gen_ai.create_agent` span\n * - **Agent Invocation** (`CompiledGraph.invoke()`) - Creates a `gen_ai.invoke_agent` span\n *\n * ## Captured Data\n *\n * When `recordInputs` and `recordOutputs` are enabled, the integration captures:\n * - Input messages from the graph state\n * - Output messages and LLM responses\n * - Tool calls made during agent execution\n * - Agent and graph names\n * - Available tools configured in the graph\n *\n */\nexport const langGraphIntegration = defineIntegration(_langGraphIntegration);\n"],"names":["generateInstrumentOnce","LANGGRAPH_INTEGRATION_NAME","SentryLangGraphInstrumentation","defineIntegration"],"mappings":";;;;;;AAKO,MAAM,mBAAA,GAAsBA,+BAAsB;AACzD,EAAEC,+BAA0B;AAC5B,EAAE,WAAW,IAAIC,8CAA8B,CAAC,OAAO,CAAC;AACxD;;AAEA,MAAM,qBAAA,IAAyB,CAAC,OAAO,GAAqB,EAAE,KAAK;AACnE,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,+BAA0B;AACpC,IAAI,SAAS,GAAG;AAChB,MAAM,mBAAmB,CAAC,OAAO,CAAC;AAClC,IAAI,CAAC;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,oBAAA,GAAuBE,sBAAiB,CAAC,qBAAqB;;;;;"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const instrumentation = require('@opentelemetry/instrumentation');
|
|
4
|
+
const core = require('@sentry/core');
|
|
5
|
+
|
|
6
|
+
const supportedVersions = ['>=0.0.0 <2.0.0'];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sentry LangGraph instrumentation using OpenTelemetry.
|
|
10
|
+
*/
|
|
11
|
+
class SentryLangGraphInstrumentation extends instrumentation.InstrumentationBase {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
super('@sentry/instrumentation-langgraph', core.SDK_VERSION, config);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initializes the instrumentation by defining the modules to be patched.
|
|
18
|
+
*/
|
|
19
|
+
init() {
|
|
20
|
+
const module = new instrumentation.InstrumentationNodeModuleDefinition(
|
|
21
|
+
'@langchain/langgraph',
|
|
22
|
+
supportedVersions,
|
|
23
|
+
this._patch.bind(this),
|
|
24
|
+
exports => exports,
|
|
25
|
+
[
|
|
26
|
+
new instrumentation.InstrumentationNodeModuleFile(
|
|
27
|
+
/**
|
|
28
|
+
* In CJS, LangGraph packages re-export from dist/index.cjs files.
|
|
29
|
+
* Patching only the root module sometimes misses the real implementation or
|
|
30
|
+
* gets overwritten when that file is loaded. We add a file-level patch so that
|
|
31
|
+
* _patch runs again on the concrete implementation
|
|
32
|
+
*/
|
|
33
|
+
'@langchain/langgraph/dist/index.cjs',
|
|
34
|
+
supportedVersions,
|
|
35
|
+
this._patch.bind(this),
|
|
36
|
+
exports => exports,
|
|
37
|
+
),
|
|
38
|
+
],
|
|
39
|
+
);
|
|
40
|
+
return module;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Core patch logic applying instrumentation to the LangGraph module.
|
|
45
|
+
*/
|
|
46
|
+
_patch(exports) {
|
|
47
|
+
const client = core.getClient();
|
|
48
|
+
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
|
|
49
|
+
|
|
50
|
+
const config = this.getConfig();
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
52
|
+
const recordInputs = config.recordInputs ?? defaultPii;
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
54
|
+
const recordOutputs = config.recordOutputs ?? defaultPii;
|
|
55
|
+
|
|
56
|
+
const options = {
|
|
57
|
+
recordInputs,
|
|
58
|
+
recordOutputs,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Patch StateGraph.compile to instrument both compile() and invoke()
|
|
62
|
+
if (exports.StateGraph && typeof exports.StateGraph === 'function') {
|
|
63
|
+
const StateGraph = exports.StateGraph
|
|
64
|
+
|
|
65
|
+
;
|
|
66
|
+
|
|
67
|
+
StateGraph.prototype.compile = core.instrumentStateGraphCompile(
|
|
68
|
+
StateGraph.prototype.compile ,
|
|
69
|
+
options,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return exports;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
exports.SentryLangGraphInstrumentation = SentryLangGraphInstrumentation;
|
|
78
|
+
//# sourceMappingURL=instrumentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/langgraph/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { CompiledGraph, LangGraphOptions } from '@sentry/core';\nimport { getClient, instrumentStateGraphCompile, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=0.0.0 <2.0.0'];\n\ntype LangGraphInstrumentationOptions = InstrumentationConfig & LangGraphOptions;\n\n/**\n * Represents the patched shape of the LangGraph module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n StateGraph?: abstract new (...args: unknown[]) => unknown;\n}\n\n/**\n * Sentry LangGraph instrumentation using OpenTelemetry.\n */\nexport class SentryLangGraphInstrumentation extends InstrumentationBase<LangGraphInstrumentationOptions> {\n public constructor(config: LangGraphInstrumentationOptions = {}) {\n super('@sentry/instrumentation-langgraph', 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 '@langchain/langgraph',\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n [\n new InstrumentationNodeModuleFile(\n /**\n * In CJS, LangGraph 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 */\n '@langchain/langgraph/dist/index.cjs',\n supportedVersions,\n this._patch.bind(this),\n exports => exports,\n ),\n ],\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the LangGraph module.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const config = this.getConfig();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordInputs = config.recordInputs ?? defaultPii;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordOutputs = config.recordOutputs ?? defaultPii;\n\n const options: LangGraphOptions = {\n recordInputs,\n recordOutputs,\n };\n\n // Patch StateGraph.compile to instrument both compile() and invoke()\n if (exports.StateGraph && typeof exports.StateGraph === 'function') {\n const StateGraph = exports.StateGraph as {\n prototype: Record<string, unknown>;\n };\n\n StateGraph.prototype.compile = instrumentStateGraphCompile(\n StateGraph.prototype.compile as (...args: unknown[]) => CompiledGraph,\n options,\n );\n }\n\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","getClient","instrumentStateGraphCompile"],"mappings":";;;;;AAUA,MAAM,iBAAA,GAAoB,CAAC,gBAAgB,CAAC;;AAY5C;AACA;AACA;AACO,MAAM,8BAAA,SAAuCA,mCAAmB,CAAkC;AACzG,GAAS,WAAW,CAAC,MAAM,GAAoC,EAAE,EAAE;AACnE,IAAI,KAAK,CAAC,mCAAmC,EAAEC,gBAAW,EAAE,MAAM,CAAC;AACnE,EAAE;;AAEF;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAIC,mDAAmC;AAC1D,MAAM,sBAAsB;AAC5B,MAAM,iBAAiB;AACvB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5B,MAAM,OAAA,IAAW,OAAO;AACxB,MAAM;AACN,QAAQ,IAAIC,6CAA6B;AACzC;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,qCAAqC;AAC/C,UAAU,iBAAiB;AAC3B,UAAU,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAChC,UAAU,OAAA,IAAW,OAAO;AAC5B,SAAS;AACT,OAAO;AACP,KAAK;AACL,IAAI,OAAO,MAAM;AACjB,EAAE;;AAEF;AACA;AACA;AACA,GAAU,MAAM,CAAC,OAAO,EAAqD;AAC7E,IAAI,MAAM,MAAA,GAASC,cAAS,EAAE;AAC9B,IAAI,MAAM,UAAA,GAAa,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,cAAc,CAAC;;AAEnE,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;AACnC;AACA,IAAI,MAAM,YAAA,GAAe,MAAM,CAAC,YAAA,IAAgB,UAAU;AAC1D;AACA,IAAI,MAAM,aAAA,GAAgB,MAAM,CAAC,aAAA,IAAiB,UAAU;;AAE5D,IAAI,MAAM,OAAO,GAAqB;AACtC,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,KAAK;;AAEL;AACA,IAAI,IAAI,OAAO,CAAC,UAAA,IAAc,OAAO,OAAO,CAAC,UAAA,KAAe,UAAU,EAAE;AACxE,MAAM,MAAM,UAAA,GAAa,OAAO,CAAC;;AAE3B;;AAEN,MAAM,UAAU,CAAC,SAAS,CAAC,OAAA,GAAUC,gCAA2B;AAChE,QAAQ,UAAU,CAAC,SAAS,CAAC,OAAA;AAC7B,QAAQ,OAAO;AACf,OAAO;AACP,IAAI;;AAEJ,IAAI,OAAO,OAAO;AAClB,EAAE;AACF;;;;"}
|