@sentry/node 10.11.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 (102) hide show
  1. package/build/cjs/index.js +10 -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/connect.js +6 -1
  10. package/build/cjs/integrations/tracing/connect.js.map +1 -1
  11. package/build/cjs/integrations/tracing/express.js +1 -1
  12. package/build/cjs/integrations/tracing/express.js.map +1 -1
  13. package/build/cjs/integrations/tracing/fastify/index.js +1 -1
  14. package/build/cjs/integrations/tracing/fastify/index.js.map +1 -1
  15. package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js +3 -0
  16. package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
  17. package/build/cjs/integrations/tracing/google-genai/index.js +78 -0
  18. package/build/cjs/integrations/tracing/google-genai/index.js.map +1 -0
  19. package/build/cjs/integrations/tracing/google-genai/instrumentation.js +94 -0
  20. package/build/cjs/integrations/tracing/google-genai/instrumentation.js.map +1 -0
  21. package/build/cjs/integrations/tracing/hapi/index.js +1 -4
  22. package/build/cjs/integrations/tracing/hapi/index.js.map +1 -1
  23. package/build/cjs/integrations/tracing/index.js +3 -0
  24. package/build/cjs/integrations/tracing/index.js.map +1 -1
  25. package/build/cjs/integrations/tracing/koa.js +6 -1
  26. package/build/cjs/integrations/tracing/koa.js.map +1 -1
  27. package/build/cjs/integrations/tracing/openai/instrumentation.js +3 -3
  28. package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -1
  29. package/build/cjs/integrations/tracing/prisma.js +117 -56
  30. package/build/cjs/integrations/tracing/prisma.js.map +1 -1
  31. package/build/cjs/integrations/tracing/vercelai/instrumentation.js +44 -46
  32. package/build/cjs/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  33. package/build/cjs/sdk/initOtel.js +1 -35
  34. package/build/cjs/sdk/initOtel.js.map +1 -1
  35. package/build/esm/index.js +2 -1
  36. package/build/esm/index.js.map +1 -1
  37. package/build/esm/integrations/http.js +25 -14
  38. package/build/esm/integrations/http.js.map +1 -1
  39. package/build/esm/integrations/tracing/anthropic-ai/index.js +2 -2
  40. package/build/esm/integrations/tracing/anthropic-ai/index.js.map +1 -1
  41. package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js +7 -18
  42. package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
  43. package/build/esm/integrations/tracing/connect.js +6 -1
  44. package/build/esm/integrations/tracing/connect.js.map +1 -1
  45. package/build/esm/integrations/tracing/express.js +1 -1
  46. package/build/esm/integrations/tracing/express.js.map +1 -1
  47. package/build/esm/integrations/tracing/fastify/index.js +1 -1
  48. package/build/esm/integrations/tracing/fastify/index.js.map +1 -1
  49. package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js +3 -0
  50. package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
  51. package/build/esm/integrations/tracing/google-genai/index.js +75 -0
  52. package/build/esm/integrations/tracing/google-genai/index.js.map +1 -0
  53. package/build/esm/integrations/tracing/google-genai/instrumentation.js +92 -0
  54. package/build/esm/integrations/tracing/google-genai/instrumentation.js.map +1 -0
  55. package/build/esm/integrations/tracing/hapi/index.js +1 -4
  56. package/build/esm/integrations/tracing/hapi/index.js.map +1 -1
  57. package/build/esm/integrations/tracing/index.js +3 -0
  58. package/build/esm/integrations/tracing/index.js.map +1 -1
  59. package/build/esm/integrations/tracing/koa.js +6 -1
  60. package/build/esm/integrations/tracing/koa.js.map +1 -1
  61. package/build/esm/integrations/tracing/openai/instrumentation.js +4 -4
  62. package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -1
  63. package/build/esm/integrations/tracing/prisma.js +117 -56
  64. package/build/esm/integrations/tracing/prisma.js.map +1 -1
  65. package/build/esm/integrations/tracing/vercelai/instrumentation.js +45 -47
  66. package/build/esm/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  67. package/build/esm/package.json +1 -1
  68. package/build/esm/sdk/initOtel.js +4 -36
  69. package/build/esm/sdk/initOtel.js.map +1 -1
  70. package/build/types/index.d.ts +2 -1
  71. package/build/types/index.d.ts.map +1 -1
  72. package/build/types/integrations/http.d.ts +2 -2
  73. package/build/types/integrations/http.d.ts.map +1 -1
  74. package/build/types/integrations/tracing/anthropic-ai/index.d.ts +1 -2
  75. package/build/types/integrations/tracing/anthropic-ai/index.d.ts.map +1 -1
  76. package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts +5 -6
  77. package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts.map +1 -1
  78. package/build/types/integrations/tracing/connect.d.ts.map +1 -1
  79. package/build/types/integrations/tracing/firebase/otel/patches/firestore.d.ts +4 -2
  80. package/build/types/integrations/tracing/firebase/otel/patches/firestore.d.ts.map +1 -1
  81. package/build/types/integrations/tracing/google-genai/index.d.ts +59 -0
  82. package/build/types/integrations/tracing/google-genai/index.d.ts.map +1 -0
  83. package/build/types/integrations/tracing/google-genai/instrumentation.d.ts +20 -0
  84. package/build/types/integrations/tracing/google-genai/instrumentation.d.ts.map +1 -0
  85. package/build/types/integrations/tracing/hapi/index.d.ts.map +1 -1
  86. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  87. package/build/types/integrations/tracing/koa.d.ts.map +1 -1
  88. package/build/types/integrations/tracing/prisma.d.ts +9 -13
  89. package/build/types/integrations/tracing/prisma.d.ts.map +1 -1
  90. package/build/types/integrations/tracing/vercelai/instrumentation.d.ts.map +1 -1
  91. package/build/types/sdk/initOtel.d.ts +0 -2
  92. package/build/types/sdk/initOtel.d.ts.map +1 -1
  93. package/build/types-ts3.8/index.d.ts +2 -1
  94. package/build/types-ts3.8/integrations/http.d.ts +2 -2
  95. package/build/types-ts3.8/integrations/tracing/anthropic-ai/index.d.ts +1 -2
  96. package/build/types-ts3.8/integrations/tracing/anthropic-ai/instrumentation.d.ts +5 -6
  97. package/build/types-ts3.8/integrations/tracing/firebase/otel/patches/firestore.d.ts +4 -2
  98. package/build/types-ts3.8/integrations/tracing/google-genai/index.d.ts +59 -0
  99. package/build/types-ts3.8/integrations/tracing/google-genai/instrumentation.d.ts +20 -0
  100. package/build/types-ts3.8/integrations/tracing/prisma.d.ts +9 -13
  101. package/build/types-ts3.8/sdk/initOtel.d.ts +0 -2
  102. package/package.json +32 -32
@@ -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;
@@ -109,6 +111,7 @@ exports.close = core.close;
109
111
  exports.consoleIntegration = core.consoleIntegration;
110
112
  exports.consoleLoggingIntegration = core.consoleLoggingIntegration;
111
113
  exports.continueTrace = core.continueTrace;
114
+ exports.createConsolaReporter = core.createConsolaReporter;
112
115
  exports.createTransport = core.createTransport;
113
116
  exports.dedupeIntegration = core.dedupeIntegration;
114
117
  exports.endSession = core.endSession;
