@sentry/node 10.12.0 → 10.13.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 (58) hide show
  1. package/build/cjs/index.js +9 -7
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/integrations/http.js +24 -13
  4. package/build/cjs/integrations/http.js.map +1 -1
  5. package/build/cjs/integrations/tracing/anthropic-ai/index.js +2 -2
  6. package/build/cjs/integrations/tracing/anthropic-ai/index.js.map +1 -1
  7. package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js +6 -17
  8. package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
  9. package/build/cjs/integrations/tracing/google-genai/index.js +78 -0
  10. package/build/cjs/integrations/tracing/google-genai/index.js.map +1 -0
  11. package/build/cjs/integrations/tracing/google-genai/instrumentation.js +94 -0
  12. package/build/cjs/integrations/tracing/google-genai/instrumentation.js.map +1 -0
  13. package/build/cjs/integrations/tracing/index.js +3 -0
  14. package/build/cjs/integrations/tracing/index.js.map +1 -1
  15. package/build/cjs/integrations/tracing/openai/instrumentation.js +3 -3
  16. package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -1
  17. package/build/cjs/integrations/tracing/vercelai/instrumentation.js +44 -51
  18. package/build/cjs/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  19. package/build/esm/index.js +1 -0
  20. package/build/esm/index.js.map +1 -1
  21. package/build/esm/integrations/http.js +25 -14
  22. package/build/esm/integrations/http.js.map +1 -1
  23. package/build/esm/integrations/tracing/anthropic-ai/index.js +2 -2
  24. package/build/esm/integrations/tracing/anthropic-ai/index.js.map +1 -1
  25. package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js +7 -18
  26. package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
  27. package/build/esm/integrations/tracing/google-genai/index.js +75 -0
  28. package/build/esm/integrations/tracing/google-genai/index.js.map +1 -0
  29. package/build/esm/integrations/tracing/google-genai/instrumentation.js +92 -0
  30. package/build/esm/integrations/tracing/google-genai/instrumentation.js.map +1 -0
  31. package/build/esm/integrations/tracing/index.js +3 -0
  32. package/build/esm/integrations/tracing/index.js.map +1 -1
  33. package/build/esm/integrations/tracing/openai/instrumentation.js +4 -4
  34. package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -1
  35. package/build/esm/integrations/tracing/vercelai/instrumentation.js +45 -52
  36. package/build/esm/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  37. package/build/esm/package.json +1 -1
  38. package/build/types/index.d.ts +1 -0
  39. package/build/types/index.d.ts.map +1 -1
  40. package/build/types/integrations/http.d.ts +2 -2
  41. package/build/types/integrations/http.d.ts.map +1 -1
  42. package/build/types/integrations/tracing/anthropic-ai/index.d.ts +1 -2
  43. package/build/types/integrations/tracing/anthropic-ai/index.d.ts.map +1 -1
  44. package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts +5 -6
  45. package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts.map +1 -1
  46. package/build/types/integrations/tracing/google-genai/index.d.ts +59 -0
  47. package/build/types/integrations/tracing/google-genai/index.d.ts.map +1 -0
  48. package/build/types/integrations/tracing/google-genai/instrumentation.d.ts +20 -0
  49. package/build/types/integrations/tracing/google-genai/instrumentation.d.ts.map +1 -0
  50. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  51. package/build/types/integrations/tracing/vercelai/instrumentation.d.ts.map +1 -1
  52. package/build/types-ts3.8/index.d.ts +1 -0
  53. package/build/types-ts3.8/integrations/http.d.ts +2 -2
  54. package/build/types-ts3.8/integrations/tracing/anthropic-ai/index.d.ts +1 -2
  55. package/build/types-ts3.8/integrations/tracing/anthropic-ai/instrumentation.d.ts +5 -6
  56. package/build/types-ts3.8/integrations/tracing/google-genai/index.d.ts +59 -0
  57. package/build/types-ts3.8/integrations/tracing/google-genai/instrumentation.d.ts +20 -0
  58. package/package.json +4 -4
@@ -27,14 +27,15 @@ const amqplib = require('./integrations/tracing/amqplib.js');
27
27
  const index$2 = require('./integrations/tracing/vercelai/index.js');
28
28
  const index$3 = require('./integrations/tracing/openai/index.js');
29
29
  const index$4 = require('./integrations/tracing/anthropic-ai/index.js');
30
+ const index$5 = require('./integrations/tracing/google-genai/index.js');
30
31
  const launchDarkly = require('./integrations/featureFlagShims/launchDarkly.js');
31
32
  const openFeature = require('./integrations/featureFlagShims/openFeature.js');
32
33
  const statsig = require('./integrations/featureFlagShims/statsig.js');
33
34
  const unleash = require('./integrations/featureFlagShims/unleash.js');
34
35
  const firebase = require('./integrations/tracing/firebase/firebase.js');
35
- const index$5 = require('./sdk/index.js');
36
+ const index$6 = require('./sdk/index.js');
36
37
  const initOtel = require('./sdk/initOtel.js');
37
- const index$6 = require('./integrations/tracing/index.js');
38
+ const index$7 = require('./integrations/tracing/index.js');
38
39
  const opentelemetry = require('@sentry/opentelemetry');
39
40
  const core = require('@sentry/core');
40
41
  const nodeCore = require('@sentry/node-core');
@@ -74,6 +75,7 @@ exports.amqplibIntegration = amqplib.amqplibIntegration;
74
75
  exports.vercelAIIntegration = index$2.vercelAIIntegration;
75
76
  exports.openAIIntegration = index$3.openAIIntegration;
76
77
  exports.anthropicAIIntegration = index$4.anthropicAIIntegration;
78
+ exports.googleGenAIIntegration = index$5.googleGenAIIntegration;
77
79
  exports.buildLaunchDarklyFlagUsedHandler = launchDarkly.buildLaunchDarklyFlagUsedHandlerShim;
78
80
  exports.launchDarklyIntegration = launchDarkly.launchDarklyIntegrationShim;
79
81
  exports.OpenFeatureIntegrationHook = openFeature.OpenFeatureIntegrationHookShim;
@@ -81,13 +83,13 @@ exports.openFeatureIntegration = openFeature.openFeatureIntegrationShim;
81
83
  exports.statsigIntegration = statsig.statsigIntegrationShim;
82
84
  exports.unleashIntegration = unleash.unleashIntegrationShim;
83
85
  exports.firebaseIntegration = firebase.firebaseIntegration;
