@sentry/node 9.26.0 → 9.28.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.
Files changed (46) hide show
  1. package/build/cjs/index.js +2 -0
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/integrations/anr/index.js +1 -1
  4. package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  5. package/build/cjs/integrations/tracing/vercelai/ai_sdk_attributes.js +128 -0
  6. package/build/cjs/integrations/tracing/vercelai/ai_sdk_attributes.js.map +1 -0
  7. package/build/cjs/integrations/tracing/vercelai/constants.js +6 -0
  8. package/build/cjs/integrations/tracing/vercelai/constants.js.map +1 -0
  9. package/build/cjs/integrations/tracing/vercelai/index.js +113 -89
  10. package/build/cjs/integrations/tracing/vercelai/index.js.map +1 -1
  11. package/build/cjs/integrations/tracing/vercelai/instrumentation.js +56 -10
  12. package/build/cjs/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  13. package/build/esm/index.js +1 -0
  14. package/build/esm/index.js.map +1 -1
  15. package/build/esm/integrations/anr/index.js +1 -1
  16. package/build/esm/integrations/anr/worker-script.js +2 -2
  17. package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  18. package/build/esm/integrations/local-variables/worker-script.js +2 -2
  19. package/build/esm/integrations/tracing/vercelai/ai_sdk_attributes.js +116 -0
  20. package/build/esm/integrations/tracing/vercelai/ai_sdk_attributes.js.map +1 -0
  21. package/build/esm/integrations/tracing/vercelai/constants.js +4 -0
  22. package/build/esm/integrations/tracing/vercelai/constants.js.map +1 -0
  23. package/build/esm/integrations/tracing/vercelai/index.js +111 -87
  24. package/build/esm/integrations/tracing/vercelai/index.js.map +1 -1
  25. package/build/esm/integrations/tracing/vercelai/instrumentation.js +57 -12
  26. package/build/esm/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  27. package/build/esm/package.json +1 -1
  28. package/build/types/index.d.ts +1 -0
  29. package/build/types/index.d.ts.map +1 -1
  30. package/build/types/integrations/tracing/vercelai/ai_sdk_attributes.d.ts +669 -0
  31. package/build/types/integrations/tracing/vercelai/ai_sdk_attributes.d.ts.map +1 -0
  32. package/build/types/integrations/tracing/vercelai/constants.d.ts +2 -0
  33. package/build/types/integrations/tracing/vercelai/constants.d.ts.map +1 -0
  34. package/build/types/integrations/tracing/vercelai/index.d.ts +2 -1
  35. package/build/types/integrations/tracing/vercelai/index.d.ts.map +1 -1
  36. package/build/types/integrations/tracing/vercelai/instrumentation.d.ts +18 -0
  37. package/build/types/integrations/tracing/vercelai/instrumentation.d.ts.map +1 -1
  38. package/build/types/integrations/tracing/vercelai/types.d.ts +16 -0
  39. package/build/types/integrations/tracing/vercelai/types.d.ts.map +1 -1
  40. package/build/types-ts3.8/index.d.ts +1 -0
  41. package/build/types-ts3.8/integrations/tracing/vercelai/ai_sdk_attributes.d.ts +669 -0
  42. package/build/types-ts3.8/integrations/tracing/vercelai/constants.d.ts +2 -0
  43. package/build/types-ts3.8/integrations/tracing/vercelai/index.d.ts +2 -1
  44. package/build/types-ts3.8/integrations/tracing/vercelai/instrumentation.d.ts +18 -0
  45. package/build/types-ts3.8/integrations/tracing/vercelai/types.d.ts +16 -0
  46. package/package.json +3 -3
@@ -3,17 +3,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
3
  const core = require('@sentry/core');
4
4
  const instrument = require('../../../otel/instrument.js');
5
5
  const addOriginToSpan = require('../../../utils/addOriginToSpan.js');
6
+ const ai_sdk_attributes = require('./ai_sdk_attributes.js');
7
+ const constants = require('./constants.js');
6
8
  const instrumentation = require('./instrumentation.js');
7
9
 
8
- const INTEGRATION_NAME = 'VercelAI';
10
+ const instrumentVercelAi = instrument.generateInstrumentOnce(constants.INTEGRATION_NAME, () => new instrumentation.SentryVercelAiInstrumentation({}));
9
11
 
