@sentry/node 9.32.0 → 9.33.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 (48) 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/fastify/index.js +42 -5
  6. package/build/cjs/integrations/tracing/fastify/index.js.map +1 -1
  7. package/build/cjs/integrations/tracing/index.js +3 -0
  8. package/build/cjs/integrations/tracing/index.js.map +1 -1
  9. package/build/cjs/integrations/tracing/postgresjs.js +283 -0
  10. package/build/cjs/integrations/tracing/postgresjs.js.map +1 -0
  11. package/build/cjs/integrations/tracing/vercelai/index.js +7 -183
  12. package/build/cjs/integrations/tracing/vercelai/index.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/fastify/index.js +43 -6
  20. package/build/esm/integrations/tracing/fastify/index.js.map +1 -1
  21. package/build/esm/integrations/tracing/index.js +3 -0
  22. package/build/esm/integrations/tracing/index.js.map +1 -1
  23. package/build/esm/integrations/tracing/postgresjs.js +279 -0
  24. package/build/esm/integrations/tracing/postgresjs.js.map +1 -0
  25. package/build/esm/integrations/tracing/vercelai/index.js +8 -184
  26. package/build/esm/integrations/tracing/vercelai/index.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/fastify/index.d.ts +1 -1
  31. package/build/types/integrations/tracing/fastify/index.d.ts.map +1 -1
  32. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  33. package/build/types/integrations/tracing/postgresjs.d.ts +81 -0
  34. package/build/types/integrations/tracing/postgresjs.d.ts.map +1 -0
  35. package/build/types/integrations/tracing/vercelai/index.d.ts +5 -7
  36. package/build/types/integrations/tracing/vercelai/index.d.ts.map +1 -1
  37. package/build/types-ts3.8/index.d.ts +1 -0
  38. package/build/types-ts3.8/integrations/tracing/fastify/index.d.ts +1 -1
  39. package/build/types-ts3.8/integrations/tracing/postgresjs.d.ts +81 -0
  40. package/build/types-ts3.8/integrations/tracing/vercelai/index.d.ts +5 -7
  41. package/package.json +3 -3
  42. package/build/cjs/integrations/tracing/vercelai/ai_sdk_attributes.js +0 -168
  43. package/build/cjs/integrations/tracing/vercelai/ai_sdk_attributes.js.map +0 -1
  44. package/build/esm/integrations/tracing/vercelai/ai_sdk_attributes.js +0 -152
  45. package/build/esm/integrations/tracing/vercelai/ai_sdk_attributes.js.map +0 -1
  46. package/build/types/integrations/tracing/vercelai/ai_sdk_attributes.d.ts +0 -669
  47. package/build/types/integrations/tracing/vercelai/ai_sdk_attributes.d.ts.map +0 -1
  48. package/build/types-ts3.8/integrations/tracing/vercelai/ai_sdk_attributes.d.ts +0 -669