84
- exports.getDefaultIntegrations = index$5.getDefaultIntegrations;
85
- exports.getDefaultIntegrationsWithoutPerformance = index$5.getDefaultIntegrationsWithoutPerformance;
86
- exports.init = index$5.init;
87
- exports.initWithoutDefaultIntegrations = index$5.initWithoutDefaultIntegrations;
86
+ exports.getDefaultIntegrations = index$6.getDefaultIntegrations;
87
+ exports.getDefaultIntegrationsWithoutPerformance = index$6.getDefaultIntegrationsWithoutPerformance;
88
+ exports.init = index$6.init;
89
+ exports.initWithoutDefaultIntegrations = index$6.initWithoutDefaultIntegrations;
88
90
  exports.initOpenTelemetry = initOtel.initOpenTelemetry;
89
91
  exports.preloadOpenTelemetry = initOtel.preloadOpenTelemetry;
90
- exports.getAutoPerformanceIntegrations = index$6.getAutoPerformanceIntegrations;
92
+ exports.getAutoPerformanceIntegrations = index$7.getAutoPerformanceIntegrations;
91
93
  exports.setNodeAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
92
94
  exports.SDK_VERSION = core.SDK_VERSION;
93
95
  exports.SEMANTIC_ATTRIBUTE_SENTRY_OP = core.SEMANTIC_ATTRIBUTE_SENTRY_OP;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -4,6 +4,7 @@ const api = require('@opentelemetry/api');
4
4
  const instrumentationHttp = require('@opentelemetry/instrumentation-http');
5
5
  const core = require('@sentry/core');
6
6
  const nodeCore = require('@sentry/node-core');
7
+ const debugBuild = require('../debug-build.js');
7
8
 
8
9
  const INTEGRATION_NAME = 'Http';
9
10
 