10
- const instrumentVercelAi = instrument.generateInstrumentOnce(INTEGRATION_NAME, () => new instrumentation.SentryVercelAiInstrumentation({}));
11
-
12
- const _vercelAIIntegration = (() => {
12
+ const _vercelAIIntegration = ((options = {}) => {
13
13
  let instrumentation;
14
14
 
15
15
  return {
16
- name: INTEGRATION_NAME,
16
+ name: constants.INTEGRATION_NAME,
17
+ options,
17
18
  setupOnce() {
18
19
  instrumentation = instrumentVercelAi();
19
20
  },
@@ -26,81 +27,30 @@ const _vercelAIIntegration = (() => {
26
27
  return;
27
28
  }
28
29
 
29
- // The id of the model
30
- const aiModelId = attributes['ai.model.id'];
30
+ // Tool call spans
31
+ // https://ai-sdk.dev/docs/ai-sdk-core/telemetry#tool-call-spans
32
+ if (
33
+ attributes[ai_sdk_attributes.AI_TOOL_CALL_NAME_ATTRIBUTE] &&
34
+ attributes[ai_sdk_attributes.AI_TOOL_CALL_ID_ATTRIBUTE] &&
35
+ name === 'ai.toolCall'
36
+ ) {
37
+ addOriginToSpan.addOriginToSpan(span, 'auto.vercelai.otel');
38
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.execute_tool');
39
+ span.setAttribute('gen_ai.tool.call.id', attributes[ai_sdk_attributes.AI_TOOL_CALL_ID_ATTRIBUTE]);
40
+ span.setAttribute('gen_ai.tool.name', attributes[ai_sdk_attributes.AI_TOOL_CALL_NAME_ATTRIBUTE]);
41
+ span.updateName(`execute_tool ${attributes[ai_sdk_attributes.AI_TOOL_CALL_NAME_ATTRIBUTE]}`);
42
+ return;
43
+ }
31
44
 
45
+ // The AI and Provider must be defined for generate, stream, and embed spans.
46
+ // The id of the model
47
+ const aiModelId = attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE];
32
48
  // the provider of the model
33
- const aiModelProvider = attributes['ai.model.provider'];
34
-
35
- // both of these must be defined for the integration to work
49
+ const aiModelProvider = attributes[ai_sdk_attributes.AI_MODEL_PROVIDER_ATTRIBUTE];
36
50
  if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) {
37
51
  return;
38
52
  }
39
53
 
40
- let isPipelineSpan = false;
41
-
42
- switch (name) {
43
- case 'ai.generateText': {
44
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateText');
45
- isPipelineSpan = true;
46
- break;
47
- }
48
- case 'ai.generateText.doGenerate': {
49
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate');
50
- break;
51
- }
52
- case 'ai.streamText': {
53
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamText');
54
- isPipelineSpan = true;
55
- break;
56
- }
57
- case 'ai.streamText.doStream': {
58
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream');
59
- break;
60
- }
61
- case 'ai.generateObject': {
62
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateObject');
63
- isPipelineSpan = true;
64
- break;
65
- }
66
- case 'ai.generateObject.doGenerate': {
67
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate');
68
- break;
69
- }
70
- case 'ai.streamObject': {
71
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamObject');
72
- isPipelineSpan = true;
73
- break;
74
- }
75
- case 'ai.streamObject.doStream': {
76
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream');
77
- break;
78
- }
79
- case 'ai.embed': {
80
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed');
81
- isPipelineSpan = true;
82
- break;
83
- }
84
- case 'ai.embed.doEmbed': {
85
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings');
86
- break;
87
- }
88
- case 'ai.embedMany': {
89
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embedMany');
90
- isPipelineSpan = true;
91
- break;
92
- }
93
- case 'ai.embedMany.doEmbed': {
94
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings');
95
- break;
96
- }
97
- case 'ai.toolCall':
98
- case 'ai.stream.firstChunk':
99
- case 'ai.stream.finish':
100
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run');
101
- break;
102
- }
103
-
104
54
  addOriginToSpan.addOriginToSpan(span, 'auto.vercelai.otel');
105
55
 
106
56
  const nameWthoutAi = name.replace('ai.', '');
@@ -108,19 +58,91 @@ const _vercelAIIntegration = (() => {
108
58
  span.updateName(nameWthoutAi);
109
59
 
110
60
  // If a Telemetry name is set and it is a pipeline span, use that as the operation name
111
- const functionId = attributes['ai.telemetry.functionId'];
112
- if (functionId && typeof functionId === 'string' && isPipelineSpan) {
113
- span.updateName(functionId);
61
+ const functionId = attributes[ai_sdk_attributes.AI_TELEMETRY_FUNCTION_ID_ATTRIBUTE];
62
+ if (functionId && typeof functionId === 'string' && name.split('.').length - 1 === 1) {
63
+ span.updateName(`${nameWthoutAi} ${functionId}`);
114
64
  span.setAttribute('ai.pipeline.name', functionId);
115
65
  }
116
66
 
117
- if (attributes['ai.prompt']) {
118
- span.setAttribute('ai.input_messages', attributes['ai.prompt']);
67
+ if (attributes[ai_sdk_attributes.AI_PROMPT_ATTRIBUTE]) {
68
+ span.setAttribute('gen_ai.prompt', attributes[ai_sdk_attributes.AI_PROMPT_ATTRIBUTE]);
119
69
  }
120
- if (attributes['ai.model.id']) {
121
- span.setAttribute('ai.model_id', attributes['ai.model.id']);
70
+ if (attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE] && !attributes[ai_sdk_attributes.GEN_AI_RESPONSE_MODEL_ATTRIBUTE]) {
71
+ span.setAttribute(ai_sdk_attributes.GEN_AI_RESPONSE_MODEL_ATTRIBUTE, attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]);
122
72
  }
123
73
  span.setAttribute('ai.streaming', name.includes('stream'));
74
+
75
+ // Generate Spans
76
+ if (name === 'ai.generateText') {
77
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generate_text');
78
+ return;
79
+ }
80
+
81
+ if (name === 'ai.generateText.doGenerate') {
82
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.generate_text');
83
+ span.updateName(`generate_text ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
84
+ return;
85
+ }
86
+
87
+ if (name === 'ai.streamText') {
88
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.stream_text');
89
+ return;
90
+ }
91
+
92
+ if (name === 'ai.streamText.doStream') {
93
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.stream_text');
94
+ span.updateName(`stream_text ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
95
+ return;
96
+ }
97
+
98
+ if (name === 'ai.generateObject') {
99
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generate_object');
100
+ return;
101
+ }
102
+
103
+ if (name === 'ai.generateObject.doGenerate') {
104
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.generate_object');
105
+ span.updateName(`generate_object ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
106
+ return;
107
+ }
108
+
109
+ if (name === 'ai.streamObject') {
110
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.stream_object');
111
+ return;
112
+ }
113
+
114
+ if (name === 'ai.streamObject.doStream') {
115
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.stream_object');
116
+ span.updateName(`stream_object ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
117
+ return;
118
+ }
119
+
120
+ if (name === 'ai.embed') {
121
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed');
122
+ return;
123
+ }
124
+
125
+ if (name === 'ai.embed.doEmbed') {
126
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.embed');
127
+ span.updateName(`embed ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
128
+ return;
129
+ }
130
+
131
+ if (name === 'ai.embedMany') {
132
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed_many');
133
+ return;
134
+ }
135
+
136
+ if (name === 'ai.embedMany.doEmbed') {
137
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.embed_many');
138
+ span.updateName(`embed_many ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
139
+ return;
140
+ }
141
+
142
+ if (name.startsWith('ai.stream')) {
143
+ span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run');
144
+ return;
145
+ }
124
146
  });
125
147
 
126
148
  client.addEventProcessor(event => {
@@ -132,18 +154,20 @@ const _vercelAIIntegration = (() => {
132
154
  continue;
133
155
  }
134
156
 
135
- if (attributes['ai.usage.completionTokens'] != undefined) {
136
- attributes['ai.completion_tokens.used'] = attributes['ai.usage.completionTokens'];
157
+ if (attributes[ai_sdk_attributes.AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE] != undefined) {
158
+ attributes[ai_sdk_attributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = attributes[ai_sdk_attributes.AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE];
159
+ delete attributes[ai_sdk_attributes.AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE];
137
160
  }
138
- if (attributes['ai.usage.promptTokens'] != undefined) {
139
- attributes['ai.prompt_tokens.used'] = attributes['ai.usage.promptTokens'];
161
+ if (attributes[ai_sdk_attributes.AI_USAGE_PROMPT_TOKENS_ATTRIBUTE] != undefined) {
162
+ attributes[ai_sdk_attributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = attributes[ai_sdk_attributes.AI_USAGE_PROMPT_TOKENS_ATTRIBUTE];
163
+ delete attributes[ai_sdk_attributes.AI_USAGE_PROMPT_TOKENS_ATTRIBUTE];
140
164
  }
141
165
  if (
142
- typeof attributes['ai.usage.completionTokens'] == 'number' &&
143
- typeof attributes['ai.usage.promptTokens'] == 'number'
166
+ typeof attributes[ai_sdk_attributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] === 'number' &&
167
+ typeof attributes[ai_sdk_attributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] === 'number'
144
168
  ) {
145
- attributes['ai.total_tokens.used'] =
146
- attributes['ai.usage.completionTokens'] + attributes['ai.usage.promptTokens'];
169
+ attributes['gen_ai.usage.total_tokens'] =
170
+ attributes[ai_sdk_attributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] + attributes[ai_sdk_attributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE];
147
171
  }
148
172
  }
149
173
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/vercelai/index.ts"],"sourcesContent":["/* eslint-disable complexity */\nimport type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, spanToJSON } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../../otel/instrument';\nimport { addOriginToSpan } from '../../../utils/addOriginToSpan';\nimport { SentryVercelAiInstrumentation } from './instrumentation';\n\nconst INTEGRATION_NAME = 'VercelAI';\n\nexport const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({}));\n\nconst _vercelAIIntegration = (() => {\n let instrumentation: undefined | SentryVercelAiInstrumentation;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentation = instrumentVercelAi();\n },\n setup(client) {\n instrumentation?.callWhenPatched(() => {\n client.on('spanStart', span => {\n const { data: attributes, description: name } = spanToJSON(span);\n\n if (!name) {\n return;\n }\n\n // The id of the model\n const aiModelId = attributes['ai.model.id'];\n\n // the provider of the model\n const aiModelProvider = attributes['ai.model.provider'];\n\n // both of these must be defined for the integration to work\n if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) {\n return;\n }\n\n let isPipelineSpan = false;\n\n switch (name) {\n case 'ai.generateText': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateText');\n isPipelineSpan = true;\n break;\n }\n case 'ai.generateText.doGenerate': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate');\n break;\n }\n case 'ai.streamText': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamText');\n isPipelineSpan = true;\n break;\n }\n case 'ai.streamText.doStream': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream');\n break;\n }\n case 'ai.generateObject': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateObject');\n isPipelineSpan = true;\n break;\n }\n case 'ai.generateObject.doGenerate': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate');\n break;\n }\n case 'ai.streamObject': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamObject');\n isPipelineSpan = true;\n break;\n }\n case 'ai.streamObject.doStream': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream');\n break;\n }\n case 'ai.embed': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed');\n isPipelineSpan = true;\n break;\n }\n case 'ai.embed.doEmbed': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings');\n break;\n }\n case 'ai.embedMany': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embedMany');\n isPipelineSpan = true;\n break;\n }\n case 'ai.embedMany.doEmbed': {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings');\n break;\n }\n case 'ai.toolCall':\n case 'ai.stream.firstChunk':\n case 'ai.stream.finish':\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run');\n break;\n }\n\n addOriginToSpan(span, 'auto.vercelai.otel');\n\n const nameWthoutAi = name.replace('ai.', '');\n span.setAttribute('ai.pipeline.name', nameWthoutAi);\n span.updateName(nameWthoutAi);\n\n // If a Telemetry name is set and it is a pipeline span, use that as the operation name\n const functionId = attributes['ai.telemetry.functionId'];\n if (functionId && typeof functionId === 'string' && isPipelineSpan) {\n span.updateName(functionId);\n span.setAttribute('ai.pipeline.name', functionId);\n }\n\n if (attributes['ai.prompt']) {\n span.setAttribute('ai.input_messages', attributes['ai.prompt']);\n }\n if (attributes['ai.model.id']) {\n span.setAttribute('ai.model_id', attributes['ai.model.id']);\n }\n span.setAttribute('ai.streaming', name.includes('stream'));\n });\n\n client.addEventProcessor(event => {\n if (event.type === 'transaction' && event.spans?.length) {\n for (const span of event.spans) {\n const { data: attributes, description: name } = span;\n\n if (!name || span.origin !== 'auto.vercelai.otel') {\n continue;\n }\n\n if (attributes['ai.usage.completionTokens'] != undefined) {\n attributes['ai.completion_tokens.used'] = attributes['ai.usage.completionTokens'];\n }\n if (attributes['ai.usage.promptTokens'] != undefined) {\n attributes['ai.prompt_tokens.used'] = attributes['ai.usage.promptTokens'];\n }\n if (\n typeof attributes['ai.usage.completionTokens'] == 'number' &&\n typeof attributes['ai.usage.promptTokens'] == 'number'\n ) {\n attributes['ai.total_tokens.used'] =\n attributes['ai.usage.completionTokens'] + attributes['ai.usage.promptTokens'];\n }\n }\n }\n\n return event;\n });\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.\n *\n * For more information, see the [`ai` documentation](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.vercelAIIntegration()],\n * });\n * ```\n *\n * By default this integration adds tracing support to all `ai` function calls. If you need to disable\n * collecting spans for a specific call, you can do so by setting `experimental_telemetry.isEnabled` to\n * `false` in the first argument of the function call.\n *\n * ```javascript\n * const result = await generateText({\n * model: openai('gpt-4-turbo'),\n * experimental_telemetry: { isEnabled: false },\n * });\n * ```\n *\n * If you want to collect inputs and outputs for a specific call, you must specifically opt-in to each\n * function call by setting `experimental_telemetry.recordInputs` and `experimental_telemetry.recordOutputs`\n * to `true`.\n *\n * ```javascript\n * const result = await generateText({\n * model: openai('gpt-4-turbo'),\n * experimental_telemetry: { isEnabled: true, recordInputs: true, recordOutputs: true },\n * });\n */\nexport const vercelAIIntegration = defineIntegration(_vercelAIIntegration);\n"],"names":["generateInstrumentOnce","SentryVercelAiInstrumentation","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","addOriginToSpan","defineIntegration"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/vercelai/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-dynamic-delete */\n/* eslint-disable complexity */\nimport type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, spanToJSON } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../../otel/instrument';\nimport { addOriginToSpan } from '../../../utils/addOriginToSpan';\nimport {\n AI_MODEL_ID_ATTRIBUTE,\n AI_MODEL_PROVIDER_ATTRIBUTE,\n AI_PROMPT_ATTRIBUTE,\n AI_TELEMETRY_FUNCTION_ID_ATTRIBUTE,\n AI_TOOL_CALL_ID_ATTRIBUTE,\n AI_TOOL_CALL_NAME_ATTRIBUTE,\n AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE,\n AI_USAGE_PROMPT_TOKENS_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n} from './ai_sdk_attributes';\nimport { INTEGRATION_NAME } from './constants';\nimport { SentryVercelAiInstrumentation } from './instrumentation';\nimport type { VercelAiOptions } from './types';\n\nexport const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({}));\n\nconst _vercelAIIntegration = ((options: VercelAiOptions = {}) => {\n let instrumentation: undefined | SentryVercelAiInstrumentation;\n\n return {\n name: INTEGRATION_NAME,\n options,\n setupOnce() {\n instrumentation = instrumentVercelAi();\n },\n setup(client) {\n instrumentation?.callWhenPatched(() => {\n client.on('spanStart', span => {\n const { data: attributes, description: name } = spanToJSON(span);\n\n if (!name) {\n return;\n }\n\n // Tool call spans\n // https://ai-sdk.dev/docs/ai-sdk-core/telemetry#tool-call-spans\n if (\n attributes[AI_TOOL_CALL_NAME_ATTRIBUTE] &&\n attributes[AI_TOOL_CALL_ID_ATTRIBUTE] &&\n name === 'ai.toolCall'\n ) {\n addOriginToSpan(span, 'auto.vercelai.otel');\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.execute_tool');\n span.setAttribute('gen_ai.tool.call.id', attributes[AI_TOOL_CALL_ID_ATTRIBUTE]);\n span.setAttribute('gen_ai.tool.name', attributes[AI_TOOL_CALL_NAME_ATTRIBUTE]);\n span.updateName(`execute_tool ${attributes[AI_TOOL_CALL_NAME_ATTRIBUTE]}`);\n return;\n }\n\n // The AI and Provider must be defined for generate, stream, and embed spans.\n // The id of the model\n const aiModelId = attributes[AI_MODEL_ID_ATTRIBUTE];\n // the provider of the model\n const aiModelProvider = attributes[AI_MODEL_PROVIDER_ATTRIBUTE];\n if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) {\n return;\n }\n\n addOriginToSpan(span, 'auto.vercelai.otel');\n\n const nameWthoutAi = name.replace('ai.', '');\n span.setAttribute('ai.pipeline.name', nameWthoutAi);\n span.updateName(nameWthoutAi);\n\n // If a Telemetry name is set and it is a pipeline span, use that as the operation name\n const functionId = attributes[AI_TELEMETRY_FUNCTION_ID_ATTRIBUTE];\n if (functionId && typeof functionId === 'string' && name.split('.').length - 1 === 1) {\n span.updateName(`${nameWthoutAi} ${functionId}`);\n span.setAttribute('ai.pipeline.name', functionId);\n }\n\n if (attributes[AI_PROMPT_ATTRIBUTE]) {\n span.setAttribute('gen_ai.prompt', attributes[AI_PROMPT_ATTRIBUTE]);\n }\n if (attributes[AI_MODEL_ID_ATTRIBUTE] && !attributes[GEN_AI_RESPONSE_MODEL_ATTRIBUTE]) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, attributes[AI_MODEL_ID_ATTRIBUTE]);\n }\n span.setAttribute('ai.streaming', name.includes('stream'));\n\n // Generate Spans\n if (name === 'ai.generateText') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generate_text');\n return;\n }\n\n if (name === 'ai.generateText.doGenerate') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.generate_text');\n span.updateName(`generate_text ${attributes[AI_MODEL_ID_ATTRIBUTE]}`);\n return;\n }\n\n if (name === 'ai.streamText') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.stream_text');\n return;\n }\n\n if (name === 'ai.streamText.doStream') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.stream_text');\n span.updateName(`stream_text ${attributes[AI_MODEL_ID_ATTRIBUTE]}`);\n return;\n }\n\n if (name === 'ai.generateObject') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generate_object');\n return;\n }\n\n if (name === 'ai.generateObject.doGenerate') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.generate_object');\n span.updateName(`generate_object ${attributes[AI_MODEL_ID_ATTRIBUTE]}`);\n return;\n }\n\n if (name === 'ai.streamObject') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.stream_object');\n return;\n }\n\n if (name === 'ai.streamObject.doStream') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.stream_object');\n span.updateName(`stream_object ${attributes[AI_MODEL_ID_ATTRIBUTE]}`);\n return;\n }\n\n if (name === 'ai.embed') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed');\n return;\n }\n\n if (name === 'ai.embed.doEmbed') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.embed');\n span.updateName(`embed ${attributes[AI_MODEL_ID_ATTRIBUTE]}`);\n return;\n }\n\n if (name === 'ai.embedMany') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed_many');\n return;\n }\n\n if (name === 'ai.embedMany.doEmbed') {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.embed_many');\n span.updateName(`embed_many ${attributes[AI_MODEL_ID_ATTRIBUTE]}`);\n return;\n }\n\n if (name.startsWith('ai.stream')) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run');\n return;\n }\n });\n\n client.addEventProcessor(event => {\n if (event.type === 'transaction' && event.spans?.length) {\n for (const span of event.spans) {\n const { data: attributes, description: name } = span;\n\n if (!name || span.origin !== 'auto.vercelai.otel') {\n continue;\n }\n\n if (attributes[AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE] != undefined) {\n attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] = attributes[AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE];\n delete attributes[AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE];\n }\n if (attributes[AI_USAGE_PROMPT_TOKENS_ATTRIBUTE] != undefined) {\n attributes[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] = attributes[AI_USAGE_PROMPT_TOKENS_ATTRIBUTE];\n delete attributes[AI_USAGE_PROMPT_TOKENS_ATTRIBUTE];\n }\n if (\n typeof attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] === 'number' &&\n typeof attributes[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] === 'number'\n ) {\n attributes['gen_ai.usage.total_tokens'] =\n attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] + attributes[GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE];\n }\n }\n }\n\n return event;\n });\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.\n *\n * For more information, see the [`ai` documentation](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.vercelAIIntegration()],\n * });\n * ```\n *\n * By default this integration adds tracing support to all `ai` function calls. If you need to disable\n * collecting spans for a specific call, you can do so by setting `experimental_telemetry.isEnabled` to\n * `false` in the first argument of the function call.\n *\n * ```javascript\n * const result = await generateText({\n * model: openai('gpt-4-turbo'),\n * experimental_telemetry: { isEnabled: false },\n * });\n * ```\n *\n * If you want to collect inputs and outputs for a specific call, you must specifically opt-in to each\n * function call by setting `experimental_telemetry.recordInputs` and `experimental_telemetry.recordOutputs`\n * to `true`.\n *\n * ```javascript\n * const result = await generateText({\n * model: openai('gpt-4-turbo'),\n * experimental_telemetry: { isEnabled: true, recordInputs: true, recordOutputs: true },\n * });\n */\nexport const vercelAIIntegration = defineIntegration(_vercelAIIntegration);\n"],"names":["generateInstrumentOnce","INTEGRATION_NAME","SentryVercelAiInstrumentation","spanToJSON","AI_TOOL_CALL_NAME_ATTRIBUTE","AI_TOOL_CALL_ID_ATTRIBUTE","addOriginToSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","AI_MODEL_ID_ATTRIBUTE","AI_MODEL_PROVIDER_ATTRIBUTE","AI_TELEMETRY_FUNCTION_ID_ATTRIBUTE","AI_PROMPT_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","AI_USAGE_PROMPT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","defineIntegration"],"mappings":"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"}
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const instrumentation = require('@opentelemetry/instrumentation');
4
4
  const core = require('@sentry/core');