@@ -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":";;;;;;;;AAkBA,MAAM,gBAAA,GAAmB,MAAM;;AAE/B,MAAM,oBAAA,GAAuB,oDAAoD;;AAuH1E,MAAM,oBAAA,GAAuBA,+BAAsB;AAC1D,EAAE,CAAC,EAAA,gBAAA,CAAA,OAAA,CAAA;AACA,EAAA,OAAA,IAAA;AACA,IAAA,OAAA,IAAAC,kCAAA,CAAA,OAAA,CAAA;AACA,GAAA;AACA;;AAEA,MAAA,kBAAA,GAAAD,+BAAA,CAAA,gBAAA,EAAA,MAAA,IAAA;AACA,EAAA,MAAA,eAAA,GAAA,IAAAE,uCAAA,CAAA;AACA,IAAA,GAAA,MAAA;AACA;AACA,IAAA,qCAAA,EAAA,IAAA;AACA,GAAA,CAAA;;AAEA;AACA,EAAA,IAAA;AACA,IAAA,eAAA,CAAA,OAAA,CAAA,GAAAC,QAAA,CAAA,qBAAA,CAAA;AACA,MAAA,SAAA,EAAA,oBAAA;AACA,KAAA,CAAA;AACA;AACA,IAAA,eAAA,CAAA,mBAAA,GAAA,oBAAA;AACA,GAAA,CAAA,MAAA;AACA;AACA;;AAEA,EAAA,OAAA,eAAA;AACA,CAAA;;AAEA;AACA,SAAA,iCAAA;AACA,EAAA,OAAA;AACA,EAAA,aAAA,GAAA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA,IAAA,OAAA,OAAA,CAAA,KAAA,KAAA,SAAA,EAAA;AACA,IAAA,OAAA,OAAA,CAAA,KAAA;AACA;;AAEA,EAAA,IAAA,aAAA,CAAA,sBAAA,EAAA;AACA,IAAA,OAAA,KAAA;AACA;;AAEA;AACA;AACA,EAAA,IAAA,CAAAC,oBAAA,CAAA,aAAA,CAAA,IAAAC,qBAAA,CAAA,KAAA,IAAA,EAAA,EAAA;AACA,IAAA,OAAA,KAAA;AACA;;AAEA,EAAA,OAAA,IAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAA,eAAA,GAAAC,sBAAA,CAAA,CAAA,OAAA,GAAA,EAAA,KAAA;AACA,EAAA,MAAA,sCAAA,GAAA,OAAA,CAAA,sCAAA,IAAA;AACA,IAAA,CAAA,GAAA,EAAA,GAAA,CAAA;AACA;AACA,IAAA,CAAA,GAAA,EAAA,GAAA,CAAA;AACA,IAAA,CAAA,GAAA,EAAA,GAAA,CAAA;AACA,GAAA;;AAEA,EAAA,OAAA;AACA,IAAA,IAAA,EAAA,gBAAA;AACA,IAAA,SAAA,GAAA;AACA,MAAA,MAAA,aAAA,IAAAC,cAAA,EAAA,EAAA,UAAA,EAAA,IAAA,EAAA,CAAA;AACA,MAAA,MAAA,0BAAA,GAAA,iCAAA,CAAA,OAAA,EAAA,aAAA,CAAA;AACA,MAAA,MAAA,2BAAA,GAAA,OAAA,CAAA,2BAAA,IAAA,CAAAH,oBAAA,CAAA,aAAA,CAAA;;AAEA;AACA,MAAA,oBAAA,CAAA;AACA,QAAA,GAAA,OAAA;AACA,QAAA,2BAAA;AACA,QAAA,8BAAA,EAAA,OAAA,CAAA,sBAAA;AACA;AACA;AACA,QAAA,gCAAA,EAAA,CAAA,0BAAA;AACA,OAAA,CAAA;;AAEA;AACA,MAAA,IAAA,0BAAA,EAAA;AACA,QAAA,MAAA,qBAAA,GAAA,qBAAA,CAAA,OAAA,CAAA;AACA,QAAA,kBAAA,CAAA,qBAAA,CAAA;AACA;AACA,KAAA;AACA,IAAA,YAAA,CAAA,KAAA,EAAA;AACA;AACA,MAAA,IAAA,KAAA,CAAA,IAAA,KAAA,aAAA,EAAA;AACA,QAAA,MAAA,UAAA,GAAA,KAAA,CAAA,QAAA,EAAA,KAAA,EAAA,IAAA,GAAA,2BAAA,CAAA;AACA,QAAA,IAAA,OAAA,UAAA,KAAA,QAAA,EAAA;AACA,UAAA,MAAA,UAAA,GAAA,sBAAA,CAAA,UAAA,EAAA,sCAAA,CAAA;AACA,UAAA,IAAA,UAAA,EAAA;AACA,YAAAI,sBAAA,IAAAC,UAAA,CAAA,GAAA,CAAA,yCAAA,EAAA,UAAA,CAAA;AACA,YAAA,OAAA,IAAA;AACA;AACA;AACA;;AAEA,MAAA,OAAA,KAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA;;AAEA,SAAA,qBAAA,CAAA,OAAA,GAAA,EAAA,EAAA;AACA,EAAA,MAAA,qBAAA,GAAA;AACA,IAAA,yBAAA,EAAA,OAAA,IAAA;AACA,MAAA,MAAA,GAAA,GAAAC,sBAAA,CAAA,OAAA,CAAA;;AAEA,MAAA,IAAA,CAAA,GAAA,EAAA;AACA,QAAA,OAAA,KAAA;AACA;;AAEA,MAAA,MAAA,uBAAA,GAAA,OAAA,CAAA,sBAAA;AACA,MAAA,IAAA,uBAAA,GAAA,GAAA,EAAA,OAAA,CAAA,EAAA;AACA,QAAA,OAAA,IAAA;AACA;;AAEA,MAAA,OAAA,KAAA;AACA,KAAA;;AAEA,IAAA,6BAAA,EAAA,KAAA;AACA,IAAA,WAAA,EAAA,CAAA,IAAA,EAAA,GAAA,KAAA;AACA,MAAAC,wBAAA,CAAA,IAAA,EAAA,qBAAA,CAAA;;AAEA,MAAA,OAAA,CAAA,eAAA,EAAA,WAAA,GAAA,IAAA,EAAA,GAAA,CAAA;AACA,KAAA;AACA,IAAA,YAAA,EAAA,CAAA,IAAA,EAAA,GAAA,KAAA;AACA,MAAA,OAAA,CAAA,eAAA,EAAA,YAAA,GAAA,IAAA,EAAA,GAAA,CAAA;AACA,KAAA;AACA,IAAA,2BAAA,EAAA;AACA,MAAA,IAAA;AACA,MAAA,OAAA;AACA,MAAA,QAAA;AACA,SAAA;AACA,MAAA,OAAA,CAAA,eAAA,EAAA,2BAAA,GAAA,IAAA,EAAA,OAAA,EAAA,QAAA,CAAA;AACA,KAAA;AACA,GAAA;;AAEA,EAAA,OAAA,qBAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,sBAAA,CAAA,UAAA,EAAA,kBAAA,EAAA;AACA,EAAA,OAAA,kBAAA,CAAA,IAAA,CAAA,IAAA,IAAA;AACA,IAAA,IAAA,OAAA,IAAA,KAAA,QAAA,EAAA;AACA,MAAA,OAAA,IAAA,KAAA,UAAA;AACA;;AAEA,IAAA,MAAA,CAAA,GAAA,EAAA,GAAA,CAAA,GAAA,IAAA;AACA,IAAA,OAAA,UAAA,IAAA,GAAA,IAAA,UAAA,IAAA,GAAA;AACA,GAAA,CAAA;AACA;;;;;;;"}
@@ -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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"}
@@ -37,7 +37,12 @@ const connectIntegration = core.defineIntegration(_connectIntegration);
37
37
 
38
38
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
39
  function connectErrorMiddleware(err, req, res, next) {
40
- core.captureException(err);
40
+ core.captureException(err, {
41
+ mechanism: {
42
+ handled: false,
43
+ type: 'auto.middleware.connect',
44
+ },
45
+ });
41
46
  next(err);
42
47
  }
43
48
 