@@ -68,7 +69,9 @@ function _shouldUseOtelHttpInstrumentation(
68
69
  const httpIntegration = core.defineIntegration((options = {}) => {
69
70
  const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [
70
71
  [401, 404],
71
- [300, 399],
72
+ // 300 and 304 are possibly valid status codes we do not want to filter
73
+ [301, 303],
74
+ [305, 399],
72
75
  ];
73
76
 
74
77
  return {
@@ -98,18 +101,12 @@ const httpIntegration = core.defineIntegration((options = {}) => {
98
101
  // Drop transaction if it has a status code that should be ignored
99
102
  if (event.type === 'transaction') {
100
103
  const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];
101
- if (
102
- typeof statusCode === 'number' &&
103
- dropSpansForIncomingRequestStatusCodes.some(code => {
104
- if (typeof code === 'number') {
105
- return code === statusCode;
106
- }
107
-
108
- const [min, max] = code;
109
- return statusCode >= min && statusCode <= max;
110
- })
111
- ) {
112
- return null;
104
+ if (typeof statusCode === 'number') {
105
+ const shouldDrop = shouldFilterStatusCode(statusCode, dropSpansForIncomingRequestStatusCodes);
106
+ if (shouldDrop) {
107
+ debugBuild.DEBUG_BUILD && core.debug.log('Dropping transaction due to status code', statusCode);
108
+ return null;
109
+ }
113
110
  }
114
111
  }
115
112
 
@@ -156,6 +153,20 @@ function getConfigWithDefaults(options = {}) {
156
153
  return instrumentationConfig;
157
154
  }
158
155
 
156
+ /**
157
+ * If the given status code should be filtered for the given list of status codes/ranges.
158
+ */
159
+ function shouldFilterStatusCode(statusCode, dropForStatusCodes) {
160
+ return dropForStatusCodes.some(code => {
161
+ if (typeof code === 'number') {
162
+ return code === statusCode;
163
+ }
164
+
165
+ const [min, max] = code;
166
+ return statusCode >= min && statusCode <= max;
167
+ });
168
+ }
169
+
159
170
  exports._shouldUseOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation;
160
171
  exports.httpIntegration = httpIntegration;
161
172
  exports.instrumentOtelHttp = instrumentOtelHttp;
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sources":["../../../src/integrations/http.ts"],"sourcesContent":["import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';\nimport { diag } from '@opentelemetry/api';\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport type { Span } from '@sentry/core';\nimport { defineIntegration, getClient, hasSpansEnabled } from '@sentry/core';\nimport type { HTTPModuleRequestIncomingMessage, NodeClient } from '@sentry/node-core';\nimport {\n type SentryHttpInstrumentationOptions,\n addOriginToSpan,\n generateInstrumentOnce,\n getRequestUrl,\n NODE_VERSION,\n SentryHttpInstrumentation,\n} from '@sentry/node-core';\nimport type { NodeClientOptions } from '../types';\n\nconst INTEGRATION_NAME = 'Http';\n\nconst INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';\n\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with 404 status code are ignored.\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [300, 399]]`\n */\n dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the incoming request.\n * @param request Contains the {@type RequestOptions} object used to make the incoming request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Controls the maximum size of incoming HTTP request bodies attached to events.\n *\n * Available options:\n * - 'none': No request bodies will be attached\n * - 'small': Request bodies up to 1,000 bytes will be attached\n * - 'medium': Request bodies up to 10,000 bytes will be attached (default)\n * - 'always': Request bodies will always be attached\n *\n * Note that even with 'always' setting, bodies exceeding 1MB will never be attached\n * for performance and security reasons.\n *\n * @default 'medium'\n */\n maxIncomingRequestBodySize?: 'none' | 'small' | 'medium' | 'always';\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;\n responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => void;\n };\n}\n\nexport const instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\n);\n\nexport const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConfig>(INTEGRATION_NAME, config => {\n const instrumentation = new HttpInstrumentation({\n ...config,\n // This is hard-coded and can never be overridden by the user\n disableIncomingRequestInstrumentation: true,\n });\n\n // We want to update the logger namespace so we can better identify what is happening here\n try {\n instrumentation['_diag'] = diag.createComponentLogger({\n namespace: INSTRUMENTATION_NAME,\n });\n // @ts-expect-error We are writing a read-only property here...\n instrumentation.instrumentationName = INSTRUMENTATION_NAME;\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldUseOtelHttpInstrumentation(\n options: HttpOptions,\n clientOptions: Partial<NodeClientOptions> = {},\n): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled\n if (typeof options.spans === 'boolean') {\n return options.spans;\n }\n\n if (clientOptions.skipOpenTelemetrySetup) {\n return false;\n }\n\n // IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on Node 22+,\n // as otherwise the necessary diagnostics channel is not available yet\n if (!hasSpansEnabled(clientOptions) && NODE_VERSION.major >= 22) {\n return false;\n }\n\n return true;\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [\n [401, 404],\n [300, 399],\n ];\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n const clientOptions = (getClient<NodeClient>()?.getOptions() || {}) as Partial<NodeClientOptions>;\n const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions);\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans ?? !hasSpansEnabled(clientOptions);\n\n // This is Sentry-specific instrumentation for request isolation and breadcrumbs\n instrumentSentryHttp({\n ...options,\n disableIncomingRequestSpans,\n ignoreSpansForIncomingRequests: options.ignoreIncomingRequests,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle trace propagation ourselves\n propagateTraceInOutgoingRequests: !useOtelHttpInstrumentation,\n });\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (useOtelHttpInstrumentation) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n },\n processEvent(event) {\n // Drop transaction if it has a status code that should be ignored\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (\n typeof statusCode === 'number' &&\n dropSpansForIncomingRequestStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n })\n ) {\n return null;\n }\n }\n\n return event;\n },\n };\n});\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n ignoreOutgoingRequestHook: request => {\n const url = getRequestUrl(request);\n\n if (!url) {\n return false;\n }\n\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n if (_ignoreOutgoingRequests?.(url, request)) {\n return true;\n }\n\n return false;\n },\n\n requireParentforOutgoingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n\n options.instrumentation?.requestHook?.(span, req);\n },\n responseHook: (span, res) => {\n options.instrumentation?.responseHook?.(span, res);\n },\n applyCustomAttributesOnSpan: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => {\n options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);\n },\n } satisfies HttpInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":["generateInstrumentOnce","SentryHttpInstrumentation","HttpInstrumentation","diag","hasSpansEnabled","NODE_VERSION","defineIntegration","getClient","getRequestUrl","addOriginToSpan"],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sources":["../../../src/integrations/http.ts"],"sourcesContent":["import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';\nimport { diag } from '@opentelemetry/api';\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport type { Span } from '@sentry/core';\nimport { debug, defineIntegration, getClient, hasSpansEnabled } from '@sentry/core';\nimport type { HTTPModuleRequestIncomingMessage, NodeClient } from '@sentry/node-core';\nimport {\n type SentryHttpInstrumentationOptions,\n addOriginToSpan,\n generateInstrumentOnce,\n getRequestUrl,\n NODE_VERSION,\n SentryHttpInstrumentation,\n} from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst INTEGRATION_NAME = 'Http';\n\nconst INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';\n\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the incoming request.\n * @param request Contains the {@type RequestOptions} object used to make the incoming request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Controls the maximum size of incoming HTTP request bodies attached to events.\n *\n * Available options:\n * - 'none': No request bodies will be attached\n * - 'small': Request bodies up to 1,000 bytes will be attached\n * - 'medium': Request bodies up to 10,000 bytes will be attached (default)\n * - 'always': Request bodies will always be attached\n *\n * Note that even with 'always' setting, bodies exceeding 1MB will never be attached\n * for performance and security reasons.\n *\n * @default 'medium'\n */\n maxIncomingRequestBodySize?: 'none' | 'small' | 'medium' | 'always';\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;\n responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => void;\n };\n}\n\nexport const instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\n);\n\nexport const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConfig>(INTEGRATION_NAME, config => {\n const instrumentation = new HttpInstrumentation({\n ...config,\n // This is hard-coded and can never be overridden by the user\n disableIncomingRequestInstrumentation: true,\n });\n\n // We want to update the logger namespace so we can better identify what is happening here\n try {\n instrumentation['_diag'] = diag.createComponentLogger({\n namespace: INSTRUMENTATION_NAME,\n });\n // @ts-expect-error We are writing a read-only property here...\n instrumentation.instrumentationName = INSTRUMENTATION_NAME;\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldUseOtelHttpInstrumentation(\n options: HttpOptions,\n clientOptions: Partial<NodeClientOptions> = {},\n): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled\n if (typeof options.spans === 'boolean') {\n return options.spans;\n }\n\n if (clientOptions.skipOpenTelemetrySetup) {\n return false;\n }\n\n // IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on Node 22+,\n // as otherwise the necessary diagnostics channel is not available yet\n if (!hasSpansEnabled(clientOptions) && NODE_VERSION.major >= 22) {\n return false;\n }\n\n return true;\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [\n [401, 404],\n // 300 and 304 are possibly valid status codes we do not want to filter\n [301, 303],\n [305, 399],\n ];\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n const clientOptions = (getClient<NodeClient>()?.getOptions() || {}) as Partial<NodeClientOptions>;\n const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions);\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans ?? !hasSpansEnabled(clientOptions);\n\n // This is Sentry-specific instrumentation for request isolation and breadcrumbs\n instrumentSentryHttp({\n ...options,\n disableIncomingRequestSpans,\n ignoreSpansForIncomingRequests: options.ignoreIncomingRequests,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle trace propagation ourselves\n propagateTraceInOutgoingRequests: !useOtelHttpInstrumentation,\n });\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (useOtelHttpInstrumentation) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n },\n processEvent(event) {\n // Drop transaction if it has a status code that should be ignored\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (typeof statusCode === 'number') {\n const shouldDrop = shouldFilterStatusCode(statusCode, dropSpansForIncomingRequestStatusCodes);\n if (shouldDrop) {\n DEBUG_BUILD && debug.log('Dropping transaction due to status code', statusCode);\n return null;\n }\n }\n }\n\n return event;\n },\n };\n});\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n ignoreOutgoingRequestHook: request => {\n const url = getRequestUrl(request);\n\n if (!url) {\n return false;\n }\n\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n if (_ignoreOutgoingRequests?.(url, request)) {\n return true;\n }\n\n return false;\n },\n\n requireParentforOutgoingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n\n options.instrumentation?.requestHook?.(span, req);\n },\n responseHook: (span, res) => {\n options.instrumentation?.responseHook?.(span, res);\n },\n applyCustomAttributesOnSpan: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => {\n options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);\n },\n } satisfies HttpInstrumentationConfig;\n\n return instrumentationConfig;\n}\n\n/**\n * If the given status code should be filtered for the given list of status codes/ranges.\n */\nfunction shouldFilterStatusCode(statusCode: number, dropForStatusCodes: (number | [number, number])[]): boolean {\n return dropForStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n });\n}\n"],"names":["generateInstrumentOnce","SentryHttpInstrumentation","HttpInstrumentation","diag","hasSpansEnabled","NODE_VERSION","defineIntegration","getClient","DEBUG_BUILD","debug","getRequestUrl","addOriginToSpan"],"mappings":"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"}
@@ -6,7 +6,7 @@ const instrumentation = require('./instrumentation.js');
6
6
 
7
7
  const instrumentAnthropicAi = nodeCore.generateInstrumentOnce(
8
8
  core.ANTHROPIC_AI_INTEGRATION_NAME,
9
- () => new instrumentation.SentryAnthropicAiInstrumentation({}),
9
+ options => new instrumentation.SentryAnthropicAiInstrumentation(options),
10
10
  );
11
11
 
12
12
  const _anthropicAIIntegration = ((options = {}) => {
@@ -14,7 +14,7 @@ const _anthropicAIIntegration = ((options = {}) => {
14
14
  name: core.ANTHROPIC_AI_INTEGRATION_NAME,
15
15
  options,
16
16
  setupOnce() {
17
- instrumentAnthropicAi();
17
+ instrumentAnthropicAi(options);
18
18
  },
19
19
  };
20
20
  }) ;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/index.ts"],"sourcesContent":["import type { AnthropicAiOptions, IntegrationFn } from '@sentry/core';\nimport { ANTHROPIC_AI_INTEGRATION_NAME, defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryAnthropicAiInstrumentation } from './instrumentation';\n\nexport const instrumentAnthropicAi = generateInstrumentOnce(\n ANTHROPIC_AI_INTEGRATION_NAME,\n () => new SentryAnthropicAiInstrumentation({}),\n);\n\nconst _anthropicAIIntegration = ((options: AnthropicAiOptions = {}) => {\n return {\n name: ANTHROPIC_AI_INTEGRATION_NAME,\n options,\n setupOnce() {\n instrumentAnthropicAi();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the Anthropic AI SDK.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments Anthropic AI SDK client instances\n * to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n *\n * Sentry.init({\n * integrations: [Sentry.anthropicAIIntegration()],\n * });\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record prompt messages (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.anthropicAIIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.anthropicAIIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n */\nexport const anthropicAIIntegration = defineIntegration(_anthropicAIIntegration);\n"],"names":["generateInstrumentOnce","ANTHROPIC_AI_INTEGRATION_NAME","SentryAnthropicAiInstrumentation","defineIntegration"],"mappings":";;;;;;AAKO,MAAM,qBAAA,GAAwBA,+BAAsB;AAC3D,EAAEC,kCAA6B;AAC/B,EAAE,MAAM,IAAIC,gDAAgC,CAAC,EAAE,CAAC;AAChD;;AAEA,MAAM,uBAAA,IAA2B,CAAC,OAAO,GAAuB,EAAE,KAAK;AACvE,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,kCAA6B;AACvC,IAAI,OAAO;AACX,IAAI,SAAS,GAAG;AAChB,MAAM,qBAAqB,EAAE;AAC7B,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,sBAAA,GAAyBE,sBAAiB,CAAC,uBAAuB;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/index.ts"],"sourcesContent":["import type { AnthropicAiOptions, IntegrationFn } from '@sentry/core';\nimport { ANTHROPIC_AI_INTEGRATION_NAME, defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryAnthropicAiInstrumentation } from './instrumentation';\n\nexport const instrumentAnthropicAi = generateInstrumentOnce<AnthropicAiOptions>(\n ANTHROPIC_AI_INTEGRATION_NAME,\n options => new SentryAnthropicAiInstrumentation(options),\n);\n\nconst _anthropicAIIntegration = ((options: AnthropicAiOptions = {}) => {\n return {\n name: ANTHROPIC_AI_INTEGRATION_NAME,\n options,\n setupOnce() {\n instrumentAnthropicAi(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the Anthropic AI SDK.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments Anthropic AI SDK client instances\n * to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n *\n * Sentry.init({\n * integrations: [Sentry.anthropicAIIntegration()],\n * });\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record prompt messages (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.anthropicAIIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.anthropicAIIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n */\nexport const anthropicAIIntegration = defineIntegration(_anthropicAIIntegration);\n"],"names":["generateInstrumentOnce","ANTHROPIC_AI_INTEGRATION_NAME","SentryAnthropicAiInstrumentation","defineIntegration"],"mappings":";;;;;;AAKO,MAAM,qBAAA,GAAwBA,+BAAsB;AAC3D,EAAEC,kCAA6B;AAC/B,EAAE,WAAW,IAAIC,gDAAgC,CAAC,OAAO,CAAC;AAC1D;;AAEA,MAAM,uBAAA,IAA2B,CAAC,OAAO,GAAuB,EAAE,KAAK;AACvE,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,kCAA6B;AACvC,IAAI,OAAO;AACX,IAAI,SAAS,GAAG;AAChB,MAAM,qBAAqB,CAAC,OAAO,CAAC;AACpC,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,sBAAA,GAAyBE,sBAAiB,CAAC,uBAAuB;;;;;"}
@@ -5,18 +5,6 @@ const core = require('@sentry/core');
5
5
 
6
6
  const supportedVersions = ['>=0.19.2 <1.0.0'];
7
7
 
8
- /**
9
- * Determines telemetry recording settings.
10
- */
11
- function determineRecordingSettings(
12
- integrationOptions,
13
- defaultEnabled,
14
- ) {
15
- const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;
16
- const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;
17
- return { recordInputs, recordOutputs };
18
- }
19
-
20
8
  /**
21
9
  * Sentry Anthropic AI instrumentation using OpenTelemetry.
22
10
  */
@@ -43,14 +31,15 @@ class SentryAnthropicAiInstrumentation extends instrumentation.InstrumentationBa
43
31
  _patch(exports) {
44
32
  const Original = exports.Anthropic;
45
33
 
34
+ const config = this.getConfig();
35
+
46
36
  const WrappedAnthropic = function ( ...args) {
47
37
  const instance = Reflect.construct(Original, args);
48
- const scopeClient = core.getCurrentScope().getClient();
49
- const integration = scopeClient?.getIntegrationByName(core.ANTHROPIC_AI_INTEGRATION_NAME);
50
- const integrationOpts = integration?.options;
51
- const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);
38
+ const client = core.getClient();
39
+ const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
52
40
 
53
- const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);
41
+ const recordInputs = config.recordInputs ?? defaultPii;
42
+ const recordOutputs = config.recordOutputs ?? defaultPii;
54
43
 
55
44
  return core.instrumentAnthropicAiClient(instance , {
56
45
  recordInputs,
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { AnthropicAiClient, AnthropicAiOptions, Integration } from '@sentry/core';\nimport { ANTHROPIC_AI_INTEGRATION_NAME, getCurrentScope, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=0.19.2 <1.0.0'];\n\nexport interface AnthropicAiIntegration extends Integration {\n options: AnthropicAiOptions;\n}\n\n/**\n * Represents the patched shape of the Anthropic AI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n Anthropic: abstract new (...args: unknown[]) => AnthropicAiClient;\n}\n\n/**\n * Determines telemetry recording settings.\n */\nfunction determineRecordingSettings(\n integrationOptions: AnthropicAiOptions | undefined,\n defaultEnabled: boolean,\n): { recordInputs: boolean; recordOutputs: boolean } {\n const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;\n const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;\n return { recordInputs, recordOutputs };\n}\n\n/**\n * Sentry Anthropic AI instrumentation using OpenTelemetry.\n */\nexport class SentryAnthropicAiInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n public constructor(config: InstrumentationConfig = {}) {\n super('@sentry/instrumentation-anthropic-ai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@anthropic-ai/sdk',\n supportedVersions,\n this._patch.bind(this),\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Anthropic AI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.Anthropic;\n\n const WrappedAnthropic = function (this: unknown, ...args: unknown[]) {\n const instance = Reflect.construct(Original, args);\n const scopeClient = getCurrentScope().getClient();\n const integration = scopeClient?.getIntegrationByName<AnthropicAiIntegration>(ANTHROPIC_AI_INTEGRATION_NAME);\n const integrationOpts = integration?.options;\n const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);\n\n const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);\n\n return instrumentAnthropicAiClient(instance as AnthropicAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => AnthropicAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedAnthropic, Original);\n Object.setPrototypeOf(WrappedAnthropic.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedAnthropic, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n try {\n exports.Anthropic = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'Anthropic', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","getCurrentScope","ANTHROPIC_AI_INTEGRATION_NAME","instrumentAnthropicAiClient"],"mappings":"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"}
1
+ {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/anthropic-ai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { AnthropicAiClient, AnthropicAiOptions } from '@sentry/core';\nimport { getClient, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=0.19.2 <1.0.0'];\n\ntype AnthropicAiInstrumentationOptions = InstrumentationConfig & AnthropicAiOptions;\n\n/**\n * Represents the patched shape of the Anthropic AI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n Anthropic: abstract new (...args: unknown[]) => AnthropicAiClient;\n}\n\n/**\n * Sentry Anthropic AI instrumentation using OpenTelemetry.\n */\nexport class SentryAnthropicAiInstrumentation extends InstrumentationBase<AnthropicAiInstrumentationOptions> {\n public constructor(config: AnthropicAiInstrumentationOptions = {}) {\n super('@sentry/instrumentation-anthropic-ai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@anthropic-ai/sdk',\n supportedVersions,\n this._patch.bind(this),\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Anthropic AI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.Anthropic;\n\n const config = this.getConfig();\n\n const WrappedAnthropic = function (this: unknown, ...args: unknown[]) {\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const recordInputs = config.recordInputs ?? defaultPii;\n const recordOutputs = config.recordOutputs ?? defaultPii;\n\n return instrumentAnthropicAiClient(instance as AnthropicAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => AnthropicAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedAnthropic, Original);\n Object.setPrototypeOf(WrappedAnthropic.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedAnthropic, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n try {\n exports.Anthropic = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'Anthropic', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The Anthropic property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedAnthropic;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedAnthropic,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","getClient","instrumentAnthropicAiClient"],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const nodeCore = require('@sentry/node-core');
5
+ const instrumentation = require('./instrumentation.js');
6
+
7
+ const instrumentGoogleGenAI = nodeCore.generateInstrumentOnce(
8
+ core.GOOGLE_GENAI_INTEGRATION_NAME,
9
+ options => new instrumentation.SentryGoogleGenAiInstrumentation(options),
10
+ );
11
+
12
+ const _googleGenAIIntegration = ((options = {}) => {
13
+ return {
14
+ name: core.GOOGLE_GENAI_INTEGRATION_NAME,
15
+ setupOnce() {
16
+ instrumentGoogleGenAI(options);
17
+ },
18
+ };
19
+ }) ;
20
+
21
+ /**
22
+ * Adds Sentry tracing instrumentation for the Google Generative AI SDK.
23
+ *
24
+ * This integration is enabled by default.
25
+ *
26
+ * When configured, this integration automatically instruments Google GenAI SDK client instances
27
+ * to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.
28
+ *
29
+ * @example
30
+ * ```javascript
31
+ * import * as Sentry from '@sentry/node';
32
+ *
33
+ * Sentry.init({
34
+ * integrations: [Sentry.googleGenAiIntegration()],
35
+ * });
36
+ * ```
37
+ *
38
+ * ## Options
39
+ *
40
+ * - `recordInputs`: Whether to record prompt messages (default: respects `sendDefaultPii` client option)
41
+ * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)
42
+ *
43
+ * ### Default Behavior
44
+ *
45
+ * By default, the integration will:
46
+ * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options
47
+ * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled
48
+ *
49
+ * @example
50
+ * ```javascript
51
+ * // Record inputs and outputs when sendDefaultPii is false
52
+ * Sentry.init({
53
+ * integrations: [
54
+ * Sentry.googleGenAiIntegration({
55
+ * recordInputs: true,
56
+ * recordOutputs: true
57
+ * })
58
+ * ],
59
+ * });
60
+ *
61
+ * // Never record inputs/outputs regardless of sendDefaultPii
62
+ * Sentry.init({
63
+ * sendDefaultPii: true,
64
+ * integrations: [
65
+ * Sentry.googleGenAiIntegration({
66
+ * recordInputs: false,
67
+ * recordOutputs: false
68
+ * })
69
+ * ],
70
+ * });
71
+ * ```
72
+ *
73
+ */
74
+ const googleGenAIIntegration = core.defineIntegration(_googleGenAIIntegration);
75
+
76
+ exports.googleGenAIIntegration = googleGenAIIntegration;
77
+ exports.instrumentGoogleGenAI = instrumentGoogleGenAI;
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/google-genai/index.ts"],"sourcesContent":["import type { GoogleGenAIOptions, IntegrationFn } from '@sentry/core';\nimport { defineIntegration, GOOGLE_GENAI_INTEGRATION_NAME } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryGoogleGenAiInstrumentation } from './instrumentation';\n\nexport const instrumentGoogleGenAI = generateInstrumentOnce<GoogleGenAIOptions>(\n GOOGLE_GENAI_INTEGRATION_NAME,\n options => new SentryGoogleGenAiInstrumentation(options),\n);\n\nconst _googleGenAIIntegration = ((options: GoogleGenAIOptions = {}) => {\n return {\n name: GOOGLE_GENAI_INTEGRATION_NAME,\n setupOnce() {\n instrumentGoogleGenAI(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the Google Generative AI SDK.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments Google GenAI SDK client instances\n * to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n *\n * Sentry.init({\n * integrations: [Sentry.googleGenAiIntegration()],\n * });\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record prompt messages (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.googleGenAiIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.googleGenAiIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n */\nexport const googleGenAIIntegration = defineIntegration(_googleGenAIIntegration);\n"],"names":["generateInstrumentOnce","GOOGLE_GENAI_INTEGRATION_NAME","SentryGoogleGenAiInstrumentation","defineIntegration"],"mappings":";;;;;;AAKO,MAAM,qBAAA,GAAwBA,+BAAsB;AAC3D,EAAEC,kCAA6B;AAC/B,EAAE,WAAW,IAAIC,gDAAgC,CAAC,OAAO,CAAC;AAC1D;;AAEA,MAAM,uBAAA,IAA2B,CAAC,OAAO,GAAuB,EAAE,KAAK;AACvE,EAAE,OAAO;AACT,IAAI,IAAI,EAAED,kCAA6B;AACvC,IAAI,SAAS,GAAG;AAChB,MAAM,qBAAqB,CAAC,OAAO,CAAC;AACpC,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,sBAAA,GAAyBE,sBAAiB,CAAC,uBAAuB;;;;;"}
@@ -0,0 +1,94 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const instrumentation = require('@opentelemetry/instrumentation');
4
+ const core = require('@sentry/core');
5
+
6
+ const supportedVersions = ['>=0.10.0 <2'];
7
+
8
+ /**
9
+ * Represents the patched shape of the Google GenAI module export.
10
+ */
11
+
12
+ /**
13
+ * Sentry Google GenAI instrumentation using OpenTelemetry.
14
+ */
15
+ class SentryGoogleGenAiInstrumentation extends instrumentation.InstrumentationBase {
16
+ constructor(config = {}) {
17
+ super('@sentry/instrumentation-google-genai', core.SDK_VERSION, config);
18
+ }
19
+
20
+ /**
21
+ * Initializes the instrumentation by defining the modules to be patched.
22
+ */
23
+ init() {
24
+ const module = new instrumentation.InstrumentationNodeModuleDefinition(
25
+ '@google/genai',
26
+ supportedVersions,
27
+ exports => this._patch(exports),
28
+ exports => exports,
29
+ // In CJS, @google/genai re-exports from (dist/node/index.cjs) file.
30
+ // Patching only the root module sometimes misses the real implementation or
31
+ // gets overwritten when that file is loaded. We add a file-level patch so that
32
+ // _patch runs again on the concrete implementation
33
+ [
34
+ new instrumentation.InstrumentationNodeModuleFile(
35
+ '@google/genai/dist/node/index.cjs',
36
+ supportedVersions,
37
+ exports => this._patch(exports),
38
+ exports => exports,
39
+ ),
40
+ ],
41
+ );
42
+ return module;
43
+ }
44
+
45
+ /**
46
+ * Core patch logic applying instrumentation to the Google GenAI client constructor.
47
+ */
48
+ _patch(exports) {
49
+ const Original = exports.GoogleGenAI;
50
+ const config = this.getConfig();
51
+
52
+ if (typeof Original !== 'function') {
53
+ return exports;
54
+ }
55
+
56
+ const WrappedGoogleGenAI = function ( ...args) {
57
+ const instance = Reflect.construct(Original, args);
58
+ const client = core.getClient();
59
+ const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
60
+
61
+ const typedConfig = config ;
62
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
63
+ const recordInputs = typedConfig?.recordInputs ?? defaultPii;
64
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
65
+ const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;
66
+
67
+ return core.instrumentGoogleGenAIClient(instance, {
68
+ recordInputs,
69
+ recordOutputs,
70
+ });
71
+ };
72
+
73
+ // Preserve static and prototype chains
74
+ Object.setPrototypeOf(WrappedGoogleGenAI, Original);
75
+ Object.setPrototypeOf(WrappedGoogleGenAI.prototype, Original.prototype);
76
+
77
+ for (const key of Object.getOwnPropertyNames(Original)) {
78
+ if (!['length', 'name', 'prototype'].includes(key)) {
79
+ const descriptor = Object.getOwnPropertyDescriptor(Original, key);
80
+ if (descriptor) {
81
+ Object.defineProperty(WrappedGoogleGenAI, key, descriptor);
82
+ }
83
+ }
84
+ }
85
+
86
+ // Replace google genai exports with the wrapped constructor
87
+ core.replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);
88
+
89
+ return exports;
90
+ }
91
+ }
92
+
93
+ exports.SentryGoogleGenAiInstrumentation = SentryGoogleGenAiInstrumentation;
94
+ //# sourceMappingURL=instrumentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/google-genai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';\nimport { getClient, instrumentGoogleGenAIClient, replaceExports, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=0.10.0 <2'];\n\n/**\n * Represents the patched shape of the Google GenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n GoogleGenAI?: unknown;\n}\n\ntype GoogleGenAIInstrumentationOptions = GoogleGenAIOptions & InstrumentationConfig;\n\n/**\n * Sentry Google GenAI instrumentation using OpenTelemetry.\n */\nexport class SentryGoogleGenAiInstrumentation extends InstrumentationBase<GoogleGenAIInstrumentationOptions> {\n public constructor(config: GoogleGenAIInstrumentationOptions = {}) {\n super('@sentry/instrumentation-google-genai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@google/genai',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n // In CJS, @google/genai re-exports from (dist/node/index.cjs) file.\n // Patching only the root module sometimes misses the real implementation or\n // gets overwritten when that file is loaded. We add a file-level patch so that\n // _patch runs again on the concrete implementation\n [\n new InstrumentationNodeModuleFile(\n '@google/genai/dist/node/index.cjs',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n ),\n ],\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Google GenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.GoogleGenAI;\n const config = this.getConfig();\n\n if (typeof Original !== 'function') {\n return exports;\n }\n\n const WrappedGoogleGenAI = function (this: unknown, ...args: unknown[]): GoogleGenAIClient {\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const typedConfig = config as GoogleGenAIInstrumentationOptions;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordInputs = typedConfig?.recordInputs ?? defaultPii;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;\n\n return instrumentGoogleGenAIClient(instance, {\n recordInputs,\n recordOutputs,\n });\n };\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedGoogleGenAI, Original);\n Object.setPrototypeOf(WrappedGoogleGenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedGoogleGenAI, key, descriptor);\n }\n }\n }\n\n // Replace google genai exports with the wrapped constructor\n replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);\n\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","getClient","instrumentGoogleGenAIClient","replaceExports"],"mappings":";;;;;AAUA,MAAM,iBAAA,GAAoB,CAAC,aAAa,CAAC;;AAEzC;AACA;AACA;;AAQA;AACA;AACA;AACO,MAAM,gCAAA,SAAyCA,mCAAmB,CAAoC;AAC7G,GAAS,WAAW,CAAC,MAAM,GAAsC,EAAE,EAAE;AACrE,IAAI,KAAK,CAAC,sCAAsC,EAAEC,gBAAW,EAAE,MAAM,CAAC;AACtE;;AAEA;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAIC,mDAAmC;AAC1D,MAAM,eAAe;AACrB,MAAM,iBAAiB;AACvB,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACrC,MAAM,OAAA,IAAW,OAAO;AACxB;AACA;AACA;AACA;AACA,MAAM;AACN,QAAQ,IAAIC,6CAA6B;AACzC,UAAU,mCAAmC;AAC7C,UAAU,iBAAiB;AAC3B,UAAU,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACzC,UAAU,OAAA,IAAW,OAAO;AAC5B,SAAS;AACT,OAAO;AACP,KAAK;AACL,IAAI,OAAO,MAAM;AACjB;;AAEA;AACA;AACA;AACA,GAAU,MAAM,CAAC,OAAO,EAAqD;AAC7E,IAAI,MAAM,QAAA,GAAW,OAAO,CAAC,WAAW;AACxC,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;;AAEnC,IAAI,IAAI,OAAO,QAAA,KAAa,UAAU,EAAE;AACxC,MAAM,OAAO,OAAO;AACpB;;AAEA,IAAI,MAAM,qBAAqB,WAAyB,GAAG,IAAI,EAAgC;AAC/F,MAAM,MAAM,QAAA,GAAW,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC;AACxD,MAAM,MAAM,MAAA,GAASC,cAAS,EAAE;AAChC,MAAM,MAAM,UAAA,GAAa,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,cAAc,CAAC;;AAErE,MAAM,MAAM,WAAA,GAAc,MAAA;AAC1B;AACA,MAAM,MAAM,YAAA,GAAe,WAAW,EAAE,YAAA,IAAgB,UAAU;AAClE;AACA,MAAM,MAAM,aAAA,GAAgB,WAAW,EAAE,aAAA,IAAiB,UAAU;;AAEpE,MAAM,OAAOC,gCAA2B,CAAC,QAAQ,EAAE;AACnD,QAAQ,YAAY;AACpB,QAAQ,aAAa;AACrB,OAAO,CAAC;AACR,KAAK;;AAEL;AACA,IAAI,MAAM,CAAC,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC;AACvD,IAAI,MAAM,CAAC,cAAc,CAAC,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;;AAE3E,IAAI,KAAK,MAAM,GAAA,IAAO,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE;AAC5D,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC1D,QAAQ,MAAM,UAAA,GAAa,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,GAAG,CAAC;AACzE,QAAQ,IAAI,UAAU,EAAE;AACxB,UAAU,MAAM,CAAC,cAAc,CAAC,kBAAkB,EAAE,GAAG,EAAE,UAAU,CAAC;AACpE;AACA;AACA;;AAEA;AACA,IAAIC,mBAAc,CAAC,OAAO,EAAE,aAAa,EAAE,kBAAkB,CAAC;;AAE9D,IAAI,OAAO,OAAO;AAClB;AACA;;;;"}
@@ -8,6 +8,7 @@ const express = require('./express.js');
8
8
  const index = require('./fastify/index.js');
9
9
  const firebase = require('./firebase/firebase.js');
10
10
  const genericPool = require('./genericPool.js');
11
+ const index$5 = require('./google-genai/index.js');
11
12
  const graphql = require('./graphql.js');
12
13
  const index$1 = require('./hapi/index.js');
13
14
  const kafka = require('./kafka.js');
@@ -53,6 +54,7 @@ function getAutoPerformanceIntegrations() {
53
54
  postgresjs.postgresJsIntegration(),
54
55
  firebase.firebaseIntegration(),
55
56
  index$4.anthropicAIIntegration(),
57
+ index$5.googleGenAIIntegration(),
56
58
  ];
57
59
  }
58
60
 
@@ -88,6 +90,7 @@ function getOpenTelemetryInstrumentationToPreload() {
88
90
  postgresjs.instrumentPostgresJs,
89
91
  firebase.instrumentFirebase,
90
92
  index$4.instrumentAnthropicAi,
93
+ index$5.instrumentGoogleGenAI,
91
94
  ];
92
95
  }
93
96
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n anthropicAIIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n ];\n}\n"],"names":["expressIntegration","fastifyIntegration","graphqlIntegration","mongoIntegration","mongooseIntegration","mysqlIntegration","mysql2Integration","redisIntegration","postgresIntegration","prismaIntegration","hapiIntegration","koaIntegration","connectIntegration","tediousIntegration","genericPoolIntegration","kafkaIntegration","amqplibIntegration","lruMemoizerIntegration","vercelAIIntegration","openAIIntegration","postgresJsIntegration","firebaseIntegration","anthropicAIIntegration","instrumentSentryHttp","instrumentOtelHttp","instrumentExpress","instrumentConnect","instrumentFastify","instrumentFastifyV3","instrumentHapi","instrumentKafka","instrumentKoa","instrumentLruMemoizer","instrumentMongo","instrumentMongoose","instrumentMysql","instrumentMysql2","instrumentPostgres","instrumentGraphql","instrumentRedis","instrumentTedious","instrumentGenericPool","instrumentAmqplib","instrumentVercelAi","instrumentOpenAi","instrumentPostgresJs","instrumentFirebase","instrumentAnthropicAi"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAIA,0BAAkB,EAAE;AACxB,IAAIC,wBAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,kBAAc,EAAE;AACpB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,2BAAmB,EAAE;AACzB,IAAIC,yBAAiB,EAAE;AACvB,IAAIC,gCAAqB,EAAE;AAC3B,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,8BAAsB,EAAE;AAC5B,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAIC,yBAAoB;AACxB,IAAIC,uBAAkB;AACtB,IAAIC,yBAAiB;AACrB,IAAIC,yBAAiB;AACrB,IAAIC,uBAAiB;AACrB,IAAIC,yBAAmB;AACvB,IAAIC,sBAAc;AAClB,IAAIC,qBAAe;AACnB,IAAIC,iBAAa;AACjB,IAAIC,iCAAqB;AACzB,IAAIC,qBAAe;AACnB,IAAIC,2BAAkB;AACtB,IAAIC,qBAAe;AACnB,IAAIC,uBAAgB;AACpB,IAAIC,2BAAkB;AACtB,IAAIR,sBAAc;AAClB,IAAIS,yBAAiB;AACrB,IAAIC,qBAAe;AACnB,IAAIC,yBAAiB;AACrB,IAAIC,iCAAqB;AACzB,IAAIC,yBAAiB;AACrB,IAAIC,0BAAkB;AACtB,IAAIC,wBAAgB;AACpB,IAAIC,+BAAoB;AACxB,IAAIC,2BAAkB;AACtB,IAAIC,6BAAqB;AACzB,GAAG;AACH;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n ];\n}\n"],"names":["expressIntegration","fastifyIntegration","graphqlIntegration","mongoIntegration","mongooseIntegration","mysqlIntegration","mysql2Integration","redisIntegration","postgresIntegration","prismaIntegration","hapiIntegration","koaIntegration","connectIntegration","tediousIntegration","genericPoolIntegration","kafkaIntegration","amqplibIntegration","lruMemoizerIntegration","vercelAIIntegration","openAIIntegration","postgresJsIntegration","firebaseIntegration","anthropicAIIntegration","googleGenAIIntegration","instrumentSentryHttp","instrumentOtelHttp","instrumentExpress","instrumentConnect","instrumentFastify","instrumentFastifyV3","instrumentHapi","instrumentKafka","instrumentKoa","instrumentLruMemoizer","instrumentMongo","instrumentMongoose","instrumentMysql","instrumentMysql2","instrumentPostgres","instrumentGraphql","instrumentRedis","instrumentTedious","instrumentGenericPool","instrumentAmqplib","instrumentVercelAi","instrumentOpenAi","instrumentPostgresJs","instrumentFirebase","instrumentAnthropicAi","instrumentGoogleGenAI"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAIA,0BAAkB,EAAE;AACxB,IAAIC,wBAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,kBAAc,EAAE;AACpB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,2BAAmB,EAAE;AACzB,IAAIC,yBAAiB,EAAE;AACvB,IAAIC,gCAAqB,EAAE;AAC3B,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,8BAAsB,EAAE;AAC5B,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAIC,yBAAoB;AACxB,IAAIC,uBAAkB;AACtB,IAAIC,yBAAiB;AACrB,IAAIC,yBAAiB;AACrB,IAAIC,uBAAiB;AACrB,IAAIC,yBAAmB;AACvB,IAAIC,sBAAc;AAClB,IAAIC,qBAAe;AACnB,IAAIC,iBAAa;AACjB,IAAIC,iCAAqB;AACzB,IAAIC,qBAAe;AACnB,IAAIC,2BAAkB;AACtB,IAAIC,qBAAe;AACnB,IAAIC,uBAAgB;AACpB,IAAIC,2BAAkB;AACtB,IAAIR,sBAAc;AAClB,IAAIS,yBAAiB;AACrB,IAAIC,qBAAe;AACnB,IAAIC,yBAAiB;AACrB,IAAIC,iCAAqB;AACzB,IAAIC,yBAAiB;AACrB,IAAIC,0BAAkB;AACtB,IAAIC,wBAAgB;AACpB,IAAIC,+BAAoB;AACxB,IAAIC,2BAAkB;AACtB,IAAIC,6BAAqB;AACzB,IAAIC,6BAAqB;AACzB,GAAG;AACH;;;;;"}
@@ -41,10 +41,10 @@ class SentryOpenAiInstrumentation extends instrumentation.InstrumentationBase {
41
41
 
42
42
  const WrappedOpenAI = function ( ...args) {
43
43
  const instance = Reflect.construct(Original, args);
44
- const scopeClient = core.getCurrentScope().getClient();
45
- const integration = scopeClient?.getIntegrationByName(core.OPENAI_INTEGRATION_NAME);
44
+ const client = core.getClient();
45
+ const integration = client?.getIntegrationByName(core.OPENAI_INTEGRATION_NAME);
46
46
  const integrationOpts = integration?.options;
47
- const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);
47
+ const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
48
48
 
49
49
  const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);
50
50
 
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/openai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core';\nimport { getCurrentScope, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=4.0.0 <6'];\n\nexport interface OpenAiIntegration extends Integration {\n options: OpenAiOptions;\n}\n\n/**\n * Represents the patched shape of the OpenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n OpenAI: abstract new (...args: unknown[]) => OpenAiClient;\n}\n\n/**\n * Determines telemetry recording settings.\n */\nfunction determineRecordingSettings(\n integrationOptions: OpenAiOptions | undefined,\n defaultEnabled: boolean,\n): { recordInputs: boolean; recordOutputs: boolean } {\n const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;\n const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;\n return { recordInputs, recordOutputs };\n}\n\n/**\n * Sentry OpenAI instrumentation using OpenTelemetry.\n */\nexport class SentryOpenAiInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n public constructor(config: InstrumentationConfig = {}) {\n super('@sentry/instrumentation-openai', 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('openai', supportedVersions, this._patch.bind(this));\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the OpenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.OpenAI;\n\n const WrappedOpenAI = function (this: unknown, ...args: unknown[]) {\n const instance = Reflect.construct(Original, args);\n const scopeClient = getCurrentScope().getClient();\n const integration = scopeClient?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);\n const integrationOpts = integration?.options;\n const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);\n\n const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);\n\n return instrumentOpenAiClient(instance as OpenAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => OpenAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedOpenAI, Original);\n Object.setPrototypeOf(WrappedOpenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedOpenAI, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The OpenAI property might have only a getter, so use defineProperty\n try {\n exports.OpenAI = WrappedOpenAI;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'OpenAI', {\n value: WrappedOpenAI,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The OpenAI property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedOpenAI;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedOpenAI,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","getCurrentScope","OPENAI_INTEGRATION_NAME","instrumentOpenAiClient"],"mappings":"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"}
1
+ {"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/openai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core';\nimport { getClient, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=4.0.0 <6'];\n\nexport interface OpenAiIntegration extends Integration {\n options: OpenAiOptions;\n}\n\n/**\n * Represents the patched shape of the OpenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n OpenAI: abstract new (...args: unknown[]) => OpenAiClient;\n}\n\n/**\n * Determines telemetry recording settings.\n */\nfunction determineRecordingSettings(\n integrationOptions: OpenAiOptions | undefined,\n defaultEnabled: boolean,\n): { recordInputs: boolean; recordOutputs: boolean } {\n const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;\n const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;\n return { recordInputs, recordOutputs };\n}\n\n/**\n * Sentry OpenAI instrumentation using OpenTelemetry.\n */\nexport class SentryOpenAiInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n public constructor(config: InstrumentationConfig = {}) {\n super('@sentry/instrumentation-openai', 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('openai', supportedVersions, this._patch.bind(this));\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the OpenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.OpenAI;\n\n const WrappedOpenAI = function (this: unknown, ...args: unknown[]) {\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const integration = client?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);\n const integrationOpts = integration?.options;\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);\n\n return instrumentOpenAiClient(instance as OpenAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => OpenAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedOpenAI, Original);\n Object.setPrototypeOf(WrappedOpenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedOpenAI, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The OpenAI property might have only a getter, so use defineProperty\n try {\n exports.OpenAI = WrappedOpenAI;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'OpenAI', {\n value: WrappedOpenAI,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The OpenAI property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedOpenAI;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedOpenAI,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","getClient","OPENAI_INTEGRATION_NAME","instrumentOpenAiClient"],"mappings":"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"}