5
+ const constants = require('./constants.js');
5
6
 
6
7
  // List of patched methods
7
8
  // From: https://sdk.vercel.ai/docs/ai-sdk-core/telemetry#collected-data
@@ -14,6 +15,42 @@ const INSTRUMENTED_METHODS = [
14
15
  'embedMany',
15
16
  ] ;
16
17
 
18
+ /**
19
+ * Determines whether to record inputs and outputs for Vercel AI telemetry based on the configuration hierarchy.
20
+ *
21
+ * The order of precedence is:
22
+ * 1. The vercel ai integration options
23
+ * 2. The experimental_telemetry options in the vercel ai method calls
24
+ * 3. When telemetry is explicitly enabled (isEnabled: true), default to recording
25
+ * 4. Otherwise, use the sendDefaultPii option from client options
26
+ */
27
+ function determineRecordingSettings(
28
+ integrationRecordingOptions,
29
+ methodTelemetryOptions,
30
+ telemetryExplicitlyEnabled,
31
+ defaultRecordingEnabled,
32
+ ) {
33
+ const recordInputs =
34
+ integrationRecordingOptions?.recordInputs !== undefined
35
+ ? integrationRecordingOptions.recordInputs
36
+ : methodTelemetryOptions.recordInputs !== undefined
37
+ ? methodTelemetryOptions.recordInputs
38
+ : telemetryExplicitlyEnabled === true
39
+ ? true // When telemetry is explicitly enabled, default to recording inputs
40
+ : defaultRecordingEnabled;
41
+
42
+ const recordOutputs =
43
+ integrationRecordingOptions?.recordOutputs !== undefined
44
+ ? integrationRecordingOptions.recordOutputs
45
+ : methodTelemetryOptions.recordOutputs !== undefined
46
+ ? methodTelemetryOptions.recordOutputs
47
+ : telemetryExplicitlyEnabled === true
48
+ ? true // When telemetry is explicitly enabled, default to recording inputs
49
+ : defaultRecordingEnabled;
50
+
51
+ return { recordInputs, recordOutputs };
52
+ }
53
+
17
54
  /**
18
55
  * This detects is added by the Sentry Vercel AI Integration to detect if the integration should
19
56
  * be enabled.
@@ -61,16 +98,24 @@ class SentryVercelAiInstrumentation extends instrumentation.InstrumentationBase
61
98
  const existingExperimentalTelemetry = args[0].experimental_telemetry || {};
62
99
  const isEnabled = existingExperimentalTelemetry.isEnabled;
63
100
 
64
- // if `isEnabled` is not explicitly set to `true` or `false`, enable telemetry
65
- // but disable capturing inputs and outputs by default
66
- if (isEnabled === undefined) {
67
- args[0].experimental_telemetry = {
68
- isEnabled: true,
69
- recordInputs: false,
70
- recordOutputs: false,
71
- ...existingExperimentalTelemetry,
72
- };
73
- }
101
+ const client = core.getCurrentScope().getClient();
102
+ const integration = client?.getIntegrationByName(constants.INTEGRATION_NAME);
103
+ const integrationOptions = integration?.options;
104
+ const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false;
105
+
106
+ const { recordInputs, recordOutputs } = determineRecordingSettings(
107
+ integrationOptions,
108
+ existingExperimentalTelemetry,
109
+ isEnabled,
110
+ shouldRecordInputsAndOutputs,
111
+ );
112
+
113
+ args[0].experimental_telemetry = {
114
+ ...existingExperimentalTelemetry,
115
+ isEnabled: isEnabled !== undefined ? isEnabled : true,
116
+ recordInputs,
117
+ recordOutputs,
118
+ };
74
119
 
75
120
  // @ts-expect-error we know that the method exists
76
121
  return originalMethod.apply(this, args);
@@ -100,4 +145,5 @@ class SentryVercelAiInstrumentation extends instrumentation.InstrumentationBase
100
145
  }
101
146
 
102
147
  exports.SentryVercelAiInstrumentation = SentryVercelAiInstrumentation;
148
+ exports.determineRecordingSettings = determineRecordingSettings;
103
149
  //# sourceMappingURL=instrumentation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/vercelai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport { SDK_VERSION } from '@sentry/core';\nimport type { TelemetrySettings } from './types';\n\n// List of patched methods\n// From: https://sdk.vercel.ai/docs/ai-sdk-core/telemetry#collected-data\nconst INSTRUMENTED_METHODS = [\n 'generateText',\n 'streamText',\n 'generateObject',\n 'streamObject',\n 'embed',\n 'embedMany',\n] as const;\n\ninterface MethodFirstArg extends Record<string, unknown> {\n experimental_telemetry?: TelemetrySettings;\n}\n\ntype MethodArgs = [MethodFirstArg, ...unknown[]];\n\ntype PatchedModuleExports = Record<(typeof INSTRUMENTED_METHODS)[number], (...args: MethodArgs) => unknown> &\n Record<string, unknown>;\n\n/**\n * This detects is added by the Sentry Vercel AI Integration to detect if the integration should\n * be enabled.\n *\n * It also patches the `ai` module to enable Vercel AI telemetry automatically for all methods.\n */\nexport class SentryVercelAiInstrumentation extends InstrumentationBase {\n private _isPatched = false;\n private _callbacks: (() => void)[] = [];\n\n public constructor(config: InstrumentationConfig = {}) {\n super('@sentry/instrumentation-vercel-ai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition('ai', ['>=3.0.0 <5'], this._patch.bind(this));\n return module;\n }\n\n /**\n * Call the provided callback when the module is patched.\n * If it has already been patched, the callback will be called immediately.\n */\n public callWhenPatched(callback: () => void): void {\n if (this._isPatched) {\n callback();\n } else {\n this._callbacks.push(callback);\n }\n }\n\n /**\n * Patches module exports to enable Vercel AI telemetry.\n */\n private _patch(moduleExports: PatchedModuleExports): unknown {\n this._isPatched = true;\n\n this._callbacks.forEach(callback => callback());\n this._callbacks = [];\n\n function generatePatch(originalMethod: (...args: MethodArgs) => unknown) {\n return (...args: MethodArgs) => {\n const existingExperimentalTelemetry = args[0].experimental_telemetry || {};\n const isEnabled = existingExperimentalTelemetry.isEnabled;\n\n // if `isEnabled` is not explicitly set to `true` or `false`, enable telemetry\n // but disable capturing inputs and outputs by default\n if (isEnabled === undefined) {\n args[0].experimental_telemetry = {\n isEnabled: true,\n recordInputs: false,\n recordOutputs: false,\n ...existingExperimentalTelemetry,\n };\n }\n\n // @ts-expect-error we know that the method exists\n return originalMethod.apply(this, args);\n };\n }\n\n // Is this an ESM module?\n // https://tc39.es/ecma262/#sec-module-namespace-objects\n if (Object.prototype.toString.call(moduleExports) === '[object Module]') {\n // In ESM we take the usual route and just replace the exports we want to instrument\n for (const method of INSTRUMENTED_METHODS) {\n moduleExports[method] = generatePatch(moduleExports[method]);\n }\n\n return moduleExports;\n } else {\n // In CJS we can't replace the exports in the original module because they\n // don't have setters, so we create a new object with the same properties\n const patchedModuleExports = INSTRUMENTED_METHODS.reduce((acc, curr) => {\n acc[curr] = generatePatch(moduleExports[curr]);\n return acc;\n }, {} as PatchedModuleExports);\n\n return { ...moduleExports, ...patchedModuleExports };\n }\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition"],"mappings":";;;;;AAKA;AACA;AACA,MAAM,uBAAuB;AAC7B,EAAE,cAAc;AAChB,EAAE,YAAY;AACd,EAAE,gBAAgB;AAClB,EAAE,cAAc;AAChB,EAAE,OAAO;AACT,EAAE,WAAW;AACb,CAAE;;AAWF;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,6BAA8B,SAAQA,mCAAoB,CAAA;AACvE,GAAE,MAAA,GAAA,CAAA,IAAA,CAAQ,UAAW,GAAE,MAAK;AAC5B,GAAU,OAAA,GAAA,CAAA,IAAA,CAAA,UAAU,GAAmB,GAAE;;AAEzC,GAAS,WAAW,CAAC,MAAM,GAA0B,EAAE,EAAE;AACzD,IAAI,KAAK,CAAC,mCAAmC,EAAEC,gBAAW,EAAE,MAAM,CAAC,CAAA,6BAAA,CAAA,SAAA,CAAA,MAAA,CAAA,IAAA,CAAA,IAAA,CAAA,CAAA,6BAAA,CAAA,SAAA,CAAA,OAAA,CAAA,IAAA,CAAA,IAAA,CAAA,CACnE;;AAEA;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,SAAS,IAAIC,mDAAmC,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxG,IAAI,OAAO,MAAM;AACjB;;AAEA;AACA;AACA;AACA;AACA,GAAS,eAAe,CAAC,QAAQ,EAAoB;AACrD,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,QAAQ,EAAE;AAChB,WAAW;AACX,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;AACpC;AACA;;AAEA;AACA;AACA;AACA,GAAU,MAAM,CAAC,aAAa,EAAiC;AAC/D,IAAI,IAAI,CAAC,UAAW,GAAE,IAAI;;AAE1B,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAA,IAAY,QAAQ,EAAE,CAAC;AACnD,IAAI,IAAI,CAAC,UAAW,GAAE,EAAE;;AAExB,IAAI,SAAS,aAAa,CAAC,cAAc,EAAoC;AAC7E,MAAM,OAAO,CAAC,GAAG,IAAI,KAAiB;AACtC,QAAQ,MAAM,6BAA8B,GAAE,IAAI,CAAC,CAAC,CAAC,CAAC,sBAAA,IAA0B,EAAE;AAClF,QAAQ,MAAM,SAAA,GAAY,6BAA6B,CAAC,SAAS;;AAEjE;AACA;AACA,QAAQ,IAAI,SAAU,KAAI,SAAS,EAAE;AACrC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,yBAAyB;AAC3C,YAAY,SAAS,EAAE,IAAI;AAC3B,YAAY,YAAY,EAAE,KAAK;AAC/B,YAAY,aAAa,EAAE,KAAK;AAChC,YAAY,GAAG,6BAA6B;AAC5C,WAAW;AACX;;AAEA;AACA,QAAQ,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;AAC/C,OAAO;AACP;;AAEA;AACA;AACA,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAE,KAAI,iBAAiB,EAAE;AAC7E;AACA,MAAM,KAAK,MAAM,MAAO,IAAG,oBAAoB,EAAE;AACjD,QAAQ,aAAa,CAAC,MAAM,CAAE,GAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;AACpE;;AAEA,MAAM,OAAO,aAAa;AAC1B,WAAW;AACX;AACA;AACA,MAAM,MAAM,oBAAA,GAAuB,oBAAoB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK;AAC9E,QAAQ,GAAG,CAAC,IAAI,CAAE,GAAE,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AACtD,QAAQ,OAAO,GAAG;AAClB,OAAO,EAAE,EAAC,EAA0B;;AAEpC,MAAM,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,sBAAsB;AAC1D;AACA;AACA;;;;"}
1
+ {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/vercelai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig, InstrumentationModuleDefinition } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport { getCurrentScope, SDK_VERSION } from '@sentry/core';\nimport { INTEGRATION_NAME } from './constants';\nimport type { TelemetrySettings, VercelAiIntegration } from './types';\n\n// List of patched methods\n// From: https://sdk.vercel.ai/docs/ai-sdk-core/telemetry#collected-data\nconst INSTRUMENTED_METHODS = [\n 'generateText',\n 'streamText',\n 'generateObject',\n 'streamObject',\n 'embed',\n 'embedMany',\n] as const;\n\ninterface MethodFirstArg extends Record<string, unknown> {\n experimental_telemetry?: TelemetrySettings;\n}\n\ntype MethodArgs = [MethodFirstArg, ...unknown[]];\n\ntype PatchedModuleExports = Record<(typeof INSTRUMENTED_METHODS)[number], (...args: MethodArgs) => unknown> &\n Record<string, unknown>;\n\ninterface RecordingOptions {\n recordInputs?: boolean;\n recordOutputs?: boolean;\n}\n\n/**\n * Determines whether to record inputs and outputs for Vercel AI telemetry based on the configuration hierarchy.\n *\n * The order of precedence is:\n * 1. The vercel ai integration options\n * 2. The experimental_telemetry options in the vercel ai method calls\n * 3. When telemetry is explicitly enabled (isEnabled: true), default to recording\n * 4. Otherwise, use the sendDefaultPii option from client options\n */\nexport function determineRecordingSettings(\n integrationRecordingOptions: RecordingOptions | undefined,\n methodTelemetryOptions: RecordingOptions,\n telemetryExplicitlyEnabled: boolean | undefined,\n defaultRecordingEnabled: boolean,\n): { recordInputs: boolean; recordOutputs: boolean } {\n const recordInputs =\n integrationRecordingOptions?.recordInputs !== undefined\n ? integrationRecordingOptions.recordInputs\n : methodTelemetryOptions.recordInputs !== undefined\n ? methodTelemetryOptions.recordInputs\n : telemetryExplicitlyEnabled === true\n ? true // When telemetry is explicitly enabled, default to recording inputs\n : defaultRecordingEnabled;\n\n const recordOutputs =\n integrationRecordingOptions?.recordOutputs !== undefined\n ? integrationRecordingOptions.recordOutputs\n : methodTelemetryOptions.recordOutputs !== undefined\n ? methodTelemetryOptions.recordOutputs\n : telemetryExplicitlyEnabled === true\n ? true // When telemetry is explicitly enabled, default to recording inputs\n : defaultRecordingEnabled;\n\n return { recordInputs, recordOutputs };\n}\n\n/**\n * This detects is added by the Sentry Vercel AI Integration to detect if the integration should\n * be enabled.\n *\n * It also patches the `ai` module to enable Vercel AI telemetry automatically for all methods.\n */\nexport class SentryVercelAiInstrumentation extends InstrumentationBase {\n private _isPatched = false;\n private _callbacks: (() => void)[] = [];\n\n public constructor(config: InstrumentationConfig = {}) {\n super('@sentry/instrumentation-vercel-ai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition('ai', ['>=3.0.0 <5'], this._patch.bind(this));\n return module;\n }\n\n /**\n * Call the provided callback when the module is patched.\n * If it has already been patched, the callback will be called immediately.\n */\n public callWhenPatched(callback: () => void): void {\n if (this._isPatched) {\n callback();\n } else {\n this._callbacks.push(callback);\n }\n }\n\n /**\n * Patches module exports to enable Vercel AI telemetry.\n */\n private _patch(moduleExports: PatchedModuleExports): unknown {\n this._isPatched = true;\n\n this._callbacks.forEach(callback => callback());\n this._callbacks = [];\n\n function generatePatch(originalMethod: (...args: MethodArgs) => unknown) {\n return (...args: MethodArgs) => {\n const existingExperimentalTelemetry = args[0].experimental_telemetry || {};\n const isEnabled = existingExperimentalTelemetry.isEnabled;\n\n const client = getCurrentScope().getClient();\n const integration = client?.getIntegrationByName<VercelAiIntegration>(INTEGRATION_NAME);\n const integrationOptions = integration?.options;\n const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false;\n\n const { recordInputs, recordOutputs } = determineRecordingSettings(\n integrationOptions,\n existingExperimentalTelemetry,\n isEnabled,\n shouldRecordInputsAndOutputs,\n );\n\n args[0].experimental_telemetry = {\n ...existingExperimentalTelemetry,\n isEnabled: isEnabled !== undefined ? isEnabled : true,\n recordInputs,\n recordOutputs,\n };\n\n // @ts-expect-error we know that the method exists\n return originalMethod.apply(this, args);\n };\n }\n\n // Is this an ESM module?\n // https://tc39.es/ecma262/#sec-module-namespace-objects\n if (Object.prototype.toString.call(moduleExports) === '[object Module]') {\n // In ESM we take the usual route and just replace the exports we want to instrument\n for (const method of INSTRUMENTED_METHODS) {\n moduleExports[method] = generatePatch(moduleExports[method]);\n }\n\n return moduleExports;\n } else {\n // In CJS we can't replace the exports in the original module because they\n // don't have setters, so we create a new object with the same properties\n const patchedModuleExports = INSTRUMENTED_METHODS.reduce((acc, curr) => {\n acc[curr] = generatePatch(moduleExports[curr]);\n return acc;\n }, {} as PatchedModuleExports);\n\n return { ...moduleExports, ...patchedModuleExports };\n }\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","getCurrentScope","INTEGRATION_NAME"],"mappings":"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"}
@@ -44,6 +44,7 @@ export { createGetModuleFromFilename } from './utils/module.js';
44
44
  export { makeNodeTransport } from './transports/http.js';
45
45
  export { NodeClient } from './sdk/client.js';
46
46
  export { cron } from './cron/index.js';
47
+ export { NODE_VERSION } from './nodeVersion.js';
47
48
  export { setOpenTelemetryContextAsyncContextStrategy as setNodeAsyncContextStrategy } from '@sentry/opentelemetry';
48
49
  export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, inboundFiltersIntegration, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, parameterize, profiler, requestDataIntegration, rewriteFramesIntegration, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
49
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}