@@ -1 +1 @@
1
- {"version":3,"file":"connect.js","sources":["../../../../src/integrations/tracing/connect.ts"],"sourcesContent":["import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n defineIntegration,\n getClient,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\n\ntype ConnectApp = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use: (middleware: any) => void;\n};\n\nconst INTEGRATION_NAME = 'Connect';\n\nexport const instrumentConnect = generateInstrumentOnce(INTEGRATION_NAME, () => new ConnectInstrumentation());\n\nconst _connectIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentConnect();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Connect](https://github.com/senchalabs/connect/).\n *\n * If you also want to capture errors, you need to call `setupConnectErrorHandler(app)` after you initialize your connect app.\n *\n * For more information, see the [connect documentation](https://docs.sentry.io/platforms/javascript/guides/connect/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.connectIntegration()],\n * })\n * ```\n */\nexport const connectIntegration = defineIntegration(_connectIntegration);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction connectErrorMiddleware(err: any, req: any, res: any, next: any): void {\n captureException(err);\n next(err);\n}\n\n/**\n * Add a Connect middleware to capture errors to Sentry.\n *\n * @param app The Connect app to attach the error handler to\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const connect = require(\"connect\");\n *\n * const app = connect();\n *\n * Sentry.setupConnectErrorHandler(app);\n *\n * // Add you connect routes here\n *\n * app.listen(3000);\n * ```\n */\nexport const setupConnectErrorHandler = (app: ConnectApp): void => {\n app.use(connectErrorMiddleware);\n\n // Sadly, ConnectInstrumentation has no requestHook, so we need to add the attributes here\n // We register this hook in this method, because if we register it in the integration `setup`,\n // it would always run even for users that are not even using connect\n const client = getClient();\n if (client) {\n client.on('spanStart', span => {\n addConnectSpanAttributes(span);\n });\n }\n\n ensureIsWrapped(app.use, 'connect');\n};\n\nfunction addConnectSpanAttributes(span: Span): void {\n const attributes = spanToJSON(span).data;\n\n // this is one of: middleware, request_handler\n const type = attributes['connect.type'];\n\n // If this is already set, or we have no connect span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || !type) {\n return;\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.connect',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.connect`,\n });\n\n // Also update the name, we don't need the \"middleware - \" prefix\n const name = attributes['connect.name'];\n if (typeof name === 'string') {\n span.updateName(name);\n }\n}\n"],"names":["generateInstrumentOnce","ConnectInstrumentation","defineIntegration","captureException","getClient","ensureIsWrapped","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":";;;;;;AAiBA,MAAM,gBAAA,GAAmB,SAAS;;AAE3B,MAAM,iBAAA,GAAoBA,+BAAsB,CAAC,gBAAgB,EAAE,MAAM,IAAIC,6CAAsB,EAAE;;AAE5G,MAAM,mBAAA,IAAuB,MAAM;AACnC,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAM,iBAAiB,EAAE;AACzB,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,kBAAA,GAAqBC,sBAAiB,CAAC,mBAAmB;;AAEvE;AACA,SAAS,sBAAsB,CAAC,GAAG,EAAO,GAAG,EAAO,GAAG,EAAO,IAAI,EAAa;AAC/E,EAAEC,qBAAgB,CAAC,GAAG,CAAC;AACvB,EAAE,IAAI,CAAC,GAAG,CAAC;AACX;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,wBAAA,GAA2B,CAAC,GAAG,KAAuB;AACnE,EAAE,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC;;AAEjC;AACA;AACA;AACA,EAAE,MAAM,MAAA,GAASC,cAAS,EAAE;AAC5B,EAAE,IAAI,MAAM,EAAE;AACd,IAAI,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ;AACnC,MAAM,wBAAwB,CAAC,IAAI,CAAC;AACpC,KAAK,CAAC;AACN;;AAEA,EAAEC,wBAAe,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC;AACrC;;AAEA,SAAS,wBAAwB,CAAC,IAAI,EAAc;AACpD,EAAE,MAAM,aAAaC,eAAU,CAAC,IAAI,CAAC,CAAC,IAAI;;AAE1C;AACA,EAAE,MAAM,IAAA,GAAO,UAAU,CAAC,cAAc,CAAC;;AAEzC;AACA,EAAE,IAAI,UAAU,CAACC,iCAA4B,CAAA,IAAK,CAAC,IAAI,EAAE;AACzD,IAAI;AACJ;;AAEA,EAAE,IAAI,CAAC,aAAa,CAAC;AACrB,IAAI,CAACC,qCAAgC,GAAG,wBAAwB;AAChE,IAAI,CAACD,iCAA4B,GAAG,CAAC,EAAA,IAAA,CAAA,QAAA,CAAA;AACA,GAAA,CAAA;;AAEA;AACA,EAAA,MAAA,IAAA,GAAA,UAAA,CAAA,cAAA,CAAA;AACA,EAAA,IAAA,OAAA,IAAA,KAAA,QAAA,EAAA;AACA,IAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA;AACA;AACA;;;;;;"}
1
+ {"version":3,"file":"connect.js","sources":["../../../../src/integrations/tracing/connect.ts"],"sourcesContent":["import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n defineIntegration,\n getClient,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\n\ntype ConnectApp = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use: (middleware: any) => void;\n};\n\nconst INTEGRATION_NAME = 'Connect';\n\nexport const instrumentConnect = generateInstrumentOnce(INTEGRATION_NAME, () => new ConnectInstrumentation());\n\nconst _connectIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentConnect();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Connect](https://github.com/senchalabs/connect/).\n *\n * If you also want to capture errors, you need to call `setupConnectErrorHandler(app)` after you initialize your connect app.\n *\n * For more information, see the [connect documentation](https://docs.sentry.io/platforms/javascript/guides/connect/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.connectIntegration()],\n * })\n * ```\n */\nexport const connectIntegration = defineIntegration(_connectIntegration);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction connectErrorMiddleware(err: any, req: any, res: any, next: any): void {\n captureException(err, {\n mechanism: {\n handled: false,\n type: 'auto.middleware.connect',\n },\n });\n next(err);\n}\n\n/**\n * Add a Connect middleware to capture errors to Sentry.\n *\n * @param app The Connect app to attach the error handler to\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const connect = require(\"connect\");\n *\n * const app = connect();\n *\n * Sentry.setupConnectErrorHandler(app);\n *\n * // Add you connect routes here\n *\n * app.listen(3000);\n * ```\n */\nexport const setupConnectErrorHandler = (app: ConnectApp): void => {\n app.use(connectErrorMiddleware);\n\n // Sadly, ConnectInstrumentation has no requestHook, so we need to add the attributes here\n // We register this hook in this method, because if we register it in the integration `setup`,\n // it would always run even for users that are not even using connect\n const client = getClient();\n if (client) {\n client.on('spanStart', span => {\n addConnectSpanAttributes(span);\n });\n }\n\n ensureIsWrapped(app.use, 'connect');\n};\n\nfunction addConnectSpanAttributes(span: Span): void {\n const attributes = spanToJSON(span).data;\n\n // this is one of: middleware, request_handler\n const type = attributes['connect.type'];\n\n // If this is already set, or we have no connect span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || !type) {\n return;\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.connect',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.connect`,\n });\n\n // Also update the name, we don't need the \"middleware - \" prefix\n const name = attributes['connect.name'];\n if (typeof name === 'string') {\n span.updateName(name);\n }\n}\n"],"names":["generateInstrumentOnce","ConnectInstrumentation","defineIntegration","captureException","getClient","ensureIsWrapped","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":";;;;;;AAiBA,MAAM,gBAAA,GAAmB,SAAS;;AAE3B,MAAM,iBAAA,GAAoBA,+BAAsB,CAAC,gBAAgB,EAAE,MAAM,IAAIC,6CAAsB,EAAE;;AAE5G,MAAM,mBAAA,IAAuB,MAAM;AACnC,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAM,iBAAiB,EAAE;AACzB,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,kBAAA,GAAqBC,sBAAiB,CAAC,mBAAmB;;AAEvE;AACA,SAAS,sBAAsB,CAAC,GAAG,EAAO,GAAG,EAAO,GAAG,EAAO,IAAI,EAAa;AAC/E,EAAEC,qBAAgB,CAAC,GAAG,EAAE;AACxB,IAAI,SAAS,EAAE;AACf,MAAM,OAAO,EAAE,KAAK;AACpB,MAAM,IAAI,EAAE,yBAAyB;AACrC,KAAK;AACL,GAAG,CAAC;AACJ,EAAE,IAAI,CAAC,GAAG,CAAC;AACX;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,wBAAA,GAA2B,CAAC,GAAG,KAAuB;AACnE,EAAE,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC;;AAEjC;AACA;AACA;AACA,EAAE,MAAM,MAAA,GAASC,cAAS,EAAE;AAC5B,EAAE,IAAI,MAAM,EAAE;AACd,IAAI,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ;AACnC,MAAM,wBAAwB,CAAC,IAAI,CAAC;AACpC,KAAK,CAAC;AACN;;AAEA,EAAEC,wBAAe,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC;AACrC;;AAEA,SAAS,wBAAwB,CAAC,IAAI,EAAc;AACpD,EAAE,MAAM,aAAaC,eAAU,CAAC,IAAI,CAAC,CAAC,IAAI;;AAE1C;AACA,EAAE,MAAM,IAAA,GAAO,UAAU,CAAC,cAAc,CAAC;;AAEzC;AACA,EAAE,IAAI,UAAU,CAACC,iCAA4B,CAAA,IAAK,CAAC,IAAI,EAAE;AACzD,IAAI;AACJ;;AAEA,EAAE,IAAI,CAAC,aAAa,CAAC;AACrB,IAAI,CAACC,qCAAgC,GAAG,wBAAwB;AAChE,IAAI,CAACD,iCAA4B,GAAG,CAAC,EAAA,IAAA,CAAA,QAAA,CAAA;AACA,GAAA,CAAA;;AAEA;AACA,EAAA,MAAA,IAAA,GAAA,UAAA,CAAA,cAAA,CAAA;AACA,EAAA,IAAA,OAAA,IAAA,KAAA,QAAA,EAAA;AACA,IAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA;AACA;AACA;;;;;;"}
@@ -93,7 +93,7 @@ function expressErrorHandler(options) {
93
93
  const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError;
94
94
 
95
95
  if (shouldHandleError(error)) {
96
- const eventId = core.captureException(error, { mechanism: { type: 'middleware', handled: false } });
96
+ const eventId = core.captureException(error, { mechanism: { type: 'auto.middleware.express', handled: false } });
97
97
  (res ).sentry = eventId;
98
98
  }
99
99
 
@@ -1 +1 @@
1
- {"version":3,"file":"express.js","sources":["../../../../src/integrations/tracing/express.ts"],"sourcesContent":["import type * as http from 'node:http';\nimport type { Span } from '@opentelemetry/api';\nimport type { ExpressRequestInfo } from '@opentelemetry/instrumentation-express';\nimport { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getDefaultIsolationScope,\n getIsolationScope,\n httpRequestToRequestData,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n} from '@sentry/core';\nimport { addOriginToSpan, ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../debug-build';\n\nconst INTEGRATION_NAME = 'Express';\n\nfunction requestHook(span: Span): void {\n addOriginToSpan(span, 'auto.http.otel.express');\n\n const attributes = spanToJSON(span).data;\n // this is one of: middleware, request_handler, router\n const type = attributes['express.type'];\n\n if (type) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, `${type}.express`);\n }\n\n // Also update the name, we don't need to \"middleware - \" prefix\n const name = attributes['express.name'];\n if (typeof name === 'string') {\n span.updateName(name);\n }\n}\n\nfunction spanNameHook(info: ExpressRequestInfo<unknown>, defaultName: string): string {\n if (getIsolationScope() === getDefaultIsolationScope()) {\n DEBUG_BUILD && debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');\n return defaultName;\n }\n if (info.layerType === 'request_handler') {\n // type cast b/c Otel unfortunately types info.request as any :(\n const req = info.request as { method?: string };\n const method = req.method ? req.method.toUpperCase() : 'GET';\n getIsolationScope().setTransactionName(`${method} ${info.route}`);\n }\n return defaultName;\n}\n\nexport const instrumentExpress = generateInstrumentOnce(\n INTEGRATION_NAME,\n () =>\n new ExpressInstrumentation({\n requestHook: span => requestHook(span),\n spanNameHook: (info, defaultName) => spanNameHook(info, defaultName),\n }),\n);\n\nconst _expressIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentExpress();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Express](https://expressjs.com/).\n *\n * If you also want to capture errors, you need to call `setupExpressErrorHandler(app)` after you set up your Express server.\n *\n * For more information, see the [express documentation](https://docs.sentry.io/platforms/javascript/guides/express/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.expressIntegration()],\n * })\n * ```\n */\nexport const expressIntegration = defineIntegration(_expressIntegration);\n\ninterface MiddlewareError extends Error {\n status?: number | string;\n statusCode?: number | string;\n status_code?: number | string;\n output?: {\n statusCode?: number | string;\n };\n}\n\ntype ExpressMiddleware = (req: http.IncomingMessage, res: http.ServerResponse, next: () => void) => void;\n\ntype ExpressErrorMiddleware = (\n error: MiddlewareError,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n next: (error: MiddlewareError) => void,\n) => void;\n\ninterface ExpressHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * @param error Captured middleware error\n */\n shouldHandleError?(this: void, error: MiddlewareError): boolean;\n}\n\n/**\n * An Express-compatible error handler.\n */\nexport function expressErrorHandler(options?: ExpressHandlerOptions): ExpressErrorMiddleware {\n return function sentryErrorMiddleware(\n error: MiddlewareError,\n request: http.IncomingMessage,\n res: http.ServerResponse,\n next: (error: MiddlewareError) => void,\n ): void {\n const normalizedRequest = httpRequestToRequestData(request);\n // Ensure we use the express-enhanced request here, instead of the plain HTTP one\n // When an error happens, the `expressRequestHandler` middleware does not run, so we set it here too\n getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });\n\n const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError;\n\n if (shouldHandleError(error)) {\n const eventId = captureException(error, { mechanism: { type: 'middleware', handled: false } });\n (res as { sentry?: string }).sentry = eventId;\n }\n\n next(error);\n };\n}\n\nfunction expressRequestHandler(): ExpressMiddleware {\n return function sentryRequestMiddleware(\n request: http.IncomingMessage,\n _res: http.ServerResponse,\n next: () => void,\n ): void {\n const normalizedRequest = httpRequestToRequestData(request);\n // Ensure we use the express-enhanced request here, instead of the plain HTTP one\n getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });\n\n next();\n };\n}\n\n/**\n * Add an Express error handler to capture errors to Sentry.\n *\n * The error handler must be before any other middleware and after all controllers.\n *\n * @param app The Express instances\n * @param options {ExpressHandlerOptions} Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const express = require(\"express\");\n *\n * const app = express();\n *\n * // Add your routes, etc.\n *\n * // Add this after all routes,\n * // but before any and other error-handling middlewares are defined\n * Sentry.setupExpressErrorHandler(app);\n *\n * app.listen(3000);\n * ```\n */\nexport function setupExpressErrorHandler(\n app: { use: (middleware: ExpressMiddleware | ExpressErrorMiddleware) => unknown },\n options?: ExpressHandlerOptions,\n): void {\n app.use(expressRequestHandler());\n app.use(expressErrorHandler(options));\n ensureIsWrapped(app.use, 'express');\n}\n\nfunction getStatusCodeFromResponse(error: MiddlewareError): number {\n const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;\n return statusCode ? parseInt(statusCode as string, 10) : 500;\n}\n\n/** Returns true if response code is internal server error */\nfunction defaultShouldHandleError(error: MiddlewareError): boolean {\n const status = getStatusCodeFromResponse(error);\n return status >= 500;\n}\n"],"names":["addOriginToSpan","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","getIsolationScope","getDefaultIsolationScope","DEBUG_BUILD","debug","generateInstrumentOnce","ExpressInstrumentation","defineIntegration","httpRequestToRequestData","captureException","ensureIsWrapped"],"mappings":"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"}
1
+ {"version":3,"file":"express.js","sources":["../../../../src/integrations/tracing/express.ts"],"sourcesContent":["import type * as http from 'node:http';\nimport type { Span } from '@opentelemetry/api';\nimport type { ExpressRequestInfo } from '@opentelemetry/instrumentation-express';\nimport { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getDefaultIsolationScope,\n getIsolationScope,\n httpRequestToRequestData,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n} from '@sentry/core';\nimport { addOriginToSpan, ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../debug-build';\n\nconst INTEGRATION_NAME = 'Express';\n\nfunction requestHook(span: Span): void {\n addOriginToSpan(span, 'auto.http.otel.express');\n\n const attributes = spanToJSON(span).data;\n // this is one of: middleware, request_handler, router\n const type = attributes['express.type'];\n\n if (type) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, `${type}.express`);\n }\n\n // Also update the name, we don't need to \"middleware - \" prefix\n const name = attributes['express.name'];\n if (typeof name === 'string') {\n span.updateName(name);\n }\n}\n\nfunction spanNameHook(info: ExpressRequestInfo<unknown>, defaultName: string): string {\n if (getIsolationScope() === getDefaultIsolationScope()) {\n DEBUG_BUILD && debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');\n return defaultName;\n }\n if (info.layerType === 'request_handler') {\n // type cast b/c Otel unfortunately types info.request as any :(\n const req = info.request as { method?: string };\n const method = req.method ? req.method.toUpperCase() : 'GET';\n getIsolationScope().setTransactionName(`${method} ${info.route}`);\n }\n return defaultName;\n}\n\nexport const instrumentExpress = generateInstrumentOnce(\n INTEGRATION_NAME,\n () =>\n new ExpressInstrumentation({\n requestHook: span => requestHook(span),\n spanNameHook: (info, defaultName) => spanNameHook(info, defaultName),\n }),\n);\n\nconst _expressIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentExpress();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Express](https://expressjs.com/).\n *\n * If you also want to capture errors, you need to call `setupExpressErrorHandler(app)` after you set up your Express server.\n *\n * For more information, see the [express documentation](https://docs.sentry.io/platforms/javascript/guides/express/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.expressIntegration()],\n * })\n * ```\n */\nexport const expressIntegration = defineIntegration(_expressIntegration);\n\ninterface MiddlewareError extends Error {\n status?: number | string;\n statusCode?: number | string;\n status_code?: number | string;\n output?: {\n statusCode?: number | string;\n };\n}\n\ntype ExpressMiddleware = (req: http.IncomingMessage, res: http.ServerResponse, next: () => void) => void;\n\ntype ExpressErrorMiddleware = (\n error: MiddlewareError,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n next: (error: MiddlewareError) => void,\n) => void;\n\ninterface ExpressHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * @param error Captured middleware error\n */\n shouldHandleError?(this: void, error: MiddlewareError): boolean;\n}\n\n/**\n * An Express-compatible error handler.\n */\nexport function expressErrorHandler(options?: ExpressHandlerOptions): ExpressErrorMiddleware {\n return function sentryErrorMiddleware(\n error: MiddlewareError,\n request: http.IncomingMessage,\n res: http.ServerResponse,\n next: (error: MiddlewareError) => void,\n ): void {\n const normalizedRequest = httpRequestToRequestData(request);\n // Ensure we use the express-enhanced request here, instead of the plain HTTP one\n // When an error happens, the `expressRequestHandler` middleware does not run, so we set it here too\n getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });\n\n const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError;\n\n if (shouldHandleError(error)) {\n const eventId = captureException(error, { mechanism: { type: 'auto.middleware.express', handled: false } });\n (res as { sentry?: string }).sentry = eventId;\n }\n\n next(error);\n };\n}\n\nfunction expressRequestHandler(): ExpressMiddleware {\n return function sentryRequestMiddleware(\n request: http.IncomingMessage,\n _res: http.ServerResponse,\n next: () => void,\n ): void {\n const normalizedRequest = httpRequestToRequestData(request);\n // Ensure we use the express-enhanced request here, instead of the plain HTTP one\n getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });\n\n next();\n };\n}\n\n/**\n * Add an Express error handler to capture errors to Sentry.\n *\n * The error handler must be before any other middleware and after all controllers.\n *\n * @param app The Express instances\n * @param options {ExpressHandlerOptions} Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const express = require(\"express\");\n *\n * const app = express();\n *\n * // Add your routes, etc.\n *\n * // Add this after all routes,\n * // but before any and other error-handling middlewares are defined\n * Sentry.setupExpressErrorHandler(app);\n *\n * app.listen(3000);\n * ```\n */\nexport function setupExpressErrorHandler(\n app: { use: (middleware: ExpressMiddleware | ExpressErrorMiddleware) => unknown },\n options?: ExpressHandlerOptions,\n): void {\n app.use(expressRequestHandler());\n app.use(expressErrorHandler(options));\n ensureIsWrapped(app.use, 'express');\n}\n\nfunction getStatusCodeFromResponse(error: MiddlewareError): number {\n const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;\n return statusCode ? parseInt(statusCode as string, 10) : 500;\n}\n\n/** Returns true if response code is internal server error */\nfunction defaultShouldHandleError(error: MiddlewareError): boolean {\n const status = getStatusCodeFromResponse(error);\n return status >= 500;\n}\n"],"names":["addOriginToSpan","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","getIsolationScope","getDefaultIsolationScope","DEBUG_BUILD","debug","generateInstrumentOnce","ExpressInstrumentation","defineIntegration","httpRequestToRequestData","captureException","ensureIsWrapped"],"mappings":"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"}
@@ -71,7 +71,7 @@ function handleFastifyError(
71
71
  }
72
72
 
73
73
  if (shouldHandleError(error, request, reply)) {
74
- core.captureException(error, { mechanism: { handled: false, type: 'fastify' } });
74
+ core.captureException(error, { mechanism: { handled: false, type: 'auto.function.fastify' } });
75
75
  }
76
76
  }
77
77
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/fastify/index.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { Instrumentation, InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getClient,\n getIsolationScope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport { FastifyOtelInstrumentation } from './fastify-otel/index';\nimport type { FastifyInstance, FastifyReply, FastifyRequest } from './types';\nimport { FastifyInstrumentationV3 } from './v3/instrumentation';\n\n/**\n * Options for the Fastify integration.\n *\n * `shouldHandleError` - Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @example\n *\n * ```javascript\n * Sentry.init({\n * integrations: [\n * Sentry.fastifyIntegration({\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 500;\n * },\n * });\n * },\n * });\n * ```\n *\n */\ninterface FastifyIntegrationOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\ninterface FastifyHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n *\n * @example\n *\n *\n * ```javascript\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 400;\n * },\n * });\n * ```\n *\n *\n * If using TypeScript, you can cast the request and reply to get full type safety.\n *\n * ```typescript\n * import type { FastifyRequest, FastifyReply } from 'fastify';\n *\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(error, minimalRequest, minimalReply) {\n * const request = minimalRequest as FastifyRequest;\n * const reply = minimalReply as FastifyReply;\n * return reply.statusCode >= 500;\n * },\n * });\n * ```\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\nconst INTEGRATION_NAME = 'Fastify';\n\nexport const instrumentFastifyV3 = generateInstrumentOnce(\n `${INTEGRATION_NAME}.v3`,\n () => new FastifyInstrumentationV3(),\n);\n\nfunction getFastifyIntegration(): ReturnType<typeof _fastifyIntegration> | undefined {\n const client = getClient();\n if (!client) {\n return undefined;\n } else {\n return client.getIntegrationByName(INTEGRATION_NAME) as ReturnType<typeof _fastifyIntegration> | undefined;\n }\n}\n\nfunction handleFastifyError(\n this: {\n diagnosticsChannelExists?: boolean;\n },\n error: Error,\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } },\n reply: FastifyReply,\n handlerOrigin: 'diagnostics-channel' | 'onError-hook',\n): void {\n const shouldHandleError = getFastifyIntegration()?.getShouldHandleError() || defaultShouldHandleError;\n // Diagnostics channel runs before the onError hook, so we can use it to check if the handler was already registered\n if (handlerOrigin === 'diagnostics-channel') {\n this.diagnosticsChannelExists = true;\n }\n\n if (this.diagnosticsChannelExists && handlerOrigin === 'onError-hook') {\n DEBUG_BUILD &&\n debug.warn(\n 'Fastify error handler was already registered via diagnostics channel.',\n 'You can safely remove `setupFastifyErrorHandler` call and set `shouldHandleError` on the integration options.',\n );\n\n // If the diagnostics channel already exists, we don't need to handle the error again\n return;\n }\n\n if (shouldHandleError(error, request, reply)) {\n captureException(error, { mechanism: { handled: false, type: 'fastify' } });\n }\n}\n\nexport const instrumentFastify = generateInstrumentOnce(`${INTEGRATION_NAME}.v5`, () => {\n const fastifyOtelInstrumentationInstance = new FastifyOtelInstrumentation();\n const plugin = fastifyOtelInstrumentationInstance.plugin();\n\n // This message handler works for Fastify versions 3, 4 and 5\n diagnosticsChannel.subscribe('fastify.initialization', message => {\n const fastifyInstance = (message as { fastify?: FastifyInstance }).fastify;\n\n fastifyInstance?.register(plugin).after(err => {\n if (err) {\n DEBUG_BUILD && debug.error('Failed to setup Fastify instrumentation', err);\n } else {\n instrumentClient();\n\n if (fastifyInstance) {\n instrumentOnRequest(fastifyInstance);\n }\n }\n });\n });\n\n // This diagnostics channel only works on Fastify version 5\n // For versions 3 and 4, we use `setupFastifyErrorHandler` instead\n diagnosticsChannel.subscribe('tracing:fastify.request.handler:error', message => {\n const { error, request, reply } = message as {\n error: Error;\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } };\n reply: FastifyReply;\n };\n\n handleFastifyError.call(handleFastifyError, error, request, reply, 'diagnostics-channel');\n });\n\n // Returning this as unknown not to deal with the internal types of the FastifyOtelInstrumentation\n return fastifyOtelInstrumentationInstance as Instrumentation<InstrumentationConfig & FastifyIntegrationOptions>;\n});\n\nconst _fastifyIntegration = (({ shouldHandleError }: Partial<FastifyIntegrationOptions>) => {\n let _shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _shouldHandleError = shouldHandleError || defaultShouldHandleError;\n\n instrumentFastifyV3();\n instrumentFastify();\n },\n getShouldHandleError() {\n return _shouldHandleError;\n },\n setShouldHandleError(fn: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean): void {\n _shouldHandleError = fn;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Fastify](https://fastify.dev/).\n *\n * If you also want to capture errors, you need to call `setupFastifyErrorHandler(app)` after you set up your Fastify server.\n *\n * For more information, see the [fastify documentation](https://docs.sentry.io/platforms/javascript/guides/fastify/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.fastifyIntegration()],\n * })\n * ```\n */\nexport const fastifyIntegration = defineIntegration((options: Partial<FastifyIntegrationOptions> = {}) =>\n _fastifyIntegration(options),\n);\n\n/**\n * Default function to determine if an error should be sent to Sentry\n *\n * 3xx and 4xx errors are not sent by default.\n */\nfunction defaultShouldHandleError(_error: Error, _request: FastifyRequest, reply: FastifyReply): boolean {\n const statusCode = reply.statusCode;\n // 3xx and 4xx errors are not sent by default.\n return statusCode >= 500 || statusCode <= 299;\n}\n\n/**\n * Add an Fastify error handler to capture errors to Sentry.\n *\n * @param fastify The Fastify instance to which to add the error handler\n * @param options Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Fastify = require(\"fastify\");\n *\n * const app = Fastify();\n *\n * Sentry.setupFastifyErrorHandler(app);\n *\n * // Add your routes, etc.\n *\n * app.listen({ port: 3000 });\n * ```\n */\nexport function setupFastifyErrorHandler(fastify: FastifyInstance, options?: Partial<FastifyHandlerOptions>): void {\n if (options?.shouldHandleError) {\n getFastifyIntegration()?.setShouldHandleError(options.shouldHandleError);\n }\n\n const plugin = Object.assign(\n function (fastify: FastifyInstance, _options: unknown, done: () => void): void {\n fastify.addHook('onError', async (request, reply, error) => {\n handleFastifyError.call(handleFastifyError, error, request, reply, 'onError-hook');\n });\n done();\n },\n {\n [Symbol.for('skip-override')]: true,\n [Symbol.for('fastify.display-name')]: 'sentry-fastify-error-handler',\n },\n );\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n fastify.register(plugin);\n}\n\nfunction addFastifySpanAttributes(span: Span): void {\n const spanJSON = spanToJSON(span);\n const spanName = spanJSON.description;\n const attributes = spanJSON.data;\n\n const type = attributes['fastify.type'];\n\n const isHook = type === 'hook';\n const isHandler = type === spanName?.startsWith('handler -');\n // In @fastify/otel `request-handler` is separated by dash, not underscore\n const isRequestHandler = spanName === 'request' || type === 'request-handler';\n\n // If this is already set, or we have no fastify span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || (!isHandler && !isRequestHandler && !isHook)) {\n return;\n }\n\n const opPrefix = isHook ? 'hook' : isHandler ? 'middleware' : isRequestHandler ? 'request-handler' : '<unknown>';\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.fastify',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${opPrefix}.fastify`,\n });\n\n const attrName = attributes['fastify.name'] || attributes['plugin.name'] || attributes['hook.name'];\n if (typeof attrName === 'string') {\n // Try removing `fastify -> ` and `@fastify/otel -> ` prefixes\n // This is a bit of a hack, and not always working for all spans\n // But it's the best we can do without a proper API\n const updatedName = attrName.replace(/^fastify -> /, '').replace(/^@fastify\\/otel -> /, '');\n\n span.updateName(updatedName);\n }\n}\n\nfunction instrumentClient(): void {\n const client = getClient();\n if (client) {\n client.on('spanStart', (span: Span) => {\n addFastifySpanAttributes(span);\n });\n }\n}\n\nfunction instrumentOnRequest(fastify: FastifyInstance): void {\n fastify.addHook('onRequest', async (request: FastifyRequest & { opentelemetry?: () => { span?: Span } }, _reply) => {\n if (request.opentelemetry) {\n const { span } = request.opentelemetry();\n\n if (span) {\n addFastifySpanAttributes(span);\n }\n }\n\n const routeName = request.routeOptions?.url;\n const method = request.method || 'GET';\n\n getIsolationScope().setTransactionName(`${method} ${routeName}`);\n });\n}\n"],"names":["generateInstrumentOnce","FastifyInstrumentationV3","getClient","DEBUG_BUILD","debug","captureException","FastifyOtelInstrumentation","diagnosticsChannel","defineIntegration","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","getIsolationScope"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/fastify/index.ts"],"sourcesContent":["import * as diagnosticsChannel from 'node:diagnostics_channel';\nimport type { Instrumentation, InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getClient,\n getIsolationScope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport { FastifyOtelInstrumentation } from './fastify-otel/index';\nimport type { FastifyInstance, FastifyReply, FastifyRequest } from './types';\nimport { FastifyInstrumentationV3 } from './v3/instrumentation';\n\n/**\n * Options for the Fastify integration.\n *\n * `shouldHandleError` - Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @example\n *\n * ```javascript\n * Sentry.init({\n * integrations: [\n * Sentry.fastifyIntegration({\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 500;\n * },\n * });\n * },\n * });\n * ```\n *\n */\ninterface FastifyIntegrationOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * This is used on Fastify v5 where Sentry handles errors in the diagnostics channel.\n * Fastify v3 and v4 use `setupFastifyErrorHandler` instead.\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\ninterface FastifyHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n *\n * @param error Captured Fastify error\n * @param request Fastify request (or any object containing at least method, routeOptions.url, and routerPath)\n * @param reply Fastify reply (or any object containing at least statusCode)\n *\n * @example\n *\n *\n * ```javascript\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(_error, _request, reply) {\n * return reply.statusCode >= 400;\n * },\n * });\n * ```\n *\n *\n * If using TypeScript, you can cast the request and reply to get full type safety.\n *\n * ```typescript\n * import type { FastifyRequest, FastifyReply } from 'fastify';\n *\n * setupFastifyErrorHandler(app, {\n * shouldHandleError(error, minimalRequest, minimalReply) {\n * const request = minimalRequest as FastifyRequest;\n * const reply = minimalReply as FastifyReply;\n * return reply.statusCode >= 500;\n * },\n * });\n * ```\n */\n shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n}\n\nconst INTEGRATION_NAME = 'Fastify';\n\nexport const instrumentFastifyV3 = generateInstrumentOnce(\n `${INTEGRATION_NAME}.v3`,\n () => new FastifyInstrumentationV3(),\n);\n\nfunction getFastifyIntegration(): ReturnType<typeof _fastifyIntegration> | undefined {\n const client = getClient();\n if (!client) {\n return undefined;\n } else {\n return client.getIntegrationByName(INTEGRATION_NAME) as ReturnType<typeof _fastifyIntegration> | undefined;\n }\n}\n\nfunction handleFastifyError(\n this: {\n diagnosticsChannelExists?: boolean;\n },\n error: Error,\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } },\n reply: FastifyReply,\n handlerOrigin: 'diagnostics-channel' | 'onError-hook',\n): void {\n const shouldHandleError = getFastifyIntegration()?.getShouldHandleError() || defaultShouldHandleError;\n // Diagnostics channel runs before the onError hook, so we can use it to check if the handler was already registered\n if (handlerOrigin === 'diagnostics-channel') {\n this.diagnosticsChannelExists = true;\n }\n\n if (this.diagnosticsChannelExists && handlerOrigin === 'onError-hook') {\n DEBUG_BUILD &&\n debug.warn(\n 'Fastify error handler was already registered via diagnostics channel.',\n 'You can safely remove `setupFastifyErrorHandler` call and set `shouldHandleError` on the integration options.',\n );\n\n // If the diagnostics channel already exists, we don't need to handle the error again\n return;\n }\n\n if (shouldHandleError(error, request, reply)) {\n captureException(error, { mechanism: { handled: false, type: 'auto.function.fastify' } });\n }\n}\n\nexport const instrumentFastify = generateInstrumentOnce(`${INTEGRATION_NAME}.v5`, () => {\n const fastifyOtelInstrumentationInstance = new FastifyOtelInstrumentation();\n const plugin = fastifyOtelInstrumentationInstance.plugin();\n\n // This message handler works for Fastify versions 3, 4 and 5\n diagnosticsChannel.subscribe('fastify.initialization', message => {\n const fastifyInstance = (message as { fastify?: FastifyInstance }).fastify;\n\n fastifyInstance?.register(plugin).after(err => {\n if (err) {\n DEBUG_BUILD && debug.error('Failed to setup Fastify instrumentation', err);\n } else {\n instrumentClient();\n\n if (fastifyInstance) {\n instrumentOnRequest(fastifyInstance);\n }\n }\n });\n });\n\n // This diagnostics channel only works on Fastify version 5\n // For versions 3 and 4, we use `setupFastifyErrorHandler` instead\n diagnosticsChannel.subscribe('tracing:fastify.request.handler:error', message => {\n const { error, request, reply } = message as {\n error: Error;\n request: FastifyRequest & { opentelemetry?: () => { span?: Span } };\n reply: FastifyReply;\n };\n\n handleFastifyError.call(handleFastifyError, error, request, reply, 'diagnostics-channel');\n });\n\n // Returning this as unknown not to deal with the internal types of the FastifyOtelInstrumentation\n return fastifyOtelInstrumentationInstance as Instrumentation<InstrumentationConfig & FastifyIntegrationOptions>;\n});\n\nconst _fastifyIntegration = (({ shouldHandleError }: Partial<FastifyIntegrationOptions>) => {\n let _shouldHandleError: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean;\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _shouldHandleError = shouldHandleError || defaultShouldHandleError;\n\n instrumentFastifyV3();\n instrumentFastify();\n },\n getShouldHandleError() {\n return _shouldHandleError;\n },\n setShouldHandleError(fn: (error: Error, request: FastifyRequest, reply: FastifyReply) => boolean): void {\n _shouldHandleError = fn;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Fastify](https://fastify.dev/).\n *\n * If you also want to capture errors, you need to call `setupFastifyErrorHandler(app)` after you set up your Fastify server.\n *\n * For more information, see the [fastify documentation](https://docs.sentry.io/platforms/javascript/guides/fastify/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.fastifyIntegration()],\n * })\n * ```\n */\nexport const fastifyIntegration = defineIntegration((options: Partial<FastifyIntegrationOptions> = {}) =>\n _fastifyIntegration(options),\n);\n\n/**\n * Default function to determine if an error should be sent to Sentry\n *\n * 3xx and 4xx errors are not sent by default.\n */\nfunction defaultShouldHandleError(_error: Error, _request: FastifyRequest, reply: FastifyReply): boolean {\n const statusCode = reply.statusCode;\n // 3xx and 4xx errors are not sent by default.\n return statusCode >= 500 || statusCode <= 299;\n}\n\n/**\n * Add an Fastify error handler to capture errors to Sentry.\n *\n * @param fastify The Fastify instance to which to add the error handler\n * @param options Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Fastify = require(\"fastify\");\n *\n * const app = Fastify();\n *\n * Sentry.setupFastifyErrorHandler(app);\n *\n * // Add your routes, etc.\n *\n * app.listen({ port: 3000 });\n * ```\n */\nexport function setupFastifyErrorHandler(fastify: FastifyInstance, options?: Partial<FastifyHandlerOptions>): void {\n if (options?.shouldHandleError) {\n getFastifyIntegration()?.setShouldHandleError(options.shouldHandleError);\n }\n\n const plugin = Object.assign(\n function (fastify: FastifyInstance, _options: unknown, done: () => void): void {\n fastify.addHook('onError', async (request, reply, error) => {\n handleFastifyError.call(handleFastifyError, error, request, reply, 'onError-hook');\n });\n done();\n },\n {\n [Symbol.for('skip-override')]: true,\n [Symbol.for('fastify.display-name')]: 'sentry-fastify-error-handler',\n },\n );\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n fastify.register(plugin);\n}\n\nfunction addFastifySpanAttributes(span: Span): void {\n const spanJSON = spanToJSON(span);\n const spanName = spanJSON.description;\n const attributes = spanJSON.data;\n\n const type = attributes['fastify.type'];\n\n const isHook = type === 'hook';\n const isHandler = type === spanName?.startsWith('handler -');\n // In @fastify/otel `request-handler` is separated by dash, not underscore\n const isRequestHandler = spanName === 'request' || type === 'request-handler';\n\n // If this is already set, or we have no fastify span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || (!isHandler && !isRequestHandler && !isHook)) {\n return;\n }\n\n const opPrefix = isHook ? 'hook' : isHandler ? 'middleware' : isRequestHandler ? 'request-handler' : '<unknown>';\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.fastify',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${opPrefix}.fastify`,\n });\n\n const attrName = attributes['fastify.name'] || attributes['plugin.name'] || attributes['hook.name'];\n if (typeof attrName === 'string') {\n // Try removing `fastify -> ` and `@fastify/otel -> ` prefixes\n // This is a bit of a hack, and not always working for all spans\n // But it's the best we can do without a proper API\n const updatedName = attrName.replace(/^fastify -> /, '').replace(/^@fastify\\/otel -> /, '');\n\n span.updateName(updatedName);\n }\n}\n\nfunction instrumentClient(): void {\n const client = getClient();\n if (client) {\n client.on('spanStart', (span: Span) => {\n addFastifySpanAttributes(span);\n });\n }\n}\n\nfunction instrumentOnRequest(fastify: FastifyInstance): void {\n fastify.addHook('onRequest', async (request: FastifyRequest & { opentelemetry?: () => { span?: Span } }, _reply) => {\n if (request.opentelemetry) {\n const { span } = request.opentelemetry();\n\n if (span) {\n addFastifySpanAttributes(span);\n }\n }\n\n const routeName = request.routeOptions?.url;\n const method = request.method || 'GET';\n\n getIsolationScope().setTransactionName(`${method} ${routeName}`);\n });\n}\n"],"names":["generateInstrumentOnce","FastifyInstrumentationV3","getClient","DEBUG_BUILD","debug","captureException","FastifyOtelInstrumentation","diagnosticsChannel","defineIntegration","spanToJSON","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","getIsolationScope"],"mappings":";;;;;;;;;AAmBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAmDA,MAAM,gBAAA,GAAmB,SAAS;;AAE3B,MAAM,mBAAA,GAAsBA,+BAAsB;AACzD,EAAE,CAAC,EAAA,gBAAA,CAAA,GAAA,CAAA;AACA,EAAA,MAAA,IAAAC,wCAAA,EAAA;AACA;;AAEA,SAAA,qBAAA,GAAA;AACA,EAAA,MAAA,MAAA,GAAAC,cAAA,EAAA;AACA,EAAA,IAAA,CAAA,MAAA,EAAA;AACA,IAAA,OAAA,SAAA;AACA,GAAA,MAAA;AACA,IAAA,OAAA,MAAA,CAAA,oBAAA,CAAA,gBAAA,CAAA;AACA;AACA;;AAEA,SAAA,kBAAA;;AAIA,EAAA,KAAA;AACA,EAAA,OAAA;AACA,EAAA,KAAA;AACA,EAAA,aAAA;AACA,EAAA;AACA,EAAA,MAAA,iBAAA,GAAA,qBAAA,EAAA,EAAA,oBAAA,EAAA,IAAA,wBAAA;AACA;AACA,EAAA,IAAA,aAAA,KAAA,qBAAA,EAAA;AACA,IAAA,IAAA,CAAA,wBAAA,GAAA,IAAA;AACA;;AAEA,EAAA,IAAA,IAAA,CAAA,wBAAA,IAAA,aAAA,KAAA,cAAA,EAAA;AACA,IAAAC,sBAAA;AACA,MAAAC,UAAA,CAAA,IAAA;AACA,QAAA,uEAAA;AACA,QAAA,+GAAA;AACA,OAAA;;AAEA;AACA,IAAA;AACA;;AAEA,EAAA,IAAA,iBAAA,CAAA,KAAA,EAAA,OAAA,EAAA,KAAA,CAAA,EAAA;AACA,IAAAC,qBAAA,CAAA,KAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,uBAAA,EAAA,EAAA,CAAA;AACA;AACA;;AAEA,MAAA,iBAAA,GAAAL,+BAAA,CAAA,CAAA,EAAA,gBAAA,CAAA,GAAA,CAAA,EAAA,MAAA;AACA,EAAA,MAAA,kCAAA,GAAA,IAAAM,gCAAA,EAAA;AACA,EAAA,MAAA,MAAA,GAAA,kCAAA,CAAA,MAAA,EAAA;;AAEA;AACA,EAAAC,EAAA,CAAA,SAAA,CAAA,wBAAA,EAAA,OAAA,IAAA;AACA,IAAA,MAAA,eAAA,GAAA,CAAA,OAAA,GAAA,OAAA;;AAEA,IAAA,eAAA,EAAA,QAAA,CAAA,MAAA,CAAA,CAAA,KAAA,CAAA,GAAA,IAAA;AACA,MAAA,IAAA,GAAA,EAAA;AACA,QAAAJ,sBAAA,IAAAC,UAAA,CAAA,KAAA,CAAA,yCAAA,EAAA,GAAA,CAAA;AACA,OAAA,MAAA;AACA,QAAA,gBAAA,EAAA;;AAEA,QAAA,IAAA,eAAA,EAAA;AACA,UAAA,mBAAA,CAAA,eAAA,CAAA;AACA;AACA;AACA,KAAA,CAAA;AACA,GAAA,CAAA;;AAEA;AACA;AACA,EAAAG,EAAA,CAAA,SAAA,CAAA,uCAAA,EAAA,OAAA,IAAA;AACA,IAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,KAAA,EAAA,GAAA;;AAIA;;AAEA,IAAA,kBAAA,CAAA,IAAA,CAAA,kBAAA,EAAA,KAAA,EAAA,OAAA,EAAA,KAAA,EAAA,qBAAA,CAAA;AACA,GAAA,CAAA;;AAEA;AACA,EAAA,OAAA,kCAAA;AACA,CAAA;;AAEA,MAAA,mBAAA,IAAA,CAAA,EAAA,iBAAA,EAAA,KAAA;AACA,EAAA,IAAA,kBAAA;;AAEA,EAAA,OAAA;AACA,IAAA,IAAA,EAAA,gBAAA;AACA,IAAA,SAAA,GAAA;AACA,MAAA,kBAAA,GAAA,iBAAA,IAAA,wBAAA;;AAEA,MAAA,mBAAA,EAAA;AACA,MAAA,iBAAA,EAAA;AACA,KAAA;AACA,IAAA,oBAAA,GAAA;AACA,MAAA,OAAA,kBAAA;AACA,KAAA;AACA,IAAA,oBAAA,CAAA,EAAA,EAAA;AACA,MAAA,kBAAA,GAAA,EAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,kBAAA,GAAAC,sBAAA,CAAA,CAAA,OAAA,GAAA,EAAA;AACA,EAAA,mBAAA,CAAA,OAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAA,wBAAA,CAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA;AACA,EAAA,MAAA,UAAA,GAAA,KAAA,CAAA,UAAA;AACA;AACA,EAAA,OAAA,UAAA,IAAA,GAAA,IAAA,UAAA,IAAA,GAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,wBAAA,CAAA,OAAA,EAAA,OAAA,EAAA;AACA,EAAA,IAAA,OAAA,EAAA,iBAAA,EAAA;AACA,IAAA,qBAAA,EAAA,EAAA,oBAAA,CAAA,OAAA,CAAA,iBAAA,CAAA;AACA;;AAEA,EAAA,MAAA,MAAA,GAAA,MAAA,CAAA,MAAA;AACA,IAAA,UAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA;AACA,MAAA,OAAA,CAAA,OAAA,CAAA,SAAA,EAAA,OAAA,OAAA,EAAA,KAAA,EAAA,KAAA,KAAA;AACA,QAAA,kBAAA,CAAA,IAAA,CAAA,kBAAA,EAAA,KAAA,EAAA,OAAA,EAAA,KAAA,EAAA,cAAA,CAAA;AACA,OAAA,CAAA;AACA,MAAA,IAAA,EAAA;AACA,KAAA;AACA,IAAA;AACA,MAAA,CAAA,MAAA,CAAA,GAAA,CAAA,eAAA,CAAA,GAAA,IAAA;AACA,MAAA,CAAA,MAAA,CAAA,GAAA,CAAA,sBAAA,CAAA,GAAA,8BAAA;AACA,KAAA;AACA,GAAA;;AAEA;AACA,EAAA,OAAA,CAAA,QAAA,CAAA,MAAA,CAAA;AACA;;AAEA,SAAA,wBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,QAAA,GAAAC,eAAA,CAAA,IAAA,CAAA;AACA,EAAA,MAAA,QAAA,GAAA,QAAA,CAAA,WAAA;AACA,EAAA,MAAA,UAAA,GAAA,QAAA,CAAA,IAAA;;AAEA,EAAA,MAAA,IAAA,GAAA,UAAA,CAAA,cAAA,CAAA;;AAEA,EAAA,MAAA,MAAA,GAAA,IAAA,KAAA,MAAA;AACA,EAAA,MAAA,SAAA,GAAA,IAAA,KAAA,QAAA,EAAA,UAAA,CAAA,WAAA,CAAA;AACA;AACA,EAAA,MAAA,gBAAA,GAAA,QAAA,KAAA,SAAA,IAAA,IAAA,KAAA,iBAAA;;AAEA;AACA,EAAA,IAAA,UAAA,CAAAC,iCAAA,CAAA,KAAA,CAAA,SAAA,IAAA,CAAA,gBAAA,IAAA,CAAA,MAAA,CAAA,EAAA;AACA,IAAA;AACA;;AAEA,EAAA,MAAA,QAAA,GAAA,MAAA,GAAA,MAAA,GAAA,SAAA,GAAA,YAAA,GAAA,gBAAA,GAAA,iBAAA,GAAA,WAAA;;AAEA,EAAA,IAAA,CAAA,aAAA,CAAA;AACA,IAAA,CAAAC,qCAAA,GAAA,wBAAA;AACA,IAAA,CAAAD,iCAAA,GAAA,CAAA,EAAA,QAAA,CAAA,QAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAA,MAAA,QAAA,GAAA,UAAA,CAAA,cAAA,CAAA,IAAA,UAAA,CAAA,aAAA,CAAA,IAAA,UAAA,CAAA,WAAA,CAAA;AACA,EAAA,IAAA,OAAA,QAAA,KAAA,QAAA,EAAA;AACA;AACA;AACA;AACA,IAAA,MAAA,WAAA,GAAA,QAAA,CAAA,OAAA,CAAA,cAAA,EAAA,EAAA,CAAA,CAAA,OAAA,CAAA,qBAAA,EAAA,EAAA,CAAA;;AAEA,IAAA,IAAA,CAAA,UAAA,CAAA,WAAA,CAAA;AACA;AACA;;AAEA,SAAA,gBAAA,GAAA;AACA,EAAA,MAAA,MAAA,GAAAR,cAAA,EAAA;AACA,EAAA,IAAA,MAAA,EAAA;AACA,IAAA,MAAA,CAAA,EAAA,CAAA,WAAA,EAAA,CAAA,IAAA,KAAA;AACA,MAAA,wBAAA,CAAA,IAAA,CAAA;AACA,KAAA,CAAA;AACA;AACA;;AAEA,SAAA,mBAAA,CAAA,OAAA,EAAA;AACA,EAAA,OAAA,CAAA,OAAA,CAAA,WAAA,EAAA,OAAA,OAAA,EAAA,MAAA,KAAA;AACA,IAAA,IAAA,OAAA,CAAA,aAAA,EAAA;AACA,MAAA,MAAA,EAAA,IAAA,EAAA,GAAA,OAAA,CAAA,aAAA,EAAA;;AAEA,MAAA,IAAA,IAAA,EAAA;AACA,QAAA,wBAAA,CAAA,IAAA,CAAA;AACA;AACA;;AAEA,IAAA,MAAA,SAAA,GAAA,OAAA,CAAA,YAAA,EAAA,GAAA;AACA,IAAA,MAAA,MAAA,GAAA,OAAA,CAAA,MAAA,IAAA,KAAA;;AAEA,IAAAU,sBAAA,EAAA,CAAA,kBAAA,CAAA,CAAA,EAAA,MAAA,CAAA,CAAA,EAAA,SAAA,CAAA,CAAA,CAAA;AACA,GAAA,CAAA;AACA;;;;;;;"}
@@ -5,6 +5,9 @@ const api = require('@opentelemetry/api');
5
5
  const instrumentation = require('@opentelemetry/instrumentation');
6
6
  const semanticConventions = require('@opentelemetry/semantic-conventions');
7
7
 
8
+ // Inline minimal types used from `shimmer` to avoid importing shimmer's types directly.
9
+ // We only need the shape for `wrap` and `unwrap` used in this file.
10
+
8
11
  /**
9
12
  *
10
13
  * @param tracer - Opentelemetry Tracer