@@ -0,0 +1,283 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const api = require('@opentelemetry/api');
4
+ const instrumentation = require('@opentelemetry/instrumentation');
5
+ const semanticConventions = require('@opentelemetry/semantic-conventions');
6
+ const core = require('@sentry/core');
7
+ const instrument = require('../../otel/instrument.js');
8
+ const addOriginToSpan = require('../../utils/addOriginToSpan.js');
9
+
10
+ // Instrumentation for https://github.com/porsager/postgres
11
+
12
+ const INTEGRATION_NAME = 'PostgresJs';
13
+ const SUPPORTED_VERSIONS = ['>=3.0.0 <4'];
14
+
15
+ const instrumentPostgresJs = instrument.generateInstrumentOnce(
16
+ INTEGRATION_NAME,
17
+ (options) =>
18
+ new PostgresJsInstrumentation({
19
+ requireParentSpan: options?.requireParentSpan ?? true,
20
+ requestHook: options?.requestHook,
21
+ }),
22
+ );
23
+
24
+ /**
25
+ * Instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.
26
+ * This instrumentation captures postgresjs queries and their attributes,
27
+ */
28
+ class PostgresJsInstrumentation extends instrumentation.InstrumentationBase {
29
+ constructor(config) {
30
+ super('sentry-postgres-js', core.SDK_VERSION, config);
31
+ }
32
+
33
+ /**
34
+ * Initializes the instrumentation.
35
+ */
36
+ init() {
37
+ const instrumentationModule = new instrumentation.InstrumentationNodeModuleDefinition('postgres', SUPPORTED_VERSIONS);
38
+
39
+ ['src', 'cf/src', 'cjs/src'].forEach(path => {
40
+ instrumentationModule.files.push(
41
+ new instrumentation.InstrumentationNodeModuleFile(
42
+ `postgres/${path}/connection.js`,
43
+ ['*'],
44
+ this._patchConnection.bind(this),
45
+ this._unwrap.bind(this),
46
+ ),
47
+ );
48
+
49
+ instrumentationModule.files.push(
50
+ new instrumentation.InstrumentationNodeModuleFile(
51
+ `postgres/${path}/query.js`,
52
+ SUPPORTED_VERSIONS,
53
+ this._patchQuery.bind(this),
54
+ this._unwrap.bind(this),
55
+ ),
56
+ );
57
+ });
58
+
59
+ return [instrumentationModule];
60
+ }
61
+
62
+ /**
63
+ * Determines whether a span should be created based on the current context.
64
+ * If `requireParentSpan` is set to true in the configuration, a span will
65
+ * only be created if there is a parent span available.
66
+ */
67
+ _shouldCreateSpans() {
68
+ const config = this.getConfig();
69
+ const hasParentSpan = api.trace.getSpan(api.context.active()) !== undefined;
70
+ return hasParentSpan || !config.requireParentSpan;
71
+ }
72
+
73
+ /**
74
+ * Patches the reject method of the Query class to set the span status and end it
75
+ */
76
+ _patchReject(rejectTarget, span) {
77
+ return new Proxy(rejectTarget, {
78
+ apply: (
79
+ rejectTarget,
80
+ rejectThisArg,
81
+ rejectArgs
82
+
83
+ ,
84
+ ) => {
85
+ span.setStatus({
86
+ code: core.SPAN_STATUS_ERROR,
87
+ // This message is the error message from the rejectArgs, when available
88
+ // e.g "relation 'User' does not exist"
89
+ message: rejectArgs?.[0]?.message || 'unknown_error',
90
+ });
91
+
92
+ const result = Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);
93
+
94
+ // This status code is PG error code, e.g. '42P01' for "relation does not exist"
95
+ // https://www.postgresql.org/docs/current/errcodes-appendix.html
96
+ span.setAttribute(semanticConventions.ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || 'Unknown error');
97
+ // This is the error type, e.g. 'PostgresError' for a Postgres error
98
+ span.setAttribute(semanticConventions.ATTR_ERROR_TYPE, rejectArgs?.[0]?.name || 'Unknown error');
99
+
100
+ span.end();
101
+ return result;
102
+ },
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Patches the resolve method of the Query class to end the span when the query is resolved.
108
+ */
109
+ _patchResolve(resolveTarget, span) {
110
+ return new Proxy(resolveTarget, {
111
+ apply: (resolveTarget, resolveThisArg, resolveArgs) => {
112
+ const result = Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);
113
+ const sqlCommand = resolveArgs?.[0]?.command;
114
+
115
+ if (sqlCommand) {
116
+ // SQL command is only available when the query is resolved successfully
117
+ span.setAttribute(semanticConventions.ATTR_DB_OPERATION_NAME, sqlCommand);
118
+ }
119
+ span.end();
120
+ return result;
121
+ },
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Patches the Query class to instrument the handle method.
127
+ */
128
+ _patchQuery(moduleExports
129
+
130
+ ) {
131
+ moduleExports.Query.prototype.handle = new Proxy(moduleExports.Query.prototype.handle, {
132
+ apply: async (
133
+ handleTarget,
134
+ handleThisArg
135
+
136
+ ,
137
+ handleArgs,
138
+ ) => {
139
+ if (!this._shouldCreateSpans()) {
140
+ // If we don't need to create spans, just call the original method
141
+ return Reflect.apply(handleTarget, handleThisArg, handleArgs);
142
+ }
143
+
144
+ const sanitizedSqlQuery = this._sanitizeSqlQuery(handleThisArg.strings?.[0]);
145
+
146
+ return core.startSpanManual(
147
+ {
148
+ name: sanitizedSqlQuery || 'postgresjs.query',
149
+ op: 'db',
150
+ },
151
+ (span) => {
152
+ const scope = core.getCurrentScope();
153
+ const postgresConnectionContext = scope.getScopeData().contexts['postgresjsConnection']
154
+
155
+ ;
156
+
157
+ addOriginToSpan.addOriginToSpan(span, 'auto.db.otel.postgres');
158
+
159
+ const { requestHook } = this.getConfig();
160
+
161
+ if (requestHook) {
162
+ instrumentation.safeExecuteInTheMiddle(
163
+ () => requestHook(span, sanitizedSqlQuery, postgresConnectionContext),
164
+ error => {
165
+ if (error) {
166
+ core.logger.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, error);
167
+ }
168
+ },
169
+ );
170
+ }
171
+
172
+ // ATTR_DB_NAMESPACE is used to indicate the database name and the schema name
173
+ // It's only the database name as we don't have the schema information
174
+ const databaseName = postgresConnectionContext?.ATTR_DB_NAMESPACE || '<unknown database>';
175
+ const databaseHost = postgresConnectionContext?.ATTR_SERVER_ADDRESS || '<unknown host>';
176
+ const databasePort = postgresConnectionContext?.ATTR_SERVER_PORT || '<unknown port>';
177
+
178
+ span.setAttribute(semanticConventions.ATTR_DB_SYSTEM_NAME, 'postgres');
179
+ span.setAttribute(semanticConventions.ATTR_DB_NAMESPACE, databaseName);
180
+ span.setAttribute(semanticConventions.ATTR_SERVER_ADDRESS, databaseHost);
181
+ span.setAttribute(semanticConventions.ATTR_SERVER_PORT, databasePort);
182
+ span.setAttribute(semanticConventions.ATTR_DB_QUERY_TEXT, sanitizedSqlQuery);
183
+
184
+ handleThisArg.resolve = this._patchResolve(handleThisArg.resolve, span);
185
+ handleThisArg.reject = this._patchReject(handleThisArg.reject, span);
186
+
187
+ try {
188
+ return Reflect.apply(handleTarget, handleThisArg, handleArgs);
189
+ } catch (error) {
190
+ span.setStatus({
191
+ code: core.SPAN_STATUS_ERROR,
192
+ });
193
+ span.end();
194
+ throw error; // Re-throw the error to propagate it
195
+ }
196
+ },
197
+ );
198
+ },
199
+ });
200
+
201
+ return moduleExports;
202
+ }
203
+
204
+ /**
205
+ * Patches the Connection class to set the database, host, and port attributes
206
+ * when a new connection is created.
207
+ */
208
+ _patchConnection(Connection) {
209
+ return new Proxy(Connection, {
210
+ apply: (connectionTarget, thisArg, connectionArgs) => {
211
+ const databaseName = connectionArgs[0]?.database || '<unknown database>';
212
+ const databaseHost = connectionArgs[0]?.host?.[0] || '<unknown host>';
213
+ const databasePort = connectionArgs[0]?.port?.[0] || '<unknown port>';
214
+
215
+ const scope = core.getCurrentScope();
216
+ scope.setContext('postgresjsConnection', {
217
+ ATTR_DB_NAMESPACE: databaseName,
218
+ ATTR_SERVER_ADDRESS: databaseHost,
219
+ ATTR_SERVER_PORT: databasePort,
220
+ });
221
+
222
+ return Reflect.apply(connectionTarget, thisArg, connectionArgs);
223
+ },
224
+ });
225
+ }
226
+
227
+ /**
228
+ * Sanitize SQL query as per the OTEL semantic conventions
229
+ * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext
230
+ */
231
+ _sanitizeSqlQuery(sqlQuery) {
232
+ if (!sqlQuery) {
233
+ return 'Unknown SQL Query';
234
+ }
235
+
236
+ return (
237
+ sqlQuery
238
+ .replace(/\s+/g, ' ')
239
+ .trim() // Remove extra spaces including newlines and trim
240
+ .substring(0, 1024) // Truncate to 1024 characters
241
+ .replace(/--.*?(\r?\n|$)/g, '') // Single line comments
242
+ .replace(/\/\*[\s\S]*?\*\//g, '') // Multi-line comments
243
+ .replace(/;\s*$/, '') // Remove trailing semicolons
244
+ .replace(/\b\d+\b/g, '?') // Replace standalone numbers
245
+ // Collapse whitespace to a single space
246
+ .replace(/\s+/g, ' ')
247
+ // Collapse IN and in clauses
248
+ // eg. IN (?, ?, ?, ?) to IN (?)
249
+ .replace(/\bIN\b\s*\(\s*\?(?:\s*,\s*\?)*\s*\)/g, 'IN (?)')
250
+ );
251
+ }
252
+ }
253
+
254
+ const _postgresJsIntegration = (() => {
255
+ return {
256
+ name: INTEGRATION_NAME,
257
+ setupOnce() {
258
+ instrumentPostgresJs();
259
+ },
260
+ };
261
+ }) ;
262
+
263
+ /**
264
+ * Adds Sentry tracing instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.
265
+ *
266
+ * For more information, see the [`postgresIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/postgres/).
267
+ *
268
+ * @example
269
+ * ```javascript
270
+ * const Sentry = require('@sentry/node');
271
+ *
272
+ * Sentry.init({
273
+ * integrations: [Sentry.postgresJsIntegration()],
274
+ * });
275
+ * ```
276
+ */
277
+
278
+ const postgresJsIntegration = core.defineIntegration(_postgresJsIntegration);
279
+
280
+ exports.PostgresJsInstrumentation = PostgresJsInstrumentation;
281
+ exports.instrumentPostgresJs = instrumentPostgresJs;
282
+ exports.postgresJsIntegration = postgresJsIntegration;
283
+ //# sourceMappingURL=postgresjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresjs.js","sources":["../../../../src/integrations/tracing/postgresjs.ts"],"sourcesContent":["// Instrumentation for https://github.com/porsager/postgres\nimport { context, trace } from '@opentelemetry/api';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n safeExecuteInTheMiddle,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_NAMESPACE,\n ATTR_DB_OPERATION_NAME,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_RESPONSE_STATUS_CODE,\n ATTR_DB_SYSTEM_NAME,\n ATTR_ERROR_TYPE,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n defineIntegration,\n getCurrentScope,\n logger,\n SDK_VERSION,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\nimport { addOriginToSpan } from '../../utils/addOriginToSpan';\n\nconst INTEGRATION_NAME = 'PostgresJs';\nconst SUPPORTED_VERSIONS = ['>=3.0.0 <4'];\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string; // Database name\n ATTR_SERVER_ADDRESS?: string; // Hostname or IP address of the database server\n ATTR_SERVER_PORT?: string; // Port number of the database server\n};\n\ntype PostgresJsInstrumentationConfig = InstrumentationConfig & {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n};\n\nexport const instrumentPostgresJs = generateInstrumentOnce(\n INTEGRATION_NAME,\n (options?: PostgresJsInstrumentationConfig) =>\n new PostgresJsInstrumentation({\n requireParentSpan: options?.requireParentSpan ?? true,\n requestHook: options?.requestHook,\n }),\n);\n\n/**\n * Instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n * This instrumentation captures postgresjs queries and their attributes,\n */\nexport class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsInstrumentationConfig> {\n public constructor(config: PostgresJsInstrumentationConfig) {\n super('sentry-postgres-js', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation.\n */\n public init(): InstrumentationNodeModuleDefinition[] {\n const instrumentationModule = new InstrumentationNodeModuleDefinition('postgres', SUPPORTED_VERSIONS);\n\n ['src', 'cf/src', 'cjs/src'].forEach(path => {\n instrumentationModule.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/connection.js`,\n ['*'],\n this._patchConnection.bind(this),\n this._unwrap.bind(this),\n ),\n );\n\n instrumentationModule.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/query.js`,\n SUPPORTED_VERSIONS,\n this._patchQuery.bind(this),\n this._unwrap.bind(this),\n ),\n );\n });\n\n return [instrumentationModule];\n }\n\n /**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the configuration, a span will\n * only be created if there is a parent span available.\n */\n private _shouldCreateSpans(): boolean {\n const config = this.getConfig();\n const hasParentSpan = trace.getSpan(context.active()) !== undefined;\n return hasParentSpan || !config.requireParentSpan;\n }\n\n /**\n * Patches the reject method of the Query class to set the span status and end it\n */\n private _patchReject(rejectTarget: any, span: Span): any {\n return new Proxy(rejectTarget, {\n apply: (\n rejectTarget,\n rejectThisArg,\n rejectArgs: {\n message?: string;\n code?: string;\n name?: string;\n }[],\n ) => {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n // This message is the error message from the rejectArgs, when available\n // e.g \"relation 'User' does not exist\"\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n\n const result = Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n\n // This status code is PG error code, e.g. '42P01' for \"relation does not exist\"\n // https://www.postgresql.org/docs/current/errcodes-appendix.html\n span.setAttribute(ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || 'Unknown error');\n // This is the error type, e.g. 'PostgresError' for a Postgres error\n span.setAttribute(ATTR_ERROR_TYPE, rejectArgs?.[0]?.name || 'Unknown error');\n\n span.end();\n return result;\n },\n });\n }\n\n /**\n * Patches the resolve method of the Query class to end the span when the query is resolved.\n */\n private _patchResolve(resolveTarget: any, span: Span): any {\n return new Proxy(resolveTarget, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n const result = Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n const sqlCommand = resolveArgs?.[0]?.command;\n\n if (sqlCommand) {\n // SQL command is only available when the query is resolved successfully\n span.setAttribute(ATTR_DB_OPERATION_NAME, sqlCommand);\n }\n span.end();\n return result;\n },\n });\n }\n\n /**\n * Patches the Query class to instrument the handle method.\n */\n private _patchQuery(moduleExports: {\n Query: {\n prototype: {\n handle: any;\n };\n };\n }): any {\n moduleExports.Query.prototype.handle = new Proxy(moduleExports.Query.prototype.handle, {\n apply: async (\n handleTarget,\n handleThisArg: {\n resolve: any;\n reject: any;\n strings?: string[];\n },\n handleArgs,\n ) => {\n if (!this._shouldCreateSpans()) {\n // If we don't need to create spans, just call the original method\n return Reflect.apply(handleTarget, handleThisArg, handleArgs);\n }\n\n const sanitizedSqlQuery = this._sanitizeSqlQuery(handleThisArg.strings?.[0]);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n const scope = getCurrentScope();\n const postgresConnectionContext = scope.getScopeData().contexts['postgresjsConnection'] as\n | PostgresConnectionContext\n | undefined;\n\n addOriginToSpan(span, 'auto.db.otel.postgres');\n\n const { requestHook } = this.getConfig();\n\n if (requestHook) {\n safeExecuteInTheMiddle(\n () => requestHook(span, sanitizedSqlQuery, postgresConnectionContext),\n error => {\n if (error) {\n logger.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, error);\n }\n },\n );\n }\n\n // ATTR_DB_NAMESPACE is used to indicate the database name and the schema name\n // It's only the database name as we don't have the schema information\n const databaseName = postgresConnectionContext?.ATTR_DB_NAMESPACE || '<unknown database>';\n const databaseHost = postgresConnectionContext?.ATTR_SERVER_ADDRESS || '<unknown host>';\n const databasePort = postgresConnectionContext?.ATTR_SERVER_PORT || '<unknown port>';\n\n span.setAttribute(ATTR_DB_SYSTEM_NAME, 'postgres');\n span.setAttribute(ATTR_DB_NAMESPACE, databaseName);\n span.setAttribute(ATTR_SERVER_ADDRESS, databaseHost);\n span.setAttribute(ATTR_SERVER_PORT, databasePort);\n span.setAttribute(ATTR_DB_QUERY_TEXT, sanitizedSqlQuery);\n\n handleThisArg.resolve = this._patchResolve(handleThisArg.resolve, span);\n handleThisArg.reject = this._patchReject(handleThisArg.reject, span);\n\n try {\n return Reflect.apply(handleTarget, handleThisArg, handleArgs);\n } catch (error) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n });\n span.end();\n throw error; // Re-throw the error to propagate it\n }\n },\n );\n },\n });\n\n return moduleExports;\n }\n\n /**\n * Patches the Connection class to set the database, host, and port attributes\n * when a new connection is created.\n */\n private _patchConnection(Connection: any): any {\n return new Proxy(Connection, {\n apply: (connectionTarget, thisArg, connectionArgs: { database: string; host: string[]; port: number[] }[]) => {\n const databaseName = connectionArgs[0]?.database || '<unknown database>';\n const databaseHost = connectionArgs[0]?.host?.[0] || '<unknown host>';\n const databasePort = connectionArgs[0]?.port?.[0] || '<unknown port>';\n\n const scope = getCurrentScope();\n scope.setContext('postgresjsConnection', {\n ATTR_DB_NAMESPACE: databaseName,\n ATTR_SERVER_ADDRESS: databaseHost,\n ATTR_SERVER_PORT: databasePort,\n });\n\n return Reflect.apply(connectionTarget, thisArg, connectionArgs);\n },\n });\n }\n\n /**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n */\n private _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n return (\n sqlQuery\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces including newlines and trim\n .substring(0, 1024) // Truncate to 1024 characters\n .replace(/--.*?(\\r?\\n|$)/g, '') // Single line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n .replace(/\\b\\d+\\b/g, '?') // Replace standalone numbers\n // Collapse whitespace to a single space\n .replace(/\\s+/g, ' ')\n // Collapse IN and in clauses\n // eg. IN (?, ?, ?, ?) to IN (?)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/g, 'IN (?)')\n );\n }\n}\n\nconst _postgresJsIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPostgresJs();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n *\n * For more information, see the [`postgresIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/postgres/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.postgresJsIntegration()],\n * });\n * ```\n */\n\nexport const postgresJsIntegration = defineIntegration(_postgresJsIntegration);\n"],"names":["generateInstrumentOnce","InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","trace","context","SPAN_STATUS_ERROR","ATTR_DB_RESPONSE_STATUS_CODE","ATTR_ERROR_TYPE","ATTR_DB_OPERATION_NAME","startSpanManual","getCurrentScope","addOriginToSpan","safeExecuteInTheMiddle","logger","ATTR_DB_SYSTEM_NAME","ATTR_DB_NAMESPACE","ATTR_SERVER_ADDRESS","ATTR_SERVER_PORT","ATTR_DB_QUERY_TEXT","defineIntegration"],"mappings":"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"}
@@ -2,8 +2,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const core = require('@sentry/core');
4
4
  const instrument = require('../../../otel/instrument.js');
5
- const addOriginToSpan = require('../../../utils/addOriginToSpan.js');
6
- const ai_sdk_attributes = require('./ai_sdk_attributes.js');
7
5
  const constants = require('./constants.js');
8
6
  const instrumentation = require('./instrumentation.js');
9
7
 
@@ -28,175 +26,14 @@ const _vercelAIIntegration = ((options = {}) => {
28
26
  instrumentation = instrumentVercelAi();
29
27
  },
30
28
  afterAllSetup(client) {
31
- function registerProcessors() {
32
- client.on('spanStart', span => {
33
- const { data: attributes, description: name } = core.spanToJSON(span);
34
-
35
- if (!name) {
36
- return;
37
- }
38
-
39
- // Tool call spans
40
- // https://ai-sdk.dev/docs/ai-sdk-core/telemetry#tool-call-spans
41
- if (
42
- attributes[ai_sdk_attributes.AI_TOOL_CALL_NAME_ATTRIBUTE] &&
43
- attributes[ai_sdk_attributes.AI_TOOL_CALL_ID_ATTRIBUTE] &&
44
- name === 'ai.toolCall'
45
- ) {
46
- addOriginToSpan.addOriginToSpan(span, 'auto.vercelai.otel');
47
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.execute_tool');
48
- span.setAttribute('gen_ai.tool.call.id', attributes[ai_sdk_attributes.AI_TOOL_CALL_ID_ATTRIBUTE]);
49
- span.setAttribute('gen_ai.tool.name', attributes[ai_sdk_attributes.AI_TOOL_CALL_NAME_ATTRIBUTE]);
50
- span.updateName(`execute_tool ${attributes[ai_sdk_attributes.AI_TOOL_CALL_NAME_ATTRIBUTE]}`);
51
- return;
52
- }
53
-
54
- // The AI and Provider must be defined for generate, stream, and embed spans.
55
- // The id of the model
56
- const aiModelId = attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE];
57
- // the provider of the model
58
- const aiModelProvider = attributes[ai_sdk_attributes.AI_MODEL_PROVIDER_ATTRIBUTE];
59
- if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) {
60
- return;
61
- }
62
-
63
- addOriginToSpan.addOriginToSpan(span, 'auto.vercelai.otel');
64
-
65
- const nameWthoutAi = name.replace('ai.', '');
66
- span.setAttribute('ai.pipeline.name', nameWthoutAi);
67
- span.updateName(nameWthoutAi);
68
-
69
- // If a Telemetry name is set and it is a pipeline span, use that as the operation name
70
- const functionId = attributes[ai_sdk_attributes.AI_TELEMETRY_FUNCTION_ID_ATTRIBUTE];
71
- if (functionId && typeof functionId === 'string' && name.split('.').length - 1 === 1) {
72
- span.updateName(`${nameWthoutAi} ${functionId}`);
73
- span.setAttribute('ai.pipeline.name', functionId);
74
- }
75
-
76
- if (attributes[ai_sdk_attributes.AI_PROMPT_ATTRIBUTE]) {
77
- span.setAttribute('gen_ai.prompt', attributes[ai_sdk_attributes.AI_PROMPT_ATTRIBUTE]);
78
- }
79
- if (attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE] && !attributes[ai_sdk_attributes.GEN_AI_RESPONSE_MODEL_ATTRIBUTE]) {
80
- span.setAttribute(ai_sdk_attributes.GEN_AI_RESPONSE_MODEL_ATTRIBUTE, attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]);
81
- }
82
- span.setAttribute('ai.streaming', name.includes('stream'));
83
-
84
- // Generate Spans
85
- if (name === 'ai.generateText') {
86
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.invoke_agent');
87
- return;
88
- }
89
-
90
- if (name === 'ai.generateText.doGenerate') {
91
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.generate_text');
92
- span.updateName(`generate_text ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
93
- return;
94
- }
95
-
96
- if (name === 'ai.streamText') {
97
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.invoke_agent');
98
- return;
99
- }
100
-
101
- if (name === 'ai.streamText.doStream') {
102
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.stream_text');
103
- span.updateName(`stream_text ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
104
- return;
105
- }
106
-
107
- if (name === 'ai.generateObject') {
108
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.invoke_agent');
109
- return;
110
- }
111
-
112
- if (name === 'ai.generateObject.doGenerate') {
113
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.generate_object');
114
- span.updateName(`generate_object ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
115
- return;
116
- }
117
-
118
- if (name === 'ai.streamObject') {
119
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.invoke_agent');
120
- return;
121
- }
122
-
123
- if (name === 'ai.streamObject.doStream') {
124
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.stream_object');
125
- span.updateName(`stream_object ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
126
- return;
127
- }
128
-
129
- if (name === 'ai.embed') {
130
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.invoke_agent');
131
- return;
132
- }
133
-
134
- if (name === 'ai.embed.doEmbed') {
135
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.embed');
136
- span.updateName(`embed ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
137
- return;
138
- }
139
-
140
- if (name === 'ai.embedMany') {
141
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.invoke_agent');
142
- return;
143
- }
144
-
145
- if (name === 'ai.embedMany.doEmbed') {
146
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'gen_ai.embed_many');
147
- span.updateName(`embed_many ${attributes[ai_sdk_attributes.AI_MODEL_ID_ATTRIBUTE]}`);
148
- return;
149
- }
150
-
151
- if (name.startsWith('ai.stream')) {
152
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run');
153
- return;
154
- }
155
- });
156
-
157
- client.addEventProcessor(event => {
158
- if (event.type === 'transaction' && event.spans?.length) {
159
- for (const span of event.spans) {
160
- const { data: attributes, description: name } = span;
161
-
162
- if (!name || span.origin !== 'auto.vercelai.otel') {
163
- continue;
164
- }
165
-
166
- renameAttributeKey(
167
- attributes,
168
- ai_sdk_attributes.AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE,
169
- ai_sdk_attributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,
170
- );
171
- renameAttributeKey(attributes, ai_sdk_attributes.AI_USAGE_PROMPT_TOKENS_ATTRIBUTE, ai_sdk_attributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE);
172
- if (
173
- typeof attributes[ai_sdk_attributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] === 'number' &&
174
- typeof attributes[ai_sdk_attributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE] === 'number'
175
- ) {
176
- attributes['gen_ai.usage.total_tokens'] =
177
- attributes[ai_sdk_attributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE] + attributes[ai_sdk_attributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE];
178
- }
179
-
180
- // Rename AI SDK attributes to standardized gen_ai attributes
181
- renameAttributeKey(attributes, ai_sdk_attributes.AI_PROMPT_MESSAGES_ATTRIBUTE, 'gen_ai.request.messages');
182
- renameAttributeKey(attributes, ai_sdk_attributes.AI_RESPONSE_TEXT_ATTRIBUTE, 'gen_ai.response.text');
183
- renameAttributeKey(attributes, ai_sdk_attributes.AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, 'gen_ai.response.tool_calls');
184
- renameAttributeKey(attributes, ai_sdk_attributes.AI_PROMPT_TOOLS_ATTRIBUTE, 'gen_ai.request.available_tools');
185
- }
186
- }
187
-
188
- return event;
189
- });
190
- }
191
-
192
29
  // Auto-detect if we should force the integration when running with 'ai' package available
193
30
  // Note that this can only be detected if the 'Modules' integration is available, and running in CJS mode
194
31
  const shouldForce = options.force ?? shouldForceIntegration(client);
195
32
 
196
33
  if (shouldForce) {
197
- registerProcessors();
34
+ core.addVercelAiProcessors(client);
198
35
  } else {
199
- instrumentation?.callWhenPatched(registerProcessors);
36
+ instrumentation?.callWhenPatched(() => core.addVercelAiProcessors(client));
200
37
  }
201
38
  },
202
39
  };
@@ -204,6 +41,7 @@ const _vercelAIIntegration = ((options = {}) => {
204
41
 
205
42
  /**
206
43
  * Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.
44
+ * This integration is not enabled by default, you need to manually add it.
207
45
  *
208
46
  * For more information, see the [`ai` documentation](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).
209
47
  *
@@ -216,17 +54,14 @@ const _vercelAIIntegration = ((options = {}) => {
216
54
  * });
217
55
  * ```
218
56
  *
219
- * The integration automatically detects when to force registration in CommonJS environments
220
- * when the 'ai' package is available. You can still manually set the `force` option if needed.
221
- *
222
- * By default this integration adds tracing support to all `ai` function calls. If you need to disable
223
- * collecting spans for a specific call, you can do so by setting `experimental_telemetry.isEnabled` to
224
- * `false` in the first argument of the function call.
57
+ * This integration adds tracing support to all `ai` function calls.
58
+ * You need to opt-in to collecting spans for a specific call,
59
+ * you can do so by setting `experimental_telemetry.isEnabled` to `true` in the first argument of the function call.
225
60
  *
226
61
  * ```javascript
227
62
  * const result = await generateText({
228
63
  * model: openai('gpt-4-turbo'),
229
- * experimental_telemetry: { isEnabled: false },
64
+ * experimental_telemetry: { isEnabled: true },
230
65
  * });
231
66
  * ```
232
67
  *
@@ -242,17 +77,6 @@ const _vercelAIIntegration = ((options = {}) => {
242
77
  */
243
78
  const vercelAIIntegration = core.defineIntegration(_vercelAIIntegration);
244
79
 
245
- /**
246
- * Renames an attribute key in the provided attributes object if the old key exists.
247
- * This function safely handles null and undefined values.
248
- */
249
- function renameAttributeKey(attributes, oldKey, newKey) {
250
- if (attributes[oldKey] != null) {
251
- attributes[newKey] = attributes[oldKey];
252
- delete attributes[oldKey];
253
- }
254
- }
255
-
256
80
  exports.instrumentVercelAi = instrumentVercelAi;
257
81
  exports.vercelAIIntegration = vercelAIIntegration;
258
82
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
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 { Client, 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 type { modulesIntegration } from '../../modules';\nimport {\n AI_MODEL_ID_ATTRIBUTE,\n AI_MODEL_PROVIDER_ATTRIBUTE,\n AI_PROMPT_ATTRIBUTE,\n AI_PROMPT_MESSAGES_ATTRIBUTE,\n AI_PROMPT_TOOLS_ATTRIBUTE,\n AI_RESPONSE_TEXT_ATTRIBUTE,\n AI_RESPONSE_TOOL_CALLS_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\n/**\n * Determines if the integration should be forced based on environment and package availability.\n * Returns true if the 'ai' package is available.\n */\nfunction shouldForceIntegration(client: Client): boolean {\n const modules = client.getIntegrationByName<ReturnType<typeof modulesIntegration>>('Modules');\n return !!modules?.getModules?.()?.ai;\n}\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 afterAllSetup(client) {\n function registerProcessors(): void {\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, 'gen_ai.invoke_agent');\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, 'gen_ai.invoke_agent');\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, 'gen_ai.invoke_agent');\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, 'gen_ai.invoke_agent');\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, 'gen_ai.invoke_agent');\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, 'gen_ai.invoke_agent');\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 renameAttributeKey(\n attributes,\n AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n );\n renameAttributeKey(attributes, AI_USAGE_PROMPT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE);\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 // Rename AI SDK attributes to standardized gen_ai attributes\n renameAttributeKey(attributes, AI_PROMPT_MESSAGES_ATTRIBUTE, 'gen_ai.request.messages');\n renameAttributeKey(attributes, AI_RESPONSE_TEXT_ATTRIBUTE, 'gen_ai.response.text');\n renameAttributeKey(attributes, AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, 'gen_ai.response.tool_calls');\n renameAttributeKey(attributes, AI_PROMPT_TOOLS_ATTRIBUTE, 'gen_ai.request.available_tools');\n }\n }\n\n return event;\n });\n }\n\n // Auto-detect if we should force the integration when running with 'ai' package available\n // Note that this can only be detected if the 'Modules' integration is available, and running in CJS mode\n const shouldForce = options.force ?? shouldForceIntegration(client);\n\n if (shouldForce) {\n registerProcessors();\n } else {\n instrumentation?.callWhenPatched(registerProcessors);\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 * The integration automatically detects when to force registration in CommonJS environments\n * when the 'ai' package is available. You can still manually set the `force` option if needed.\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\n/**\n * Renames an attribute key in the provided attributes object if the old key exists.\n * This function safely handles null and undefined values.\n */\nfunction renameAttributeKey(attributes: Record<string, unknown>, oldKey: string, newKey: string): void {\n if (attributes[oldKey] != null) {\n attributes[newKey] = attributes[oldKey];\n delete attributes[oldKey];\n }\n}\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","AI_PROMPT_MESSAGES_ATTRIBUTE","AI_RESPONSE_TEXT_ATTRIBUTE","AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","AI_PROMPT_TOOLS_ATTRIBUTE","defineIntegration"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/vercelai/index.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core';\nimport { addVercelAiProcessors, defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../../otel/instrument';\nimport type { modulesIntegration } from '../../modules';\nimport { INTEGRATION_NAME } from './constants';\nimport { SentryVercelAiInstrumentation } from './instrumentation';\nimport type { VercelAiOptions } from './types';\n\nexport const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({}));\n\n/**\n * Determines if the integration should be forced based on environment and package availability.\n * Returns true if the 'ai' package is available.\n */\nfunction shouldForceIntegration(client: Client): boolean {\n const modules = client.getIntegrationByName<ReturnType<typeof modulesIntegration>>('Modules');\n return !!modules?.getModules?.()?.ai;\n}\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 afterAllSetup(client) {\n // Auto-detect if we should force the integration when running with 'ai' package available\n // Note that this can only be detected if the 'Modules' integration is available, and running in CJS mode\n const shouldForce = options.force ?? shouldForceIntegration(client);\n\n if (shouldForce) {\n addVercelAiProcessors(client);\n } else {\n instrumentation?.callWhenPatched(() => addVercelAiProcessors(client));\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.\n * This integration is not enabled by default, you need to manually add it.\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 * This integration adds tracing support to all `ai` function calls.\n * You need to opt-in to collecting spans for a specific call,\n * you can do so by setting `experimental_telemetry.isEnabled` to `true` 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: true },\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","addVercelAiProcessors","defineIntegration"],"mappings":";;;;;;;MAQa,kBAAmB,GAAEA,iCAAsB,CAACC,0BAAgB,EAAE,MAAM,IAAIC,6CAA6B,CAAC,EAAE,CAAC;;AAEtH;AACA;AACA;AACA;AACA,SAAS,sBAAsB,CAAC,MAAM,EAAmB;AACzD,EAAE,MAAM,UAAU,MAAM,CAAC,oBAAoB,CAAwC,SAAS,CAAC;AAC/F,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,EAAE;AACtC;;AAEA,MAAM,oBAAA,IAAwB,CAAC,OAAO,GAAoB,EAAE,KAAK;AACjE,EAAE,IAAI,eAAe;;AAErB,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,0BAAgB;AAC1B,IAAI,OAAO;AACX,IAAI,SAAS,GAAG;AAChB,MAAM,eAAgB,GAAE,kBAAkB,EAAE;AAC5C,KAAK;AACL,IAAI,aAAa,CAAC,MAAM,EAAE;AAC1B;AACA;AACA,MAAM,MAAM,WAAY,GAAE,OAAO,CAAC,SAAS,sBAAsB,CAAC,MAAM,CAAC;;AAEzE,MAAM,IAAI,WAAW,EAAE;AACvB,QAAQE,0BAAqB,CAAC,MAAM,CAAC;AACrC,aAAa;AACb,QAAQ,eAAe,EAAE,eAAe,CAAC,MAAMA,0BAAqB,CAAC,MAAM,CAAC,CAAC;AAC7E;AACA,KAAK;AACL,GAAG;AACH,CAAC,CAAE;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,mBAAoB,GAAEC,sBAAiB,CAAC,oBAAoB;;;;;"}
@@ -21,6 +21,7 @@ export { mysqlIntegration } from './integrations/tracing/mysql.js';
21
21
  export { mysql2Integration } from './integrations/tracing/mysql2.js';
22
22
  export { redisIntegration } from './integrations/tracing/redis.js';
23
23
  export { postgresIntegration } from './integrations/tracing/postgres.js';
24
+ export { postgresJsIntegration } from './integrations/tracing/postgresjs.js';
24
25
  export { prismaIntegration } from './integrations/tracing/prisma.js';
25
26
  export { hapiIntegration, setupHapiErrorHandler } from './integrations/tracing/hapi/index.js';
26
27
  export { koaIntegration, setupKoaErrorHandler } from './integrations/tracing/koa.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}