@sentry/core 10.36.0 → 10.38.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/exports.js +10 -0
- package/build/cjs/exports.js.map +1 -1
- package/build/cjs/index.js +82 -78
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/captureconsole.js +2 -2
- package/build/cjs/integrations/captureconsole.js.map +1 -1
- package/build/cjs/integrations/conversationId.js +37 -0
- package/build/cjs/integrations/conversationId.js.map +1 -0
- package/build/cjs/integrations/mcp-server/errorCapture.js +2 -2
- package/build/cjs/integrations/mcp-server/errorCapture.js.map +1 -1
- package/build/cjs/integrations/supabase.js +4 -4
- package/build/cjs/integrations/supabase.js.map +1 -1
- package/build/cjs/scope.js +20 -0
- package/build/cjs/scope.js.map +1 -1
- package/build/cjs/semanticAttributes.js +16 -0
- package/build/cjs/semanticAttributes.js.map +1 -1
- package/build/cjs/tracing/ai/gen-ai-attributes.js +51 -7
- package/build/cjs/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/cjs/tracing/ai/messageTruncation.js +26 -45
- package/build/cjs/tracing/ai/messageTruncation.js.map +1 -1
- package/build/cjs/tracing/ai/utils.js +50 -3
- package/build/cjs/tracing/ai/utils.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/index.js +3 -3
- package/build/cjs/tracing/anthropic-ai/index.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/streaming.js +3 -3
- package/build/cjs/tracing/anthropic-ai/streaming.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/utils.js +17 -6
- package/build/cjs/tracing/anthropic-ai/utils.js.map +1 -1
- package/build/cjs/tracing/google-genai/index.js +12 -5
- package/build/cjs/tracing/google-genai/index.js.map +1 -1
- package/build/cjs/tracing/google-genai/streaming.js +2 -2
- package/build/cjs/tracing/google-genai/streaming.js.map +1 -1
- package/build/cjs/tracing/langchain/index.js +9 -9
- package/build/cjs/tracing/langchain/index.js.map +1 -1
- package/build/cjs/tracing/langchain/utils.js +40 -25
- package/build/cjs/tracing/langchain/utils.js.map +1 -1
- package/build/cjs/tracing/langgraph/index.js +14 -6
- package/build/cjs/tracing/langgraph/index.js.map +1 -1
- package/build/cjs/tracing/openai/index.js +52 -14
- package/build/cjs/tracing/openai/index.js.map +1 -1
- package/build/cjs/tracing/openai/streaming.js +2 -2
- package/build/cjs/tracing/openai/streaming.js.map +1 -1
- package/build/cjs/tracing/openai/utils.js +4 -3
- package/build/cjs/tracing/openai/utils.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/constants.js +22 -0
- package/build/cjs/tracing/vercel-ai/constants.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/index.js +41 -11
- package/build/cjs/tracing/vercel-ai/index.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/utils.js +19 -5
- package/build/cjs/tracing/vercel-ai/utils.js.map +1 -1
- package/build/cjs/trpc.js +3 -3
- package/build/cjs/trpc.js.map +1 -1
- package/build/cjs/utils/aggregate-errors.js +13 -5
- package/build/cjs/utils/aggregate-errors.js.map +1 -1
- package/build/cjs/utils/exports.js +7 -7
- package/build/cjs/utils/exports.js.map +1 -1
- package/build/cjs/utils/flushIfServerless.js +2 -2
- package/build/cjs/utils/flushIfServerless.js.map +1 -1
- package/build/cjs/utils/traceData.js +2 -2
- package/build/cjs/utils/traceData.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/esm/exports.js +12 -3
- package/build/esm/exports.js.map +1 -1
- package/build/esm/feedback.js +1 -1
- package/build/esm/index.js +3 -2
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/conversationId.js +35 -0
- package/build/esm/integrations/conversationId.js.map +1 -0
- package/build/esm/integrations/moduleMetadata.js +1 -1
- package/build/esm/integrations/third-party-errors-filter.js +1 -1
- package/build/esm/logs/internal.js +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/scope.js +20 -0
- package/build/esm/scope.js.map +1 -1
- package/build/esm/semanticAttributes.js +16 -1
- package/build/esm/semanticAttributes.js.map +1 -1
- package/build/esm/tracing/ai/gen-ai-attributes.js +43 -6
- package/build/esm/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/esm/tracing/ai/messageTruncation.js +26 -45
- package/build/esm/tracing/ai/messageTruncation.js.map +1 -1
- package/build/esm/tracing/ai/utils.js +50 -4
- package/build/esm/tracing/ai/utils.js.map +1 -1
- package/build/esm/tracing/anthropic-ai/utils.js +17 -6
- package/build/esm/tracing/anthropic-ai/utils.js.map +1 -1
- package/build/esm/tracing/google-genai/index.js +11 -4
- package/build/esm/tracing/google-genai/index.js.map +1 -1
- package/build/esm/tracing/langchain/index.js +6 -6
- package/build/esm/tracing/langchain/index.js.map +1 -1
- package/build/esm/tracing/langchain/utils.js +41 -26
- package/build/esm/tracing/langchain/utils.js.map +1 -1
- package/build/esm/tracing/langgraph/index.js +12 -4
- package/build/esm/tracing/langgraph/index.js.map +1 -1
- package/build/esm/tracing/measurement.js +1 -1
- package/build/esm/tracing/openai/index.js +51 -13
- package/build/esm/tracing/openai/index.js.map +1 -1
- package/build/esm/tracing/openai/utils.js +4 -3
- package/build/esm/tracing/openai/utils.js.map +1 -1
- package/build/esm/tracing/trace.js +3 -3
- package/build/esm/tracing/vercel-ai/constants.js +20 -1
- package/build/esm/tracing/vercel-ai/constants.js.map +1 -1
- package/build/esm/tracing/vercel-ai/index.js +44 -14
- package/build/esm/tracing/vercel-ai/index.js.map +1 -1
- package/build/esm/tracing/vercel-ai/utils.js +21 -7
- package/build/esm/tracing/vercel-ai/utils.js.map +1 -1
- package/build/esm/utils/aggregate-errors.js +13 -5
- package/build/esm/utils/aggregate-errors.js.map +1 -1
- package/build/esm/utils/exports.js +7 -7
- package/build/esm/utils/exports.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/types/exports.d.ts +6 -0
- package/build/types/exports.d.ts.map +1 -1
- package/build/types/index.d.ts +2 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/conversationId.d.ts +9 -0
- package/build/types/integrations/conversationId.d.ts.map +1 -0
- package/build/types/scope.d.ts +9 -0
- package/build/types/scope.d.ts.map +1 -1
- package/build/types/semanticAttributes.d.ts +13 -0
- package/build/types/semanticAttributes.d.ts.map +1 -1
- package/build/types/tracing/ai/gen-ai-attributes.d.ts +35 -5
- package/build/types/tracing/ai/gen-ai-attributes.d.ts.map +1 -1
- package/build/types/tracing/ai/messageTruncation.d.ts.map +1 -1
- package/build/types/tracing/ai/utils.d.ts +13 -1
- package/build/types/tracing/ai/utils.d.ts.map +1 -1
- package/build/types/tracing/anthropic-ai/utils.d.ts +1 -0
- package/build/types/tracing/anthropic-ai/utils.d.ts.map +1 -1
- package/build/types/tracing/google-genai/index.d.ts.map +1 -1
- package/build/types/tracing/langchain/index.d.ts.map +1 -1
- package/build/types/tracing/langchain/utils.d.ts +4 -2
- package/build/types/tracing/langchain/utils.d.ts.map +1 -1
- package/build/types/tracing/langgraph/index.d.ts.map +1 -1
- package/build/types/tracing/openai/index.d.ts.map +1 -1
- package/build/types/tracing/openai/utils.d.ts +2 -1
- package/build/types/tracing/openai/utils.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/constants.d.ts +3 -0
- package/build/types/tracing/vercel-ai/constants.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/index.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/utils.d.ts.map +1 -1
- package/build/types/types-hoist/clientreport.d.ts +1 -1
- package/build/types/types-hoist/clientreport.d.ts.map +1 -1
- package/build/types-ts3.8/exports.d.ts +6 -0
- package/build/types-ts3.8/index.d.ts +2 -1
- package/build/types-ts3.8/integrations/conversationId.d.ts +9 -0
- package/build/types-ts3.8/scope.d.ts +9 -0
- package/build/types-ts3.8/semanticAttributes.d.ts +13 -0
- package/build/types-ts3.8/tracing/ai/gen-ai-attributes.d.ts +35 -5
- package/build/types-ts3.8/tracing/ai/utils.d.ts +13 -1
- package/build/types-ts3.8/tracing/anthropic-ai/utils.d.ts +1 -0
- package/build/types-ts3.8/tracing/langchain/utils.d.ts +4 -2
- package/build/types-ts3.8/tracing/openai/utils.d.ts +2 -1
- package/build/types-ts3.8/tracing/vercel-ai/constants.d.ts +3 -0
- package/build/types-ts3.8/types-hoist/clientreport.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const _exports = require('../../exports.js');
|
|
4
4
|
const spanstatus = require('../spanstatus.js');
|
|
5
5
|
const genAiAttributes = require('../ai/gen-ai-attributes.js');
|
|
6
6
|
const utils = require('../ai/utils.js');
|
|
@@ -15,15 +15,26 @@ function shouldInstrument(methodPath) {
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Set the messages and messages original length attributes.
|
|
18
|
+
* Extracts system instructions before truncation.
|
|
18
19
|
*/
|
|
19
20
|
function setMessagesAttribute(span, messages) {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (Array.isArray(messages) && messages.length === 0) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { systemInstructions, filteredMessages } = utils.extractSystemInstructions(messages);
|
|
26
|
+
|
|
27
|
+
if (systemInstructions) {
|
|
22
28
|
span.setAttributes({
|
|
23
|
-
[genAiAttributes.
|
|
24
|
-
[genAiAttributes.GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: length,
|
|
29
|
+
[genAiAttributes.GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE]: systemInstructions,
|
|
25
30
|
});
|
|
26
31
|
}
|
|
32
|
+
|
|
33
|
+
const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 1;
|
|
34
|
+
span.setAttributes({
|
|
35
|
+
[genAiAttributes.GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: utils.getTruncatedJsonString(filteredMessages),
|
|
36
|
+
[genAiAttributes.GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,
|
|
37
|
+
});
|
|
27
38
|
}
|
|
28
39
|
|
|
29
40
|
/**
|
|
@@ -34,7 +45,7 @@ function handleResponseError(span, response) {
|
|
|
34
45
|
if (response.error) {
|
|
35
46
|
span.setStatus({ code: spanstatus.SPAN_STATUS_ERROR, message: response.error.type || 'internal_error' });
|
|
36
47
|
|
|
37
|
-
|
|
48
|
+
_exports.captureException(response.error, {
|
|
38
49
|
mechanism: {
|
|
39
50
|
handled: false,
|
|
40
51
|
type: 'auto.ai.anthropic.anthropic_error',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../src/tracing/anthropic-ai/utils.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span } from '../../types-hoist/span';\nimport {\n
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/tracing/anthropic-ai/utils.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span } from '../../types-hoist/span';\nimport {\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { extractSystemInstructions, getTruncatedJsonString } from '../ai/utils';\nimport { ANTHROPIC_AI_INSTRUMENTED_METHODS } from './constants';\nimport type { AnthropicAiInstrumentedMethod, AnthropicAiResponse } from './types';\n\n/**\n * Check if a method path should be instrumented\n */\nexport function shouldInstrument(methodPath: string): methodPath is AnthropicAiInstrumentedMethod {\n return ANTHROPIC_AI_INSTRUMENTED_METHODS.includes(methodPath as AnthropicAiInstrumentedMethod);\n}\n\n/**\n * Set the messages and messages original length attributes.\n * Extracts system instructions before truncation.\n */\nexport function setMessagesAttribute(span: Span, messages: unknown): void {\n if (Array.isArray(messages) && messages.length === 0) {\n return;\n }\n\n const { systemInstructions, filteredMessages } = extractSystemInstructions(messages);\n\n if (systemInstructions) {\n span.setAttributes({\n [GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE]: systemInstructions,\n });\n }\n\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 1;\n span.setAttributes({\n [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: getTruncatedJsonString(filteredMessages),\n [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,\n });\n}\n\n/**\n * Capture error information from the response\n * @see https://docs.anthropic.com/en/api/errors#error-shapes\n */\nexport function handleResponseError(span: Span, response: AnthropicAiResponse): void {\n if (response.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: response.error.type || 'internal_error' });\n\n captureException(response.error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.anthropic.anthropic_error',\n },\n });\n }\n}\n\n/**\n * Include the system prompt in the messages list, if available\n */\nexport function messagesFromParams(params: Record<string, unknown>): unknown[] {\n const { system, messages, input } = params;\n\n const systemMessages = typeof system === 'string' ? [{ role: 'system', content: params.system }] : [];\n\n const inputParamMessages = Array.isArray(input) ? input : input != null ? [input] : undefined;\n\n const messagesParamMessages = Array.isArray(messages) ? messages : messages != null ? [messages] : [];\n\n const userMessages = inputParamMessages ?? messagesParamMessages;\n\n return [...systemMessages, ...userMessages];\n}\n"],"names":["ANTHROPIC_AI_INSTRUMENTED_METHODS","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","getTruncatedJsonString","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","SPAN_STATUS_ERROR","captureException"],"mappings":";;;;;;;;AAYA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,UAAU,EAAuD;AAClG,EAAE,OAAOA,2CAAiC,CAAC,QAAQ,CAAC,YAA4C;AAChG;;AAEA;AACA;AACA;AACA;AACO,SAAS,oBAAoB,CAAC,IAAI,EAAQ,QAAQ,EAAiB;AAC1E,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAA,IAAK,QAAQ,CAAC,MAAA,KAAW,CAAC,EAAE;AACxD,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,EAAE,kBAAkB,EAAE,gBAAA,KAAqBC,+BAAyB,CAAC,QAAQ,CAAC;;AAEtF,EAAE,IAAI,kBAAkB,EAAE;AAC1B,IAAI,IAAI,CAAC,aAAa,CAAC;AACvB,MAAM,CAACC,oDAAoC,GAAG,kBAAkB;AAChE,KAAK,CAAC;AACN,EAAE;;AAEF,EAAE,MAAM,cAAA,GAAiB,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAA,GAAI,gBAAgB,CAAC,MAAA,GAAS,CAAC;AACtF,EAAE,IAAI,CAAC,aAAa,CAAC;AACrB,IAAI,CAACC,+CAA+B,GAAGC,4BAAsB,CAAC,gBAAgB,CAAC;AAC/E,IAAI,CAACC,+DAA+C,GAAG,cAAc;AACrE,GAAG,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACO,SAAS,mBAAmB,CAAC,IAAI,EAAQ,QAAQ,EAA6B;AACrF,EAAE,IAAI,QAAQ,CAAC,KAAK,EAAE;AACtB,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAEC,4BAAiB,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,gBAAA,EAAkB,CAAC;;AAEjG,IAAIC,yBAAgB,CAAC,QAAQ,CAAC,KAAK,EAAE;AACrC,MAAM,SAAS,EAAE;AACjB,QAAQ,OAAO,EAAE,KAAK;AACtB,QAAQ,IAAI,EAAE,mCAAmC;AACjD,OAAO;AACP,KAAK,CAAC;AACN,EAAE;AACF;;AAEA;AACA;AACA;AACO,SAAS,kBAAkB,CAAC,MAAM,EAAsC;AAC/E,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAA,EAAM,GAAI,MAAM;;AAE5C,EAAE,MAAM,iBAAiB,OAAO,WAAW,QAAA,GAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAA,GAAI,EAAE;;AAEvG,EAAE,MAAM,qBAAqB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAA,GAAI,QAAQ,KAAA,IAAS,IAAA,GAAO,CAAC,KAAK,CAAA,GAAI,SAAS;;AAE/F,EAAE,MAAM,wBAAwB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAA,GAAI,WAAW,QAAA,IAAY,IAAA,GAAO,CAAC,QAAQ,CAAA,GAAI,EAAE;;AAEvG,EAAE,MAAM,YAAA,GAAe,kBAAA,IAAsB,qBAAqB;;AAElE,EAAE,OAAO,CAAC,GAAG,cAAc,EAAE,GAAG,YAAY,CAAC;AAC7C;;;;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const currentScopes = require('../../currentScopes.js');
|
|
4
|
-
const
|
|
4
|
+
const _exports = require('../../exports.js');
|
|
5
5
|
const semanticAttributes = require('../../semanticAttributes.js');
|
|
6
6
|
const spanstatus = require('../spanstatus.js');
|
|
7
7
|
const trace = require('../trace.js');
|
|
@@ -141,9 +141,16 @@ function addPrivateRequestAttributes(span, params) {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
if (Array.isArray(messages) && messages.length) {
|
|
144
|
+
const { systemInstructions, filteredMessages } = utils$1.extractSystemInstructions(messages);
|
|
145
|
+
|
|
146
|
+
if (systemInstructions) {
|
|
147
|
+
span.setAttribute(genAiAttributes.GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;
|
|
144
151
|
span.setAttributes({
|
|
145
|
-
[genAiAttributes.
|
|
146
|
-
[genAiAttributes.
|
|
152
|
+
[genAiAttributes.GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,
|
|
153
|
+
[genAiAttributes.GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: JSON.stringify(messageTruncation.truncateGenAiMessages(filteredMessages )),
|
|
147
154
|
});
|
|
148
155
|
}
|
|
149
156
|
}
|
|
@@ -249,7 +256,7 @@ function instrumentMethod(
|
|
|
249
256
|
return streaming.instrumentStream(stream, span, Boolean(options.recordOutputs)) ;
|
|
250
257
|
} catch (error) {
|
|
251
258
|
span.setStatus({ code: spanstatus.SPAN_STATUS_ERROR, message: 'internal_error' });
|
|
252
|
-
|
|
259
|
+
_exports.captureException(error, {
|
|
253
260
|
mechanism: {
|
|
254
261
|
handled: false,
|
|
255
262
|
type: 'auto.ai.google_genai',
|
|
@@ -277,7 +284,7 @@ function instrumentMethod(
|
|
|
277
284
|
return handleCallbackErrors.handleCallbackErrors(
|
|
278
285
|
() => target.apply(context, args),
|
|
279
286
|
error => {
|
|
280
|
-
|
|
287
|
+
_exports.captureException(error, {
|
|
281
288
|
mechanism: { handled: false, type: 'auto.ai.google_genai', data: { function: methodPath } },
|
|
282
289
|
});
|
|
283
290
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/google-genai/index.ts"],"sourcesContent":["import { getClient } from '../../currentScopes';\nimport { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpan, startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport { handleCallbackErrors } from '../../utils/handleCallbackErrors';\nimport {\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MESSAGES_ATTRIBUTE,\n GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_K_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { truncateGenAiMessages } from '../ai/messageTruncation';\nimport { buildMethodPath, getFinalOperationName, getSpanOperation } from '../ai/utils';\nimport { CHAT_PATH, CHATS_CREATE_METHOD, GOOGLE_GENAI_SYSTEM_NAME } from './constants';\nimport { instrumentStream } from './streaming';\nimport type {\n Candidate,\n ContentPart,\n GoogleGenAIIstrumentedMethod,\n GoogleGenAIOptions,\n GoogleGenAIResponse,\n} from './types';\nimport type { ContentListUnion, ContentUnion, Message, PartListUnion } from './utils';\nimport { contentUnionToMessages, isStreamingMethod, shouldInstrument } from './utils';\n\n/**\n * Extract model from parameters or chat context object\n * For chat instances, the model is available on the chat object as 'model' (older versions) or 'modelVersion' (newer versions)\n */\nexport function extractModel(params: Record<string, unknown>, context?: unknown): string {\n if ('model' in params && typeof params.model === 'string') {\n return params.model;\n }\n\n // Try to get model from chat context object (chat instance has model property)\n if (context && typeof context === 'object') {\n const contextObj = context as Record<string, unknown>;\n\n // Check for 'model' property (older versions, and streaming)\n if ('model' in contextObj && typeof contextObj.model === 'string') {\n return contextObj.model;\n }\n\n // Check for 'modelVersion' property (newer versions)\n if ('modelVersion' in contextObj && typeof contextObj.modelVersion === 'string') {\n return contextObj.modelVersion;\n }\n }\n\n return 'unknown';\n}\n\n/**\n * Extract generation config parameters\n */\nfunction extractConfigAttributes(config: Record<string, unknown>): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {};\n\n if ('temperature' in config && typeof config.temperature === 'number') {\n attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = config.temperature;\n }\n if ('topP' in config && typeof config.topP === 'number') {\n attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = config.topP;\n }\n if ('topK' in config && typeof config.topK === 'number') {\n attributes[GEN_AI_REQUEST_TOP_K_ATTRIBUTE] = config.topK;\n }\n if ('maxOutputTokens' in config && typeof config.maxOutputTokens === 'number') {\n attributes[GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE] = config.maxOutputTokens;\n }\n if ('frequencyPenalty' in config && typeof config.frequencyPenalty === 'number') {\n attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = config.frequencyPenalty;\n }\n if ('presencePenalty' in config && typeof config.presencePenalty === 'number') {\n attributes[GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE] = config.presencePenalty;\n }\n\n return attributes;\n}\n\n/**\n * Extract request attributes from method arguments\n * Builds the base attributes for span creation including system info, model, and config\n */\nfunction extractRequestAttributes(\n methodPath: string,\n params?: Record<string, unknown>,\n context?: unknown,\n): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {\n [GEN_AI_SYSTEM_ATTRIBUTE]: GOOGLE_GENAI_SYSTEM_NAME,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getFinalOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.google_genai',\n };\n\n if (params) {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel(params, context);\n\n // Extract generation config parameters\n if ('config' in params && typeof params.config === 'object' && params.config) {\n const config = params.config as Record<string, unknown>;\n Object.assign(attributes, extractConfigAttributes(config));\n\n // Extract available tools from config\n if ('tools' in config && Array.isArray(config.tools)) {\n const functionDeclarations = config.tools.flatMap(\n (tool: { functionDeclarations: unknown[] }) => tool.functionDeclarations,\n );\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = JSON.stringify(functionDeclarations);\n }\n }\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel({}, context);\n }\n\n return attributes;\n}\n\n/**\n * Add private request attributes to spans.\n * This is only recorded if recordInputs is true.\n * Handles different parameter formats for different Google GenAI methods.\n */\nfunction addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {\n const messages: Message[] = [];\n\n // config.systemInstruction: ContentUnion\n if (\n 'config' in params &&\n params.config &&\n typeof params.config === 'object' &&\n 'systemInstruction' in params.config &&\n params.config.systemInstruction\n ) {\n messages.push(...contentUnionToMessages(params.config.systemInstruction as ContentUnion, 'system'));\n }\n\n // For chats.create: history contains the conversation history\n if ('history' in params) {\n messages.push(...contentUnionToMessages(params.history as PartListUnion, 'user'));\n }\n\n // For models.generateContent: ContentListUnion\n if ('contents' in params) {\n messages.push(...contentUnionToMessages(params.contents as ContentListUnion, 'user'));\n }\n\n // For chat.sendMessage: message can be PartListUnion\n if ('message' in params) {\n messages.push(...contentUnionToMessages(params.message as PartListUnion, 'user'));\n }\n\n if (Array.isArray(messages) && messages.length) {\n span.setAttributes({\n [GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: messages.length,\n [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(truncateGenAiMessages(messages)),\n });\n }\n}\n\n/**\n * Add response attributes from the Google GenAI response\n * @see https://github.com/googleapis/js-genai/blob/v1.19.0/src/types.ts#L2313\n */\nfunction addResponseAttributes(span: Span, response: GoogleGenAIResponse, recordOutputs?: boolean): void {\n if (!response || typeof response !== 'object') return;\n\n if (response.modelVersion) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, response.modelVersion);\n }\n\n // Add usage metadata if present\n if (response.usageMetadata && typeof response.usageMetadata === 'object') {\n const usage = response.usageMetadata;\n if (typeof usage.promptTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: usage.promptTokenCount,\n });\n }\n if (typeof usage.candidatesTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: usage.candidatesTokenCount,\n });\n }\n if (typeof usage.totalTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: usage.totalTokenCount,\n });\n }\n }\n\n // Add response text if recordOutputs is enabled\n if (recordOutputs && Array.isArray(response.candidates) && response.candidates.length > 0) {\n const responseTexts = response.candidates\n .map((candidate: Candidate) => {\n if (candidate.content?.parts && Array.isArray(candidate.content.parts)) {\n return candidate.content.parts\n .map((part: ContentPart) => (typeof part.text === 'string' ? part.text : ''))\n .filter((text: string) => text.length > 0)\n .join('');\n }\n return '';\n })\n .filter((text: string) => text.length > 0);\n\n if (responseTexts.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: responseTexts.join(''),\n });\n }\n }\n\n // Add tool calls if recordOutputs is enabled\n if (recordOutputs && response.functionCalls) {\n const functionCalls = response.functionCalls;\n if (Array.isArray(functionCalls) && functionCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(functionCalls),\n });\n }\n }\n}\n\n/**\n * Instrument any async or synchronous genai method with Sentry spans\n * Handles operations like models.generateContent and chat.sendMessage and chats.create\n * @see https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/ai-agents-module/#manual-instrumentation\n */\nfunction instrumentMethod<T extends unknown[], R>(\n originalMethod: (...args: T) => R | Promise<R>,\n methodPath: GoogleGenAIIstrumentedMethod,\n context: unknown,\n options: GoogleGenAIOptions,\n): (...args: T) => R | Promise<R> {\n const isSyncCreate = methodPath === CHATS_CREATE_METHOD;\n\n return new Proxy(originalMethod, {\n apply(target, _, args: T): R | Promise<R> {\n const params = args[0] as Record<string, unknown> | undefined;\n const requestAttributes = extractRequestAttributes(methodPath, params, context);\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const operationName = getFinalOperationName(methodPath);\n\n // Check if this is a streaming method\n if (isStreamingMethod(methodPath)) {\n // Use startSpanManual for streaming methods to control span lifecycle\n return startSpanManual(\n {\n name: `${operationName} ${model} stream-response`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n async (span: Span) => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const stream = await target.apply(context, args);\n return instrumentStream(stream, span, Boolean(options.recordOutputs)) as R;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.google_genai',\n data: { function: methodPath },\n },\n });\n span.end();\n throw error;\n }\n },\n );\n }\n // Single span for both sync and async operations\n return startSpan(\n {\n name: isSyncCreate ? `${operationName} ${model} create` : `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n (span: Span) => {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n\n return handleCallbackErrors(\n () => target.apply(context, args),\n error => {\n captureException(error, {\n mechanism: { handled: false, type: 'auto.ai.google_genai', data: { function: methodPath } },\n });\n },\n () => {},\n result => {\n // Only add response attributes for content-producing methods, not for chats.create\n if (!isSyncCreate) {\n addResponseAttributes(span, result, options.recordOutputs);\n }\n },\n );\n },\n );\n },\n }) as (...args: T) => R | Promise<R>;\n}\n\n/**\n * Create a deep proxy for Google GenAI client instrumentation\n * Recursively instruments methods and handles special cases like chats.create\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: GoogleGenAIOptions): T {\n return new Proxy(target, {\n get: (t, prop, receiver) => {\n const value = Reflect.get(t, prop, receiver);\n const methodPath = buildMethodPath(currentPath, String(prop));\n\n if (typeof value === 'function' && shouldInstrument(methodPath)) {\n // Special case: chats.create is synchronous but needs both instrumentation AND result proxying\n if (methodPath === CHATS_CREATE_METHOD) {\n const instrumentedMethod = instrumentMethod(value as (...args: unknown[]) => unknown, methodPath, t, options);\n return function instrumentedAndProxiedCreate(...args: unknown[]): unknown {\n const result = instrumentedMethod(...args);\n // If the result is an object (like a chat instance), proxy it too\n if (result && typeof result === 'object') {\n return createDeepProxy(result, CHAT_PATH, options);\n }\n return result;\n };\n }\n\n return instrumentMethod(value as (...args: unknown[]) => Promise<unknown>, methodPath, t, options);\n }\n\n if (typeof value === 'function') {\n // Bind non-instrumented functions to preserve the original `this` context\n return value.bind(t);\n }\n\n if (value && typeof value === 'object') {\n return createDeepProxy(value, methodPath, options);\n }\n\n return value;\n },\n });\n}\n\n/**\n * Instrument a Google GenAI client with Sentry tracing\n * Can be used across Node.js, Cloudflare Workers, and Vercel Edge\n *\n * @template T - The type of the client that extends client object\n * @param client - The Google GenAI client to instrument\n * @param options - Optional configuration for recording inputs and outputs\n * @returns The instrumented client with the same type as the input\n *\n * @example\n * ```typescript\n * import { GoogleGenAI } from '@google/genai';\n * import { instrumentGoogleGenAIClient } from '@sentry/core';\n *\n * const genAI = new GoogleGenAI({ apiKey: process.env.GOOGLE_GENAI_API_KEY });\n * const instrumentedClient = instrumentGoogleGenAIClient(genAI);\n *\n * // Now both chats.create and sendMessage will be instrumented\n * const chat = instrumentedClient.chats.create({ model: 'gemini-1.5-pro' });\n * const response = await chat.sendMessage({ message: 'Hello' });\n * ```\n */\nexport function instrumentGoogleGenAIClient<T extends object>(client: T, options?: GoogleGenAIOptions): T {\n const sendDefaultPii = Boolean(getClient()?.getOptions().sendDefaultPii);\n\n const _options = {\n recordInputs: sendDefaultPii,\n recordOutputs: sendDefaultPii,\n ...options,\n };\n return createDeepProxy(client, '', _options);\n}\n"],"names":["GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_TOP_K_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_SYSTEM_ATTRIBUTE","GOOGLE_GENAI_SYSTEM_NAME","GEN_AI_OPERATION_NAME_ATTRIBUTE","getFinalOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","contentUnionToMessages","GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","GEN_AI_REQUEST_MESSAGES_ATTRIBUTE","truncateGenAiMessages","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","CHATS_CREATE_METHOD","isStreamingMethod","startSpanManual","getSpanOperation","instrumentStream","SPAN_STATUS_ERROR","captureException","startSpan","handleCallbackErrors","buildMethodPath","shouldInstrument","CHAT_PATH","getClient"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/google-genai/index.ts"],"sourcesContent":["import { getClient } from '../../currentScopes';\nimport { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpan, startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport { handleCallbackErrors } from '../../utils/handleCallbackErrors';\nimport {\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_K_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { truncateGenAiMessages } from '../ai/messageTruncation';\nimport { buildMethodPath, extractSystemInstructions, getFinalOperationName, getSpanOperation } from '../ai/utils';\nimport { CHAT_PATH, CHATS_CREATE_METHOD, GOOGLE_GENAI_SYSTEM_NAME } from './constants';\nimport { instrumentStream } from './streaming';\nimport type {\n Candidate,\n ContentPart,\n GoogleGenAIIstrumentedMethod,\n GoogleGenAIOptions,\n GoogleGenAIResponse,\n} from './types';\nimport type { ContentListUnion, ContentUnion, Message, PartListUnion } from './utils';\nimport { contentUnionToMessages, isStreamingMethod, shouldInstrument } from './utils';\n\n/**\n * Extract model from parameters or chat context object\n * For chat instances, the model is available on the chat object as 'model' (older versions) or 'modelVersion' (newer versions)\n */\nexport function extractModel(params: Record<string, unknown>, context?: unknown): string {\n if ('model' in params && typeof params.model === 'string') {\n return params.model;\n }\n\n // Try to get model from chat context object (chat instance has model property)\n if (context && typeof context === 'object') {\n const contextObj = context as Record<string, unknown>;\n\n // Check for 'model' property (older versions, and streaming)\n if ('model' in contextObj && typeof contextObj.model === 'string') {\n return contextObj.model;\n }\n\n // Check for 'modelVersion' property (newer versions)\n if ('modelVersion' in contextObj && typeof contextObj.modelVersion === 'string') {\n return contextObj.modelVersion;\n }\n }\n\n return 'unknown';\n}\n\n/**\n * Extract generation config parameters\n */\nfunction extractConfigAttributes(config: Record<string, unknown>): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {};\n\n if ('temperature' in config && typeof config.temperature === 'number') {\n attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = config.temperature;\n }\n if ('topP' in config && typeof config.topP === 'number') {\n attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = config.topP;\n }\n if ('topK' in config && typeof config.topK === 'number') {\n attributes[GEN_AI_REQUEST_TOP_K_ATTRIBUTE] = config.topK;\n }\n if ('maxOutputTokens' in config && typeof config.maxOutputTokens === 'number') {\n attributes[GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE] = config.maxOutputTokens;\n }\n if ('frequencyPenalty' in config && typeof config.frequencyPenalty === 'number') {\n attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = config.frequencyPenalty;\n }\n if ('presencePenalty' in config && typeof config.presencePenalty === 'number') {\n attributes[GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE] = config.presencePenalty;\n }\n\n return attributes;\n}\n\n/**\n * Extract request attributes from method arguments\n * Builds the base attributes for span creation including system info, model, and config\n */\nfunction extractRequestAttributes(\n methodPath: string,\n params?: Record<string, unknown>,\n context?: unknown,\n): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {\n [GEN_AI_SYSTEM_ATTRIBUTE]: GOOGLE_GENAI_SYSTEM_NAME,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getFinalOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.google_genai',\n };\n\n if (params) {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel(params, context);\n\n // Extract generation config parameters\n if ('config' in params && typeof params.config === 'object' && params.config) {\n const config = params.config as Record<string, unknown>;\n Object.assign(attributes, extractConfigAttributes(config));\n\n // Extract available tools from config\n if ('tools' in config && Array.isArray(config.tools)) {\n const functionDeclarations = config.tools.flatMap(\n (tool: { functionDeclarations: unknown[] }) => tool.functionDeclarations,\n );\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = JSON.stringify(functionDeclarations);\n }\n }\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel({}, context);\n }\n\n return attributes;\n}\n\n/**\n * Add private request attributes to spans.\n * This is only recorded if recordInputs is true.\n * Handles different parameter formats for different Google GenAI methods.\n */\nfunction addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {\n const messages: Message[] = [];\n\n // config.systemInstruction: ContentUnion\n if (\n 'config' in params &&\n params.config &&\n typeof params.config === 'object' &&\n 'systemInstruction' in params.config &&\n params.config.systemInstruction\n ) {\n messages.push(...contentUnionToMessages(params.config.systemInstruction as ContentUnion, 'system'));\n }\n\n // For chats.create: history contains the conversation history\n if ('history' in params) {\n messages.push(...contentUnionToMessages(params.history as PartListUnion, 'user'));\n }\n\n // For models.generateContent: ContentListUnion\n if ('contents' in params) {\n messages.push(...contentUnionToMessages(params.contents as ContentListUnion, 'user'));\n }\n\n // For chat.sendMessage: message can be PartListUnion\n if ('message' in params) {\n messages.push(...contentUnionToMessages(params.message as PartListUnion, 'user'));\n }\n\n if (Array.isArray(messages) && messages.length) {\n const { systemInstructions, filteredMessages } = extractSystemInstructions(messages);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n span.setAttributes({\n [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,\n [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: JSON.stringify(truncateGenAiMessages(filteredMessages as unknown[])),\n });\n }\n}\n\n/**\n * Add response attributes from the Google GenAI response\n * @see https://github.com/googleapis/js-genai/blob/v1.19.0/src/types.ts#L2313\n */\nfunction addResponseAttributes(span: Span, response: GoogleGenAIResponse, recordOutputs?: boolean): void {\n if (!response || typeof response !== 'object') return;\n\n if (response.modelVersion) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, response.modelVersion);\n }\n\n // Add usage metadata if present\n if (response.usageMetadata && typeof response.usageMetadata === 'object') {\n const usage = response.usageMetadata;\n if (typeof usage.promptTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: usage.promptTokenCount,\n });\n }\n if (typeof usage.candidatesTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: usage.candidatesTokenCount,\n });\n }\n if (typeof usage.totalTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: usage.totalTokenCount,\n });\n }\n }\n\n // Add response text if recordOutputs is enabled\n if (recordOutputs && Array.isArray(response.candidates) && response.candidates.length > 0) {\n const responseTexts = response.candidates\n .map((candidate: Candidate) => {\n if (candidate.content?.parts && Array.isArray(candidate.content.parts)) {\n return candidate.content.parts\n .map((part: ContentPart) => (typeof part.text === 'string' ? part.text : ''))\n .filter((text: string) => text.length > 0)\n .join('');\n }\n return '';\n })\n .filter((text: string) => text.length > 0);\n\n if (responseTexts.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: responseTexts.join(''),\n });\n }\n }\n\n // Add tool calls if recordOutputs is enabled\n if (recordOutputs && response.functionCalls) {\n const functionCalls = response.functionCalls;\n if (Array.isArray(functionCalls) && functionCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(functionCalls),\n });\n }\n }\n}\n\n/**\n * Instrument any async or synchronous genai method with Sentry spans\n * Handles operations like models.generateContent and chat.sendMessage and chats.create\n * @see https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/ai-agents-module/#manual-instrumentation\n */\nfunction instrumentMethod<T extends unknown[], R>(\n originalMethod: (...args: T) => R | Promise<R>,\n methodPath: GoogleGenAIIstrumentedMethod,\n context: unknown,\n options: GoogleGenAIOptions,\n): (...args: T) => R | Promise<R> {\n const isSyncCreate = methodPath === CHATS_CREATE_METHOD;\n\n return new Proxy(originalMethod, {\n apply(target, _, args: T): R | Promise<R> {\n const params = args[0] as Record<string, unknown> | undefined;\n const requestAttributes = extractRequestAttributes(methodPath, params, context);\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const operationName = getFinalOperationName(methodPath);\n\n // Check if this is a streaming method\n if (isStreamingMethod(methodPath)) {\n // Use startSpanManual for streaming methods to control span lifecycle\n return startSpanManual(\n {\n name: `${operationName} ${model} stream-response`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n async (span: Span) => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const stream = await target.apply(context, args);\n return instrumentStream(stream, span, Boolean(options.recordOutputs)) as R;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.google_genai',\n data: { function: methodPath },\n },\n });\n span.end();\n throw error;\n }\n },\n );\n }\n // Single span for both sync and async operations\n return startSpan(\n {\n name: isSyncCreate ? `${operationName} ${model} create` : `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n (span: Span) => {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n\n return handleCallbackErrors(\n () => target.apply(context, args),\n error => {\n captureException(error, {\n mechanism: { handled: false, type: 'auto.ai.google_genai', data: { function: methodPath } },\n });\n },\n () => {},\n result => {\n // Only add response attributes for content-producing methods, not for chats.create\n if (!isSyncCreate) {\n addResponseAttributes(span, result, options.recordOutputs);\n }\n },\n );\n },\n );\n },\n }) as (...args: T) => R | Promise<R>;\n}\n\n/**\n * Create a deep proxy for Google GenAI client instrumentation\n * Recursively instruments methods and handles special cases like chats.create\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: GoogleGenAIOptions): T {\n return new Proxy(target, {\n get: (t, prop, receiver) => {\n const value = Reflect.get(t, prop, receiver);\n const methodPath = buildMethodPath(currentPath, String(prop));\n\n if (typeof value === 'function' && shouldInstrument(methodPath)) {\n // Special case: chats.create is synchronous but needs both instrumentation AND result proxying\n if (methodPath === CHATS_CREATE_METHOD) {\n const instrumentedMethod = instrumentMethod(value as (...args: unknown[]) => unknown, methodPath, t, options);\n return function instrumentedAndProxiedCreate(...args: unknown[]): unknown {\n const result = instrumentedMethod(...args);\n // If the result is an object (like a chat instance), proxy it too\n if (result && typeof result === 'object') {\n return createDeepProxy(result, CHAT_PATH, options);\n }\n return result;\n };\n }\n\n return instrumentMethod(value as (...args: unknown[]) => Promise<unknown>, methodPath, t, options);\n }\n\n if (typeof value === 'function') {\n // Bind non-instrumented functions to preserve the original `this` context\n return value.bind(t);\n }\n\n if (value && typeof value === 'object') {\n return createDeepProxy(value, methodPath, options);\n }\n\n return value;\n },\n });\n}\n\n/**\n * Instrument a Google GenAI client with Sentry tracing\n * Can be used across Node.js, Cloudflare Workers, and Vercel Edge\n *\n * @template T - The type of the client that extends client object\n * @param client - The Google GenAI client to instrument\n * @param options - Optional configuration for recording inputs and outputs\n * @returns The instrumented client with the same type as the input\n *\n * @example\n * ```typescript\n * import { GoogleGenAI } from '@google/genai';\n * import { instrumentGoogleGenAIClient } from '@sentry/core';\n *\n * const genAI = new GoogleGenAI({ apiKey: process.env.GOOGLE_GENAI_API_KEY });\n * const instrumentedClient = instrumentGoogleGenAIClient(genAI);\n *\n * // Now both chats.create and sendMessage will be instrumented\n * const chat = instrumentedClient.chats.create({ model: 'gemini-1.5-pro' });\n * const response = await chat.sendMessage({ message: 'Hello' });\n * ```\n */\nexport function instrumentGoogleGenAIClient<T extends object>(client: T, options?: GoogleGenAIOptions): T {\n const sendDefaultPii = Boolean(getClient()?.getOptions().sendDefaultPii);\n\n const _options = {\n recordInputs: sendDefaultPii,\n recordOutputs: sendDefaultPii,\n ...options,\n };\n return createDeepProxy(client, '', _options);\n}\n"],"names":["GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_TOP_K_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_SYSTEM_ATTRIBUTE","GOOGLE_GENAI_SYSTEM_NAME","GEN_AI_OPERATION_NAME_ATTRIBUTE","getFinalOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","contentUnionToMessages","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","truncateGenAiMessages","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","CHATS_CREATE_METHOD","isStreamingMethod","startSpanManual","getSpanOperation","instrumentStream","SPAN_STATUS_ERROR","captureException","startSpan","handleCallbackErrors","buildMethodPath","shouldInstrument","CHAT_PATH","getClient"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const _exports = require('../../exports.js');
|
|
4
4
|
const spanstatus = require('../spanstatus.js');
|
|
5
5
|
const genAiAttributes = require('../ai/gen-ai-attributes.js');
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ function isErrorChunk(chunk, span) {
|
|
|
19
19
|
if (feedback?.blockReason) {
|
|
20
20
|
const message = feedback.blockReasonMessage ?? feedback.blockReason;
|
|
21
21
|
span.setStatus({ code: spanstatus.SPAN_STATUS_ERROR, message: `Content blocked: ${message}` });
|
|
22
|
-
|
|
22
|
+
_exports.captureException(`Content blocked: ${message}`, {
|
|
23
23
|
mechanism: { handled: false, type: 'auto.ai.google_genai' },
|
|
24
24
|
});
|
|
25
25
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.js","sources":["../../../../src/tracing/google-genai/streaming.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_STREAMING_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport type { GoogleGenAIResponse } from './types';\n\n/**\n * State object used to accumulate information from a stream of Google GenAI events.\n */\ninterface StreamingState {\n /** Collected response text fragments (for output recording). */\n responseTexts: string[];\n /** Reasons for finishing the response, as reported by the API. */\n finishReasons: string[];\n /** The response ID. */\n responseId?: string;\n /** The model name. */\n responseModel?: string;\n /** Number of prompt/input tokens used. */\n promptTokens?: number;\n /** Number of completion/output tokens used. */\n completionTokens?: number;\n /** Number of total tokens used. */\n totalTokens?: number;\n /** Accumulated tool calls (finalized) */\n toolCalls: Array<Record<string, unknown>>;\n}\n\n/**\n * Checks if a response chunk contains an error\n * @param chunk - The response chunk to check\n * @param span - The span to update if error is found\n * @returns Whether an error occurred\n */\nfunction isErrorChunk(chunk: GoogleGenAIResponse, span: Span): boolean {\n const feedback = chunk?.promptFeedback;\n if (feedback?.blockReason) {\n const message = feedback.blockReasonMessage ?? feedback.blockReason;\n span.setStatus({ code: SPAN_STATUS_ERROR, message: `Content blocked: ${message}` });\n captureException(`Content blocked: ${message}`, {\n mechanism: { handled: false, type: 'auto.ai.google_genai' },\n });\n return true;\n }\n return false;\n}\n\n/**\n * Processes response metadata from a chunk\n * @param chunk - The response chunk to process\n * @param state - The state of the streaming process\n */\nfunction handleResponseMetadata(chunk: GoogleGenAIResponse, state: StreamingState): void {\n if (typeof chunk.responseId === 'string') state.responseId = chunk.responseId;\n if (typeof chunk.modelVersion === 'string') state.responseModel = chunk.modelVersion;\n\n const usage = chunk.usageMetadata;\n if (usage) {\n if (typeof usage.promptTokenCount === 'number') state.promptTokens = usage.promptTokenCount;\n if (typeof usage.candidatesTokenCount === 'number') state.completionTokens = usage.candidatesTokenCount;\n if (typeof usage.totalTokenCount === 'number') state.totalTokens = usage.totalTokenCount;\n }\n}\n\n/**\n * Processes candidate content from a response chunk\n * @param chunk - The response chunk to process\n * @param state - The state of the streaming process\n * @param recordOutputs - Whether to record outputs\n */\nfunction handleCandidateContent(chunk: GoogleGenAIResponse, state: StreamingState, recordOutputs: boolean): void {\n if (Array.isArray(chunk.functionCalls)) {\n state.toolCalls.push(...chunk.functionCalls);\n }\n\n for (const candidate of chunk.candidates ?? []) {\n if (candidate?.finishReason && !state.finishReasons.includes(candidate.finishReason)) {\n state.finishReasons.push(candidate.finishReason);\n }\n\n for (const part of candidate?.content?.parts ?? []) {\n if (recordOutputs && part.text) state.responseTexts.push(part.text);\n if (part.functionCall) {\n state.toolCalls.push({\n type: 'function',\n id: part.functionCall.id,\n name: part.functionCall.name,\n arguments: part.functionCall.args,\n });\n }\n }\n }\n}\n\n/**\n * Processes a single chunk from the Google GenAI stream\n * @param chunk - The chunk to process\n * @param state - The state of the streaming process\n * @param recordOutputs - Whether to record outputs\n * @param span - The span to update\n */\nfunction processChunk(chunk: GoogleGenAIResponse, state: StreamingState, recordOutputs: boolean, span: Span): void {\n if (!chunk || isErrorChunk(chunk, span)) return;\n handleResponseMetadata(chunk, state);\n handleCandidateContent(chunk, state, recordOutputs);\n}\n\n/**\n * Instruments an async iterable stream of Google GenAI response chunks, updates the span with\n * streaming attributes and (optionally) the aggregated output text, and yields\n * each chunk from the input stream unchanged.\n */\nexport async function* instrumentStream(\n stream: AsyncIterable<GoogleGenAIResponse>,\n span: Span,\n recordOutputs: boolean,\n): AsyncGenerator<GoogleGenAIResponse, void, unknown> {\n const state: StreamingState = {\n responseTexts: [],\n finishReasons: [],\n toolCalls: [],\n };\n\n try {\n for await (const chunk of stream) {\n processChunk(chunk, state, recordOutputs, span);\n yield chunk;\n }\n } finally {\n const attrs: Record<string, SpanAttributeValue> = {\n [GEN_AI_RESPONSE_STREAMING_ATTRIBUTE]: true,\n };\n\n if (state.responseId) attrs[GEN_AI_RESPONSE_ID_ATTRIBUTE] = state.responseId;\n if (state.responseModel) attrs[GEN_AI_RESPONSE_MODEL_ATTRIBUTE] = state.responseModel;\n if (state.promptTokens !== undefined) attrs[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = state.promptTokens;\n if (state.completionTokens !== undefined) attrs[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = state.completionTokens;\n if (state.totalTokens !== undefined) attrs[GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE] = state.totalTokens;\n\n if (state.finishReasons.length) {\n attrs[GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE] = JSON.stringify(state.finishReasons);\n }\n if (recordOutputs && state.responseTexts.length) {\n attrs[GEN_AI_RESPONSE_TEXT_ATTRIBUTE] = state.responseTexts.join('');\n }\n if (recordOutputs && state.toolCalls.length) {\n attrs[GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE] = JSON.stringify(state.toolCalls);\n }\n\n span.setAttributes(attrs);\n span.end();\n }\n}\n"],"names":["SPAN_STATUS_ERROR","captureException","GEN_AI_RESPONSE_STREAMING_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"streaming.js","sources":["../../../../src/tracing/google-genai/streaming.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_STREAMING_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport type { GoogleGenAIResponse } from './types';\n\n/**\n * State object used to accumulate information from a stream of Google GenAI events.\n */\ninterface StreamingState {\n /** Collected response text fragments (for output recording). */\n responseTexts: string[];\n /** Reasons for finishing the response, as reported by the API. */\n finishReasons: string[];\n /** The response ID. */\n responseId?: string;\n /** The model name. */\n responseModel?: string;\n /** Number of prompt/input tokens used. */\n promptTokens?: number;\n /** Number of completion/output tokens used. */\n completionTokens?: number;\n /** Number of total tokens used. */\n totalTokens?: number;\n /** Accumulated tool calls (finalized) */\n toolCalls: Array<Record<string, unknown>>;\n}\n\n/**\n * Checks if a response chunk contains an error\n * @param chunk - The response chunk to check\n * @param span - The span to update if error is found\n * @returns Whether an error occurred\n */\nfunction isErrorChunk(chunk: GoogleGenAIResponse, span: Span): boolean {\n const feedback = chunk?.promptFeedback;\n if (feedback?.blockReason) {\n const message = feedback.blockReasonMessage ?? feedback.blockReason;\n span.setStatus({ code: SPAN_STATUS_ERROR, message: `Content blocked: ${message}` });\n captureException(`Content blocked: ${message}`, {\n mechanism: { handled: false, type: 'auto.ai.google_genai' },\n });\n return true;\n }\n return false;\n}\n\n/**\n * Processes response metadata from a chunk\n * @param chunk - The response chunk to process\n * @param state - The state of the streaming process\n */\nfunction handleResponseMetadata(chunk: GoogleGenAIResponse, state: StreamingState): void {\n if (typeof chunk.responseId === 'string') state.responseId = chunk.responseId;\n if (typeof chunk.modelVersion === 'string') state.responseModel = chunk.modelVersion;\n\n const usage = chunk.usageMetadata;\n if (usage) {\n if (typeof usage.promptTokenCount === 'number') state.promptTokens = usage.promptTokenCount;\n if (typeof usage.candidatesTokenCount === 'number') state.completionTokens = usage.candidatesTokenCount;\n if (typeof usage.totalTokenCount === 'number') state.totalTokens = usage.totalTokenCount;\n }\n}\n\n/**\n * Processes candidate content from a response chunk\n * @param chunk - The response chunk to process\n * @param state - The state of the streaming process\n * @param recordOutputs - Whether to record outputs\n */\nfunction handleCandidateContent(chunk: GoogleGenAIResponse, state: StreamingState, recordOutputs: boolean): void {\n if (Array.isArray(chunk.functionCalls)) {\n state.toolCalls.push(...chunk.functionCalls);\n }\n\n for (const candidate of chunk.candidates ?? []) {\n if (candidate?.finishReason && !state.finishReasons.includes(candidate.finishReason)) {\n state.finishReasons.push(candidate.finishReason);\n }\n\n for (const part of candidate?.content?.parts ?? []) {\n if (recordOutputs && part.text) state.responseTexts.push(part.text);\n if (part.functionCall) {\n state.toolCalls.push({\n type: 'function',\n id: part.functionCall.id,\n name: part.functionCall.name,\n arguments: part.functionCall.args,\n });\n }\n }\n }\n}\n\n/**\n * Processes a single chunk from the Google GenAI stream\n * @param chunk - The chunk to process\n * @param state - The state of the streaming process\n * @param recordOutputs - Whether to record outputs\n * @param span - The span to update\n */\nfunction processChunk(chunk: GoogleGenAIResponse, state: StreamingState, recordOutputs: boolean, span: Span): void {\n if (!chunk || isErrorChunk(chunk, span)) return;\n handleResponseMetadata(chunk, state);\n handleCandidateContent(chunk, state, recordOutputs);\n}\n\n/**\n * Instruments an async iterable stream of Google GenAI response chunks, updates the span with\n * streaming attributes and (optionally) the aggregated output text, and yields\n * each chunk from the input stream unchanged.\n */\nexport async function* instrumentStream(\n stream: AsyncIterable<GoogleGenAIResponse>,\n span: Span,\n recordOutputs: boolean,\n): AsyncGenerator<GoogleGenAIResponse, void, unknown> {\n const state: StreamingState = {\n responseTexts: [],\n finishReasons: [],\n toolCalls: [],\n };\n\n try {\n for await (const chunk of stream) {\n processChunk(chunk, state, recordOutputs, span);\n yield chunk;\n }\n } finally {\n const attrs: Record<string, SpanAttributeValue> = {\n [GEN_AI_RESPONSE_STREAMING_ATTRIBUTE]: true,\n };\n\n if (state.responseId) attrs[GEN_AI_RESPONSE_ID_ATTRIBUTE] = state.responseId;\n if (state.responseModel) attrs[GEN_AI_RESPONSE_MODEL_ATTRIBUTE] = state.responseModel;\n if (state.promptTokens !== undefined) attrs[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = state.promptTokens;\n if (state.completionTokens !== undefined) attrs[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = state.completionTokens;\n if (state.totalTokens !== undefined) attrs[GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE] = state.totalTokens;\n\n if (state.finishReasons.length) {\n attrs[GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE] = JSON.stringify(state.finishReasons);\n }\n if (recordOutputs && state.responseTexts.length) {\n attrs[GEN_AI_RESPONSE_TEXT_ATTRIBUTE] = state.responseTexts.join('');\n }\n if (recordOutputs && state.toolCalls.length) {\n attrs[GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE] = JSON.stringify(state.toolCalls);\n }\n\n span.setAttributes(attrs);\n span.end();\n }\n}\n"],"names":["SPAN_STATUS_ERROR","captureException","GEN_AI_RESPONSE_STREAMING_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE"],"mappings":";;;;;;AAgBA;AACA;AACA;;AAoBA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,YAAY,CAAC,KAAK,EAAuB,IAAI,EAAiB;AACvE,EAAE,MAAM,QAAA,GAAW,KAAK,EAAE,cAAc;AACxC,EAAE,IAAI,QAAQ,EAAE,WAAW,EAAE;AAC7B,IAAI,MAAM,UAAU,QAAQ,CAAC,kBAAA,IAAsB,QAAQ,CAAC,WAAW;AACvE,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAEA,4BAAiB,EAAE,OAAO,EAAE,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA,EAAA,CAAA;AACA,IAAAC,yBAAA,CAAA,CAAA,iBAAA,EAAA,OAAA,CAAA,CAAA,EAAA;AACA,MAAA,SAAA,EAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,sBAAA,EAAA;AACA,KAAA,CAAA;AACA,IAAA,OAAA,IAAA;AACA,EAAA;AACA,EAAA,OAAA,KAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAA,sBAAA,CAAA,KAAA,EAAA,KAAA,EAAA;AACA,EAAA,IAAA,OAAA,KAAA,CAAA,UAAA,KAAA,QAAA,EAAA,KAAA,CAAA,UAAA,GAAA,KAAA,CAAA,UAAA;AACA,EAAA,IAAA,OAAA,KAAA,CAAA,YAAA,KAAA,QAAA,EAAA,KAAA,CAAA,aAAA,GAAA,KAAA,CAAA,YAAA;;AAEA,EAAA,MAAA,KAAA,GAAA,KAAA,CAAA,aAAA;AACA,EAAA,IAAA,KAAA,EAAA;AACA,IAAA,IAAA,OAAA,KAAA,CAAA,gBAAA,KAAA,QAAA,EAAA,KAAA,CAAA,YAAA,GAAA,KAAA,CAAA,gBAAA;AACA,IAAA,IAAA,OAAA,KAAA,CAAA,oBAAA,KAAA,QAAA,EAAA,KAAA,CAAA,gBAAA,GAAA,KAAA,CAAA,oBAAA;AACA,IAAA,IAAA,OAAA,KAAA,CAAA,eAAA,KAAA,QAAA,EAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,eAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,sBAAA,CAAA,KAAA,EAAA,KAAA,EAAA,aAAA,EAAA;AACA,EAAA,IAAA,KAAA,CAAA,OAAA,CAAA,KAAA,CAAA,aAAA,CAAA,EAAA;AACA,IAAA,KAAA,CAAA,SAAA,CAAA,IAAA,CAAA,GAAA,KAAA,CAAA,aAAA,CAAA;AACA,EAAA;;AAEA,EAAA,KAAA,MAAA,SAAA,IAAA,KAAA,CAAA,UAAA,IAAA,EAAA,EAAA;AACA,IAAA,IAAA,SAAA,EAAA,YAAA,IAAA,CAAA,KAAA,CAAA,aAAA,CAAA,QAAA,CAAA,SAAA,CAAA,YAAA,CAAA,EAAA;AACA,MAAA,KAAA,CAAA,aAAA,CAAA,IAAA,CAAA,SAAA,CAAA,YAAA,CAAA;AACA,IAAA;;AAEA,IAAA,KAAA,MAAA,IAAA,IAAA,SAAA,EAAA,OAAA,EAAA,KAAA,IAAA,EAAA,EAAA;AACA,MAAA,IAAA,aAAA,IAAA,IAAA,CAAA,IAAA,EAAA,KAAA,CAAA,aAAA,CAAA,IAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,YAAA,EAAA;AACA,QAAA,KAAA,CAAA,SAAA,CAAA,IAAA,CAAA;AACA,UAAA,IAAA,EAAA,UAAA;AACA,UAAA,EAAA,EAAA,IAAA,CAAA,YAAA,CAAA,EAAA;AACA,UAAA,IAAA,EAAA,IAAA,CAAA,YAAA,CAAA,IAAA;AACA,UAAA,SAAA,EAAA,IAAA,CAAA,YAAA,CAAA,IAAA;AACA,SAAA,CAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,YAAA,CAAA,KAAA,EAAA,KAAA,EAAA,aAAA,EAAA,IAAA,EAAA;AACA,EAAA,IAAA,CAAA,KAAA,IAAA,YAAA,CAAA,KAAA,EAAA,IAAA,CAAA,EAAA;AACA,EAAA,sBAAA,CAAA,KAAA,EAAA,KAAA,CAAA;AACA,EAAA,sBAAA,CAAA,KAAA,EAAA,KAAA,EAAA,aAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAA,gBAAA;AACA,EAAA,MAAA;AACA,EAAA,IAAA;AACA,EAAA,aAAA;AACA,EAAA;AACA,EAAA,MAAA,KAAA,GAAA;AACA,IAAA,aAAA,EAAA,EAAA;AACA,IAAA,aAAA,EAAA,EAAA;AACA,IAAA,SAAA,EAAA,EAAA;AACA,GAAA;;AAEA,EAAA,IAAA;AACA,IAAA,WAAA,MAAA,KAAA,IAAA,MAAA,EAAA;AACA,MAAA,YAAA,CAAA,KAAA,EAAA,KAAA,EAAA,aAAA,EAAA,IAAA,CAAA;AACA,MAAA,MAAA,KAAA;AACA,IAAA;AACA,EAAA,CAAA,SAAA;AACA,IAAA,MAAA,KAAA,GAAA;AACA,MAAA,CAAAC,mDAAA,GAAA,IAAA;AACA,KAAA;;AAEA,IAAA,IAAA,KAAA,CAAA,UAAA,EAAA,KAAA,CAAAC,4CAAA,CAAA,GAAA,KAAA,CAAA,UAAA;AACA,IAAA,IAAA,KAAA,CAAA,aAAA,EAAA,KAAA,CAAAC,+CAAA,CAAA,GAAA,KAAA,CAAA,aAAA;AACA,IAAA,IAAA,KAAA,CAAA,YAAA,KAAA,SAAA,EAAA,KAAA,CAAAC,mDAAA,CAAA,GAAA,KAAA,CAAA,YAAA;AACA,IAAA,IAAA,KAAA,CAAA,gBAAA,KAAA,SAAA,EAAA,KAAA,CAAAC,oDAAA,CAAA,GAAA,KAAA,CAAA,gBAAA;AACA,IAAA,IAAA,KAAA,CAAA,WAAA,KAAA,SAAA,EAAA,KAAA,CAAAC,mDAAA,CAAA,GAAA,KAAA,CAAA,WAAA;;AAEA,IAAA,IAAA,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AACA,MAAA,KAAA,CAAAC,wDAAA,CAAA,GAAA,IAAA,CAAA,SAAA,CAAA,KAAA,CAAA,aAAA,CAAA;AACA,IAAA;AACA,IAAA,IAAA,aAAA,IAAA,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AACA,MAAA,KAAA,CAAAC,8CAAA,CAAA,GAAA,KAAA,CAAA,aAAA,CAAA,IAAA,CAAA,EAAA,CAAA;AACA,IAAA;AACA,IAAA,IAAA,aAAA,IAAA,KAAA,CAAA,SAAA,CAAA,MAAA,EAAA;AACA,MAAA,KAAA,CAAAC,oDAAA,CAAA,GAAA,IAAA,CAAA,SAAA,CAAA,KAAA,CAAA,SAAA,CAAA;AACA,IAAA;;AAEA,IAAA,IAAA,CAAA,aAAA,CAAA,KAAA,CAAA;AACA,IAAA,IAAA,CAAA,GAAA,EAAA;AACA,EAAA;AACA;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const _exports = require('../../exports.js');
|
|
4
4
|
const semanticAttributes = require('../../semanticAttributes.js');
|
|
5
5
|
const spanstatus = require('../spanstatus.js');
|
|
6
6
|
const trace = require('../trace.js');
|
|
@@ -81,10 +81,10 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
81
81
|
trace.startSpanManual(
|
|
82
82
|
{
|
|
83
83
|
name: `${operationName} ${modelName}`,
|
|
84
|
-
op: 'gen_ai.
|
|
84
|
+
op: 'gen_ai.chat',
|
|
85
85
|
attributes: {
|
|
86
86
|
...attributes,
|
|
87
|
-
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.
|
|
87
|
+
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',
|
|
88
88
|
},
|
|
89
89
|
},
|
|
90
90
|
span => {
|
|
@@ -158,7 +158,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
158
158
|
exitSpan(runId);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
_exports.captureException(error, {
|
|
162
162
|
mechanism: {
|
|
163
163
|
handled: false,
|
|
164
164
|
type: `${constants.LANGCHAIN_ORIGIN}.llm_error_handler`,
|
|
@@ -217,7 +217,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
217
217
|
exitSpan(runId);
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
_exports.captureException(error, {
|
|
221
221
|
mechanism: {
|
|
222
222
|
handled: false,
|
|
223
223
|
type: `${constants.LANGCHAIN_ORIGIN}.chain_error_handler`,
|
|
@@ -230,12 +230,12 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
230
230
|
const toolName = tool.name || 'unknown_tool';
|
|
231
231
|
const attributes = {
|
|
232
232
|
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: constants.LANGCHAIN_ORIGIN,
|
|
233
|
-
|
|
233
|
+
[genAiAttributes.GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,
|
|
234
234
|
};
|
|
235
235
|
|
|
236
236
|
// Add input if recordInputs is enabled
|
|
237
237
|
if (recordInputs) {
|
|
238
|
-
attributes[
|
|
238
|
+
attributes[genAiAttributes.GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
trace.startSpanManual(
|
|
@@ -261,7 +261,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
261
261
|
// Add output if recordOutputs is enabled
|
|
262
262
|
if (recordOutputs) {
|
|
263
263
|
span.setAttributes({
|
|
264
|
-
|
|
264
|
+
[genAiAttributes.GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: JSON.stringify(output),
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
exitSpan(runId);
|
|
@@ -276,7 +276,7 @@ function createLangChainCallbackHandler(options = {}) {
|
|
|
276
276
|
exitSpan(runId);
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
|
|
279
|
+
_exports.captureException(error, {
|
|
280
280
|
mechanism: {
|
|
281
281
|
handled: false,
|
|
282
282
|
type: `${constants.LANGCHAIN_ORIGIN}.tool_error_handler`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/langchain/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport { GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_MODEL_ATTRIBUTE } from '../ai/gen-ai-attributes';\nimport { LANGCHAIN_ORIGIN } from './constants';\nimport type {\n LangChainCallbackHandler,\n LangChainLLMResult,\n LangChainMessage,\n LangChainOptions,\n LangChainSerialized,\n} from './types';\nimport {\n extractChatModelRequestAttributes,\n extractLLMRequestAttributes,\n extractLlmResponseAttributes,\n getInvocationParams,\n} from './utils';\n\n/**\n * Creates a Sentry callback handler for LangChain\n * Returns a plain object that LangChain will call via duck-typing\n *\n * This is a stateful handler that tracks spans across multiple LangChain executions.\n */\nexport function createLangChainCallbackHandler(options: LangChainOptions = {}): LangChainCallbackHandler {\n const recordInputs = options.recordInputs ?? false;\n const recordOutputs = options.recordOutputs ?? false;\n\n // Internal state - single instance tracks all spans\n const spanMap = new Map<string, Span>();\n\n /**\n * Exit a span and clean up\n */\n const exitSpan = (runId: string): void => {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.end();\n spanMap.delete(runId);\n }\n };\n\n /**\n * Handler for LLM Start\n * This handler will be called by LangChain's callback handler when an LLM event is detected.\n */\n const handler: LangChainCallbackHandler = {\n // Required LangChain BaseCallbackHandler properties\n lc_serializable: false,\n lc_namespace: ['langchain_core', 'callbacks', 'sentry'],\n lc_secrets: undefined,\n lc_attributes: undefined,\n lc_aliases: undefined,\n lc_serializable_keys: undefined,\n lc_id: ['langchain_core', 'callbacks', 'sentry'],\n lc_kwargs: {},\n name: 'SentryCallbackHandler',\n\n // BaseCallbackHandlerInput boolean flags\n ignoreLLM: false,\n ignoreChain: false,\n ignoreAgent: false,\n ignoreRetriever: false,\n ignoreCustomEvent: false,\n raiseError: false,\n awaitHandlers: true,\n\n handleLLMStart(\n llm: unknown,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractLLMRequestAttributes(\n llm as LangChainSerialized,\n prompts,\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.pipeline',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.pipeline',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chat Model Start Handler\n handleChatModelStart(\n llm: unknown,\n messages: unknown,\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractChatModelRequestAttributes(\n llm as LangChainSerialized,\n messages as LangChainMessage[][],\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // LLM End Handler - note: handleLLMEnd with capital LLM (used by both LLMs and chat models!)\n handleLLMEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>,\n ) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n const attributes = extractLlmResponseAttributes(output as LangChainLLMResult, recordOutputs);\n if (attributes) {\n span.setAttributes(attributes);\n }\n exitSpan(runId);\n }\n },\n\n // LLM Error Handler - note: handleLLMError with capital LLM\n handleLLMError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'llm_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.llm_error_handler`,\n },\n });\n },\n\n // Chain Start Handler\n handleChainStart(chain: { name?: string }, inputs: Record<string, unknown>, runId: string, _parentRunId?: string) {\n const chainName = chain.name || 'unknown_chain';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',\n 'langchain.chain.name': chainName,\n };\n\n // Add inputs if recordInputs is enabled\n if (recordInputs) {\n attributes['langchain.chain.inputs'] = JSON.stringify(inputs);\n }\n\n startSpanManual(\n {\n name: `chain ${chainName}`,\n op: 'gen_ai.invoke_agent',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chain End Handler\n handleChainEnd(outputs: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add outputs if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'langchain.chain.outputs': JSON.stringify(outputs),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Chain Error Handler\n handleChainError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'chain_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.chain_error_handler`,\n },\n });\n },\n\n // Tool Start Handler\n handleToolStart(tool: { name?: string }, input: string, runId: string, _parentRunId?: string) {\n const toolName = tool.name || 'unknown_tool';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n 'gen_ai.tool.name': toolName,\n };\n\n // Add input if recordInputs is enabled\n if (recordInputs) {\n attributes['gen_ai.tool.input'] = input;\n }\n\n startSpanManual(\n {\n name: `execute_tool ${toolName}`,\n op: 'gen_ai.execute_tool',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.execute_tool',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Tool End Handler\n handleToolEnd(output: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add output if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'gen_ai.tool.output': JSON.stringify(output),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Tool Error Handler\n handleToolError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'tool_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.tool_error_handler`,\n },\n });\n },\n\n // LangChain BaseCallbackHandler required methods\n copy() {\n return handler;\n },\n\n toJSON() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n\n toJSONNotImplemented() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n };\n\n return handler;\n}\n"],"names":["getInvocationParams","extractLLMRequestAttributes","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_OP","extractChatModelRequestAttributes","extractLlmResponseAttributes","SPAN_STATUS_ERROR","captureException","LANGCHAIN_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/langchain/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_TOOL_INPUT_ATTRIBUTE,\n GEN_AI_TOOL_NAME_ATTRIBUTE,\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { LANGCHAIN_ORIGIN } from './constants';\nimport type {\n LangChainCallbackHandler,\n LangChainLLMResult,\n LangChainMessage,\n LangChainOptions,\n LangChainSerialized,\n} from './types';\nimport {\n extractChatModelRequestAttributes,\n extractLLMRequestAttributes,\n extractLlmResponseAttributes,\n getInvocationParams,\n} from './utils';\n\n/**\n * Creates a Sentry callback handler for LangChain\n * Returns a plain object that LangChain will call via duck-typing\n *\n * This is a stateful handler that tracks spans across multiple LangChain executions.\n */\nexport function createLangChainCallbackHandler(options: LangChainOptions = {}): LangChainCallbackHandler {\n const recordInputs = options.recordInputs ?? false;\n const recordOutputs = options.recordOutputs ?? false;\n\n // Internal state - single instance tracks all spans\n const spanMap = new Map<string, Span>();\n\n /**\n * Exit a span and clean up\n */\n const exitSpan = (runId: string): void => {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.end();\n spanMap.delete(runId);\n }\n };\n\n /**\n * Handler for LLM Start\n * This handler will be called by LangChain's callback handler when an LLM event is detected.\n */\n const handler: LangChainCallbackHandler = {\n // Required LangChain BaseCallbackHandler properties\n lc_serializable: false,\n lc_namespace: ['langchain_core', 'callbacks', 'sentry'],\n lc_secrets: undefined,\n lc_attributes: undefined,\n lc_aliases: undefined,\n lc_serializable_keys: undefined,\n lc_id: ['langchain_core', 'callbacks', 'sentry'],\n lc_kwargs: {},\n name: 'SentryCallbackHandler',\n\n // BaseCallbackHandlerInput boolean flags\n ignoreLLM: false,\n ignoreChain: false,\n ignoreAgent: false,\n ignoreRetriever: false,\n ignoreCustomEvent: false,\n raiseError: false,\n awaitHandlers: true,\n\n handleLLMStart(\n llm: unknown,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractLLMRequestAttributes(\n llm as LangChainSerialized,\n prompts,\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chat Model Start Handler\n handleChatModelStart(\n llm: unknown,\n messages: unknown,\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractChatModelRequestAttributes(\n llm as LangChainSerialized,\n messages as LangChainMessage[][],\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // LLM End Handler - note: handleLLMEnd with capital LLM (used by both LLMs and chat models!)\n handleLLMEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>,\n ) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n const attributes = extractLlmResponseAttributes(output as LangChainLLMResult, recordOutputs);\n if (attributes) {\n span.setAttributes(attributes);\n }\n exitSpan(runId);\n }\n },\n\n // LLM Error Handler - note: handleLLMError with capital LLM\n handleLLMError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'llm_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.llm_error_handler`,\n },\n });\n },\n\n // Chain Start Handler\n handleChainStart(chain: { name?: string }, inputs: Record<string, unknown>, runId: string, _parentRunId?: string) {\n const chainName = chain.name || 'unknown_chain';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',\n 'langchain.chain.name': chainName,\n };\n\n // Add inputs if recordInputs is enabled\n if (recordInputs) {\n attributes['langchain.chain.inputs'] = JSON.stringify(inputs);\n }\n\n startSpanManual(\n {\n name: `chain ${chainName}`,\n op: 'gen_ai.invoke_agent',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chain End Handler\n handleChainEnd(outputs: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add outputs if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'langchain.chain.outputs': JSON.stringify(outputs),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Chain Error Handler\n handleChainError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'chain_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.chain_error_handler`,\n },\n });\n },\n\n // Tool Start Handler\n handleToolStart(tool: { name?: string }, input: string, runId: string, _parentRunId?: string) {\n const toolName = tool.name || 'unknown_tool';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,\n };\n\n // Add input if recordInputs is enabled\n if (recordInputs) {\n attributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;\n }\n\n startSpanManual(\n {\n name: `execute_tool ${toolName}`,\n op: 'gen_ai.execute_tool',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.execute_tool',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Tool End Handler\n handleToolEnd(output: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add output if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n [GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: JSON.stringify(output),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Tool Error Handler\n handleToolError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'tool_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.tool_error_handler`,\n },\n });\n },\n\n // LangChain BaseCallbackHandler required methods\n copy() {\n return handler;\n },\n\n toJSON() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n\n toJSONNotImplemented() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n };\n\n return handler;\n}\n"],"names":["getInvocationParams","extractLLMRequestAttributes","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_OP","extractChatModelRequestAttributes","extractLlmResponseAttributes","SPAN_STATUS_ERROR","captureException","LANGCHAIN_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_TOOL_NAME_ATTRIBUTE","GEN_AI_TOOL_INPUT_ATTRIBUTE","GEN_AI_TOOL_OUTPUT_ATTRIBUTE"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const semanticAttributes = require('../../semanticAttributes.js');
|
|
4
4
|
const genAiAttributes = require('../ai/gen-ai-attributes.js');
|
|
5
5
|
const messageTruncation = require('../ai/messageTruncation.js');
|
|
6
|
+
const utils = require('../ai/utils.js');
|
|
6
7
|
const constants = require('./constants.js');
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -102,12 +103,16 @@ function normalizeLangChainMessages(messages) {
|
|
|
102
103
|
};
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
// 2)
|
|
106
|
-
|
|
107
|
-
if (
|
|
106
|
+
// 2) Serialized LangChain format (lc: 1) - check before constructor name
|
|
107
|
+
// This is more reliable than constructor.name which can be lost during serialization
|
|
108
|
+
if (message.lc === 1 && message.kwargs) {
|
|
109
|
+
const id = message.id;
|
|
110
|
+
const messageType = Array.isArray(id) && id.length > 0 ? id[id.length - 1] : '';
|
|
111
|
+
const role = typeof messageType === 'string' ? normalizeRoleNameFromCtor(messageType) : 'user';
|
|
112
|
+
|
|
108
113
|
return {
|
|
109
|
-
role: normalizeMessageRole(
|
|
110
|
-
content: asString(message.content),
|
|
114
|
+
role: normalizeMessageRole(role),
|
|
115
|
+
content: asString(message.kwargs?.content),
|
|
111
116
|
};
|
|
112
117
|
}
|
|
113
118
|
|
|
@@ -120,7 +125,8 @@ function normalizeLangChainMessages(messages) {
|
|
|
120
125
|
};
|
|
121
126
|
}
|
|
122
127
|
|
|
123
|
-
// 4) Then objects with `{ role, content }`
|
|
128
|
+
// 4) Then objects with `{ role, content }` - check before constructor name
|
|
129
|
+
// Plain objects have constructor.name="Object" which would incorrectly default to "user"
|
|
124
130
|
if (message.role) {
|
|
125
131
|
return {
|
|
126
132
|
role: normalizeMessageRole(String(message.role)),
|
|
@@ -128,15 +134,13 @@ function normalizeLangChainMessages(messages) {
|
|
|
128
134
|
};
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
// 5)
|
|
132
|
-
if
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const role = typeof messageType === 'string' ? normalizeRoleNameFromCtor(messageType) : 'user';
|
|
136
|
-
|
|
137
|
+
// 5) Then try constructor name (SystemMessage / HumanMessage / ...)
|
|
138
|
+
// Only use this if we haven't matched a more specific case
|
|
139
|
+
const ctor = (message ).constructor?.name;
|
|
140
|
+
if (ctor && ctor !== 'Object') {
|
|
137
141
|
return {
|
|
138
|
-
role: normalizeMessageRole(
|
|
139
|
-
content: asString(message.
|
|
142
|
+
role: normalizeMessageRole(normalizeRoleNameFromCtor(ctor)),
|
|
143
|
+
content: asString(message.content),
|
|
140
144
|
};
|
|
141
145
|
}
|
|
142
146
|
|
|
@@ -193,18 +197,18 @@ function extractCommonRequestAttributes(
|
|
|
193
197
|
|
|
194
198
|
/**
|
|
195
199
|
* Small helper to assemble boilerplate attributes shared by both request extractors.
|
|
200
|
+
* Always uses 'chat' as the operation type for all LLM and chat model operations.
|
|
196
201
|
*/
|
|
197
202
|
function baseRequestAttributes(
|
|
198
203
|
system,
|
|
199
204
|
modelName,
|
|
200
|
-
operation,
|
|
201
205
|
serialized,
|
|
202
206
|
invocationParams,
|
|
203
207
|
langSmithMetadata,
|
|
204
208
|
) {
|
|
205
209
|
return {
|
|
206
210
|
[genAiAttributes.GEN_AI_SYSTEM_ATTRIBUTE]: asString(system ?? 'langchain'),
|
|
207
|
-
[genAiAttributes.GEN_AI_OPERATION_NAME_ATTRIBUTE]:
|
|
211
|
+
[genAiAttributes.GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'chat',
|
|
208
212
|
[genAiAttributes.GEN_AI_REQUEST_MODEL_ATTRIBUTE]: asString(modelName),
|
|
209
213
|
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: constants.LANGCHAIN_ORIGIN,
|
|
210
214
|
...extractCommonRequestAttributes(serialized, invocationParams, langSmithMetadata),
|
|
@@ -214,7 +218,8 @@ function baseRequestAttributes(
|
|
|
214
218
|
/**
|
|
215
219
|
* Extracts attributes for plain LLM invocations (string prompts).
|
|
216
220
|
*
|
|
217
|
-
* - Operation is tagged as `
|
|
221
|
+
* - Operation is tagged as `chat` following OpenTelemetry semantic conventions.
|
|
222
|
+
* LangChain LLM operations are treated as chat operations.
|
|
218
223
|
* - When `recordInputs` is true, string prompts are wrapped into `{role:"user"}`
|
|
219
224
|
* messages to align with the chat schema used elsewhere.
|
|
220
225
|
*/
|
|
@@ -228,12 +233,12 @@ function extractLLMRequestAttributes(
|
|
|
228
233
|
const system = langSmithMetadata?.ls_provider;
|
|
229
234
|
const modelName = invocationParams?.model ?? langSmithMetadata?.ls_model_name ?? 'unknown';
|
|
230
235
|
|
|
231
|
-
const attrs = baseRequestAttributes(system, modelName,
|
|
236
|
+
const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata);
|
|
232
237
|
|
|
233
238
|
if (recordInputs && Array.isArray(prompts) && prompts.length > 0) {
|
|
234
|
-
setIfDefined(attrs, genAiAttributes.
|
|
239
|
+
setIfDefined(attrs, genAiAttributes.GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, prompts.length);
|
|
235
240
|
const messages = prompts.map(p => ({ role: 'user', content: p }));
|
|
236
|
-
setIfDefined(attrs, genAiAttributes.
|
|
241
|
+
setIfDefined(attrs, genAiAttributes.GEN_AI_INPUT_MESSAGES_ATTRIBUTE, asString(messages));
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
return attrs;
|
|
@@ -242,7 +247,8 @@ function extractLLMRequestAttributes(
|
|
|
242
247
|
/**
|
|
243
248
|
* Extracts attributes for ChatModel invocations (array-of-arrays of messages).
|
|
244
249
|
*
|
|
245
|
-
* - Operation is tagged as `chat
|
|
250
|
+
* - Operation is tagged as `chat` following OpenTelemetry semantic conventions.
|
|
251
|
+
* LangChain chat model operations are chat operations.
|
|
246
252
|
* - We flatten LangChain's `LangChainMessage[][]` and normalize shapes into a
|
|
247
253
|
* consistent `{ role, content }` array when `recordInputs` is true.
|
|
248
254
|
* - Provider system value falls back to `serialized.id?.[2]`.
|
|
@@ -257,13 +263,22 @@ function extractChatModelRequestAttributes(
|
|
|
257
263
|
const system = langSmithMetadata?.ls_provider ?? llm.id?.[2];
|
|
258
264
|
const modelName = invocationParams?.model ?? langSmithMetadata?.ls_model_name ?? 'unknown';
|
|
259
265
|
|
|
260
|
-
const attrs = baseRequestAttributes(system, modelName,
|
|
266
|
+
const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata);
|
|
261
267
|
|
|
262
268
|
if (recordInputs && Array.isArray(langChainMessages) && langChainMessages.length > 0) {
|
|
263
269
|
const normalized = normalizeLangChainMessages(langChainMessages.flat());
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
|
|
270
|
+
|
|
271
|
+
const { systemInstructions, filteredMessages } = utils.extractSystemInstructions(normalized);
|
|
272
|
+
|
|
273
|
+
if (systemInstructions) {
|
|
274
|
+
setIfDefined(attrs, genAiAttributes.GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;
|
|
278
|
+
setIfDefined(attrs, genAiAttributes.GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredLength);
|
|
279
|
+
|
|
280
|
+
const truncated = messageTruncation.truncateGenAiMessages(filteredMessages );
|
|
281
|
+
setIfDefined(attrs, genAiAttributes.GEN_AI_INPUT_MESSAGES_ATTRIBUTE, asString(truncated));
|
|
267
282
|
}
|
|
268
283
|
|
|
269
284
|
return attrs;
|