@sentry/core 10.50.0 → 10.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/client.js +33 -5
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/envelope.js +4 -1
- package/build/cjs/envelope.js.map +1 -1
- package/build/cjs/fetch.js +7 -4
- package/build/cjs/fetch.js.map +1 -1
- package/build/cjs/index.js +37 -13
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrument/console.js +3 -1
- package/build/cjs/instrument/console.js.map +1 -1
- package/build/cjs/instrument/fetch.js +6 -2
- package/build/cjs/instrument/fetch.js.map +1 -1
- package/build/cjs/instrument/handlers.js +11 -1
- package/build/cjs/instrument/handlers.js.map +1 -1
- package/build/cjs/integrations/console.js +3 -1
- package/build/cjs/integrations/console.js.map +1 -1
- package/build/cjs/integrations/express/index.js +2 -4
- package/build/cjs/integrations/express/index.js.map +1 -1
- package/build/cjs/integrations/express/utils.js +0 -7
- package/build/cjs/integrations/express/utils.js.map +1 -1
- package/build/cjs/integrations/extraerrordata.js +2 -2
- package/build/cjs/integrations/extraerrordata.js.map +1 -1
- package/build/cjs/integrations/http/add-outgoing-request-breadcrumb.js +43 -0
- package/build/cjs/integrations/http/add-outgoing-request-breadcrumb.js.map +1 -0
- package/build/cjs/integrations/http/client-patch.js +113 -0
- package/build/cjs/integrations/http/client-patch.js.map +1 -0
- package/build/cjs/integrations/http/client-subscriptions.js +166 -0
- package/build/cjs/integrations/http/client-subscriptions.js.map +1 -0
- package/build/cjs/integrations/http/constants.js +10 -0
- package/build/cjs/integrations/http/constants.js.map +1 -0
- package/build/cjs/integrations/http/double-wrap-warning.js +29 -0
- package/build/cjs/integrations/http/double-wrap-warning.js.map +1 -0
- package/build/cjs/integrations/http/get-outgoing-span-data.js +88 -0
- package/build/cjs/integrations/http/get-outgoing-span-data.js.map +1 -0
- package/build/cjs/integrations/http/get-request-url.js +54 -0
- package/build/cjs/integrations/http/get-request-url.js.map +1 -0
- package/build/cjs/integrations/http/inject-trace-propagation-headers.js +81 -0
- package/build/cjs/integrations/http/inject-trace-propagation-headers.js.map +1 -0
- package/build/cjs/integrations/postgresjs.js +10 -1
- package/build/cjs/integrations/postgresjs.js.map +1 -1
- package/build/cjs/integrations/requestdata.js +92 -6
- package/build/cjs/integrations/requestdata.js.map +1 -1
- package/build/cjs/integrations/supabase.js +39 -12
- package/build/cjs/integrations/supabase.js.map +1 -1
- package/build/cjs/logs/console-integration.js +3 -1
- package/build/cjs/logs/console-integration.js.map +1 -1
- package/build/cjs/logs/envelope.js +12 -2
- package/build/cjs/logs/envelope.js.map +1 -1
- package/build/cjs/logs/internal.js +7 -1
- package/build/cjs/logs/internal.js.map +1 -1
- package/build/cjs/metrics/envelope.js +15 -2
- package/build/cjs/metrics/envelope.js.map +1 -1
- package/build/cjs/metrics/internal.js +7 -1
- package/build/cjs/metrics/internal.js.map +1 -1
- package/build/cjs/server-runtime-client.js +20 -2
- package/build/cjs/server-runtime-client.js.map +1 -1
- package/build/cjs/tracing/ai/gen-ai-attributes.js +6 -0
- package/build/cjs/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/cjs/tracing/idleSpan.js +7 -1
- package/build/cjs/tracing/idleSpan.js.map +1 -1
- package/build/cjs/tracing/langchain/index.js +43 -8
- package/build/cjs/tracing/langchain/index.js.map +1 -1
- package/build/cjs/tracing/langchain/utils.js +44 -10
- package/build/cjs/tracing/langchain/utils.js.map +1 -1
- package/build/cjs/tracing/langgraph/index.js +105 -2
- package/build/cjs/tracing/langgraph/index.js.map +1 -1
- package/build/cjs/tracing/langgraph/utils.js +168 -0
- package/build/cjs/tracing/langgraph/utils.js.map +1 -1
- package/build/cjs/tracing/spans/captureSpan.js +169 -9
- package/build/cjs/tracing/spans/captureSpan.js.map +1 -1
- package/build/cjs/tracing/spans/envelope.js +13 -3
- package/build/cjs/tracing/spans/envelope.js.map +1 -1
- package/build/cjs/tracing/trace.js +2 -0
- package/build/cjs/tracing/trace.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/constants.js +8 -0
- package/build/cjs/tracing/vercel-ai/constants.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/index.js +93 -14
- package/build/cjs/tracing/vercel-ai/index.js.map +1 -1
- package/build/cjs/trpc.js +2 -3
- package/build/cjs/trpc.js.map +1 -1
- package/build/cjs/utils/baggage.js +73 -0
- package/build/cjs/utils/baggage.js.map +1 -1
- package/build/cjs/utils/chain-and-copy-promiselike.js +1 -0
- package/build/cjs/utils/chain-and-copy-promiselike.js.map +1 -1
- package/build/cjs/utils/get-default-export.js +32 -0
- package/build/cjs/utils/get-default-export.js.map +1 -0
- package/build/cjs/utils/isSentryRequestUrl.js +9 -1
- package/build/cjs/utils/isSentryRequestUrl.js.map +1 -1
- package/build/cjs/utils/normalizationHints.js +38 -0
- package/build/cjs/utils/normalizationHints.js.map +1 -0
- package/build/cjs/utils/normalize.js +7 -11
- package/build/cjs/utils/normalize.js.map +1 -1
- package/build/cjs/utils/object.js +1 -1
- package/build/cjs/utils/object.js.map +1 -1
- package/build/cjs/utils/request.js +192 -12
- package/build/cjs/utils/request.js.map +1 -1
- package/build/cjs/utils/should-ignore-span.js +27 -8
- package/build/cjs/utils/should-ignore-span.js.map +1 -1
- package/build/cjs/utils/spanUtils.js +1 -1
- package/build/cjs/utils/spanUtils.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/esm/client.js +33 -5
- package/build/esm/client.js.map +1 -1
- package/build/esm/envelope.js +4 -1
- package/build/esm/envelope.js.map +1 -1
- package/build/esm/fetch.js +7 -4
- package/build/esm/fetch.js.map +1 -1
- package/build/esm/index.js +11 -5
- package/build/esm/index.js.map +1 -1
- package/build/esm/instrument/console.js +3 -1
- package/build/esm/instrument/console.js.map +1 -1
- package/build/esm/instrument/fetch.js +6 -2
- package/build/esm/instrument/fetch.js.map +1 -1
- package/build/esm/instrument/handlers.js +11 -1
- package/build/esm/instrument/handlers.js.map +1 -1
- package/build/esm/integrations/console.js +3 -1
- package/build/esm/integrations/console.js.map +1 -1
- package/build/esm/integrations/express/index.js +3 -5
- package/build/esm/integrations/express/index.js.map +1 -1
- package/build/esm/integrations/express/utils.js +1 -7
- package/build/esm/integrations/express/utils.js.map +1 -1
- package/build/esm/integrations/extraerrordata.js +2 -2
- package/build/esm/integrations/extraerrordata.js.map +1 -1
- package/build/esm/integrations/http/add-outgoing-request-breadcrumb.js +41 -0
- package/build/esm/integrations/http/add-outgoing-request-breadcrumb.js.map +1 -0
- package/build/esm/integrations/http/client-patch.js +111 -0
- package/build/esm/integrations/http/client-patch.js.map +1 -0
- package/build/esm/integrations/http/client-subscriptions.js +164 -0
- package/build/esm/integrations/http/client-subscriptions.js.map +1 -0
- package/build/esm/integrations/http/constants.js +6 -0
- package/build/esm/integrations/http/constants.js.map +1 -0
- package/build/esm/integrations/http/double-wrap-warning.js +26 -0
- package/build/esm/integrations/http/double-wrap-warning.js.map +1 -0
- package/build/esm/integrations/http/get-outgoing-span-data.js +85 -0
- package/build/esm/integrations/http/get-outgoing-span-data.js.map +1 -0
- package/build/esm/integrations/http/get-request-url.js +49 -0
- package/build/esm/integrations/http/get-request-url.js.map +1 -0
- package/build/esm/integrations/http/inject-trace-propagation-headers.js +79 -0
- package/build/esm/integrations/http/inject-trace-propagation-headers.js.map +1 -0
- package/build/esm/integrations/postgresjs.js +10 -1
- package/build/esm/integrations/postgresjs.js.map +1 -1
- package/build/esm/integrations/requestdata.js +92 -6
- package/build/esm/integrations/requestdata.js.map +1 -1
- package/build/esm/integrations/supabase.js +39 -12
- package/build/esm/integrations/supabase.js.map +1 -1
- package/build/esm/logs/console-integration.js +3 -1
- package/build/esm/logs/console-integration.js.map +1 -1
- package/build/esm/logs/envelope.js +12 -2
- package/build/esm/logs/envelope.js.map +1 -1
- package/build/esm/logs/internal.js +7 -1
- package/build/esm/logs/internal.js.map +1 -1
- package/build/esm/metrics/envelope.js +15 -2
- package/build/esm/metrics/envelope.js.map +1 -1
- package/build/esm/metrics/internal.js +7 -1
- package/build/esm/metrics/internal.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server-runtime-client.js +20 -2
- package/build/esm/server-runtime-client.js.map +1 -1
- package/build/esm/tracing/ai/gen-ai-attributes.js +6 -1
- package/build/esm/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/esm/tracing/idleSpan.js +7 -1
- package/build/esm/tracing/idleSpan.js.map +1 -1
- package/build/esm/tracing/langchain/index.js +45 -10
- package/build/esm/tracing/langchain/index.js.map +1 -1
- package/build/esm/tracing/langchain/utils.js +44 -12
- package/build/esm/tracing/langchain/utils.js.map +1 -1
- package/build/esm/tracing/langgraph/index.js +107 -5
- package/build/esm/tracing/langgraph/index.js.map +1 -1
- package/build/esm/tracing/langgraph/utils.js +166 -2
- package/build/esm/tracing/langgraph/utils.js.map +1 -1
- package/build/esm/tracing/spans/captureSpan.js +170 -11
- package/build/esm/tracing/spans/captureSpan.js.map +1 -1
- package/build/esm/tracing/spans/envelope.js +13 -3
- package/build/esm/tracing/spans/envelope.js.map +1 -1
- package/build/esm/tracing/trace.js +2 -1
- package/build/esm/tracing/trace.js.map +1 -1
- package/build/esm/tracing/vercel-ai/constants.js +8 -1
- package/build/esm/tracing/vercel-ai/constants.js.map +1 -1
- package/build/esm/tracing/vercel-ai/index.js +95 -17
- package/build/esm/tracing/vercel-ai/index.js.map +1 -1
- package/build/esm/trpc.js +2 -3
- package/build/esm/trpc.js.map +1 -1
- package/build/esm/utils/baggage.js +73 -1
- package/build/esm/utils/baggage.js.map +1 -1
- package/build/esm/utils/chain-and-copy-promiselike.js +1 -0
- package/build/esm/utils/chain-and-copy-promiselike.js.map +1 -1
- package/build/esm/utils/get-default-export.js +30 -0
- package/build/esm/utils/get-default-export.js.map +1 -0
- package/build/esm/utils/isSentryRequestUrl.js +9 -1
- package/build/esm/utils/isSentryRequestUrl.js.map +1 -1
- package/build/esm/utils/normalizationHints.js +33 -0
- package/build/esm/utils/normalizationHints.js.map +1 -0
- package/build/esm/utils/normalize.js +7 -11
- package/build/esm/utils/normalize.js.map +1 -1
- package/build/esm/utils/object.js +1 -1
- package/build/esm/utils/object.js.map +1 -1
- package/build/esm/utils/request.js +190 -13
- package/build/esm/utils/request.js.map +1 -1
- package/build/esm/utils/should-ignore-span.js +27 -8
- package/build/esm/utils/should-ignore-span.js.map +1 -1
- package/build/esm/utils/spanUtils.js +1 -1
- package/build/esm/utils/spanUtils.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/types/client.d.ts +12 -1
- package/build/types/client.d.ts.map +1 -1
- package/build/types/envelope.d.ts.map +1 -1
- package/build/types/fetch.d.ts.map +1 -1
- package/build/types/index.d.ts +17 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrument/console.d.ts +2 -1
- package/build/types/instrument/console.d.ts.map +1 -1
- package/build/types/instrument/fetch.d.ts +4 -2
- package/build/types/instrument/fetch.d.ts.map +1 -1
- package/build/types/instrument/handlers.d.ts +2 -2
- package/build/types/instrument/handlers.d.ts.map +1 -1
- package/build/types/integrations/console.d.ts.map +1 -1
- package/build/types/integrations/express/index.d.ts.map +1 -1
- package/build/types/integrations/express/utils.d.ts +1 -5
- package/build/types/integrations/express/utils.d.ts.map +1 -1
- package/build/types/integrations/http/add-outgoing-request-breadcrumb.d.ts +6 -0
- package/build/types/integrations/http/add-outgoing-request-breadcrumb.d.ts.map +1 -0
- package/build/types/integrations/http/client-patch.d.ts +46 -0
- package/build/types/integrations/http/client-patch.d.ts.map +1 -0
- package/build/types/integrations/http/client-subscriptions.d.ts +21 -0
- package/build/types/integrations/http/client-subscriptions.d.ts.map +1 -0
- package/build/types/integrations/http/constants.d.ts +6 -0
- package/build/types/integrations/http/constants.d.ts.map +1 -0
- package/build/types/integrations/http/double-wrap-warning.d.ts +4 -0
- package/build/types/integrations/http/double-wrap-warning.d.ts.map +1 -0
- package/build/types/integrations/http/get-outgoing-span-data.d.ts +13 -0
- package/build/types/integrations/http/get-outgoing-span-data.d.ts.map +1 -0
- package/build/types/integrations/http/get-request-url.d.ts +10 -0
- package/build/types/integrations/http/get-request-url.d.ts.map +1 -0
- package/build/types/integrations/http/index.d.ts +4 -0
- package/build/types/integrations/http/index.d.ts.map +1 -0
- package/build/types/integrations/http/inject-trace-propagation-headers.d.ts +12 -0
- package/build/types/integrations/http/inject-trace-propagation-headers.d.ts.map +1 -0
- package/build/types/integrations/http/types.d.ts +249 -0
- package/build/types/integrations/http/types.d.ts.map +1 -0
- package/build/types/integrations/postgresjs.d.ts.map +1 -1
- package/build/types/integrations/requestdata.d.ts.map +1 -1
- package/build/types/integrations/supabase.d.ts.map +1 -1
- package/build/types/logs/console-integration.d.ts.map +1 -1
- package/build/types/logs/envelope.d.ts +5 -2
- package/build/types/logs/envelope.d.ts.map +1 -1
- package/build/types/logs/internal.d.ts.map +1 -1
- package/build/types/metrics/envelope.d.ts +5 -2
- package/build/types/metrics/envelope.d.ts.map +1 -1
- package/build/types/metrics/internal.d.ts.map +1 -1
- package/build/types/server-runtime-client.d.ts +5 -0
- package/build/types/server-runtime-client.d.ts.map +1 -1
- package/build/types/tracing/idleSpan.d.ts.map +1 -1
- package/build/types/tracing/index.d.ts +1 -1
- package/build/types/tracing/index.d.ts.map +1 -1
- package/build/types/tracing/langchain/index.d.ts.map +1 -1
- package/build/types/tracing/langchain/types.d.ts +8 -0
- package/build/types/tracing/langchain/types.d.ts.map +1 -1
- package/build/types/tracing/langchain/utils.d.ts +2 -0
- package/build/types/tracing/langchain/utils.d.ts.map +1 -1
- package/build/types/tracing/langgraph/index.d.ts +4 -0
- package/build/types/tracing/langgraph/index.d.ts.map +1 -1
- package/build/types/tracing/langgraph/utils.d.ts +18 -2
- package/build/types/tracing/langgraph/utils.d.ts.map +1 -1
- package/build/types/tracing/spans/captureSpan.d.ts +13 -3
- package/build/types/tracing/spans/captureSpan.d.ts.map +1 -1
- package/build/types/tracing/spans/envelope.d.ts.map +1 -1
- package/build/types/tracing/trace.d.ts +1 -0
- package/build/types/tracing/trace.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/constants.d.ts +1 -0
- package/build/types/tracing/vercel-ai/constants.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/index.d.ts +9 -0
- package/build/types/tracing/vercel-ai/index.d.ts.map +1 -1
- package/build/types/trpc.d.ts.map +1 -1
- package/build/types/types-hoist/feedback/config.d.ts +20 -0
- package/build/types/types-hoist/feedback/config.d.ts.map +1 -1
- package/build/types/types-hoist/feedback/index.d.ts +2 -2
- package/build/types/types-hoist/feedback/index.d.ts.map +1 -1
- package/build/types/types-hoist/feedback/sendFeedback.d.ts +3 -0
- package/build/types/types-hoist/feedback/sendFeedback.d.ts.map +1 -1
- package/build/types/types-hoist/log.d.ts +5 -0
- package/build/types/types-hoist/log.d.ts.map +1 -1
- package/build/types/types-hoist/metric.d.ts +5 -0
- package/build/types/types-hoist/metric.d.ts.map +1 -1
- package/build/types/types-hoist/options.d.ts +37 -2
- package/build/types/types-hoist/options.d.ts.map +1 -1
- package/build/types/types-hoist/span.d.ts +5 -0
- package/build/types/types-hoist/span.d.ts.map +1 -1
- package/build/types/types-hoist/webfetchapi.d.ts +2 -0
- package/build/types/types-hoist/webfetchapi.d.ts.map +1 -1
- package/build/types/utils/baggage.d.ts +13 -0
- package/build/types/utils/baggage.d.ts.map +1 -1
- package/build/types/utils/get-default-export.d.ts +22 -0
- package/build/types/utils/get-default-export.d.ts.map +1 -0
- package/build/types/utils/normalizationHints.d.ts +9 -0
- package/build/types/utils/normalizationHints.d.ts.map +1 -0
- package/build/types/utils/normalize.d.ts.map +1 -1
- package/build/types/utils/object.d.ts +1 -1
- package/build/types/utils/object.d.ts.map +1 -1
- package/build/types/utils/request.d.ts +30 -0
- package/build/types/utils/request.d.ts.map +1 -1
- package/build/types/utils/should-ignore-span.d.ts +3 -1
- package/build/types/utils/should-ignore-span.d.ts.map +1 -1
- package/build/types/utils/spanUtils.d.ts +1 -1
- package/build/types-ts3.8/client.d.ts +12 -1
- package/build/types-ts3.8/index.d.ts +17 -6
- package/build/types-ts3.8/instrument/console.d.ts +2 -1
- package/build/types-ts3.8/instrument/fetch.d.ts +4 -2
- package/build/types-ts3.8/instrument/handlers.d.ts +2 -2
- package/build/types-ts3.8/integrations/express/utils.d.ts +1 -5
- package/build/types-ts3.8/integrations/http/add-outgoing-request-breadcrumb.d.ts +6 -0
- package/build/types-ts3.8/integrations/http/client-patch.d.ts +46 -0
- package/build/types-ts3.8/integrations/http/client-subscriptions.d.ts +21 -0
- package/build/types-ts3.8/integrations/http/constants.d.ts +6 -0
- package/build/types-ts3.8/integrations/http/double-wrap-warning.d.ts +4 -0
- package/build/types-ts3.8/integrations/http/get-outgoing-span-data.d.ts +13 -0
- package/build/types-ts3.8/integrations/http/get-request-url.d.ts +10 -0
- package/build/types-ts3.8/integrations/http/index.d.ts +4 -0
- package/build/types-ts3.8/integrations/http/inject-trace-propagation-headers.d.ts +12 -0
- package/build/types-ts3.8/integrations/http/types.d.ts +252 -0
- package/build/types-ts3.8/logs/envelope.d.ts +5 -2
- package/build/types-ts3.8/metrics/envelope.d.ts +5 -2
- package/build/types-ts3.8/server-runtime-client.d.ts +5 -0
- package/build/types-ts3.8/tracing/index.d.ts +1 -1
- package/build/types-ts3.8/tracing/langchain/types.d.ts +8 -0
- package/build/types-ts3.8/tracing/langchain/utils.d.ts +2 -0
- package/build/types-ts3.8/tracing/langgraph/index.d.ts +4 -0
- package/build/types-ts3.8/tracing/langgraph/utils.d.ts +18 -2
- package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +13 -3
- package/build/types-ts3.8/tracing/trace.d.ts +1 -0
- package/build/types-ts3.8/tracing/vercel-ai/constants.d.ts +1 -0
- package/build/types-ts3.8/tracing/vercel-ai/index.d.ts +9 -0
- package/build/types-ts3.8/types-hoist/feedback/config.d.ts +20 -0
- package/build/types-ts3.8/types-hoist/feedback/index.d.ts +2 -2
- package/build/types-ts3.8/types-hoist/feedback/sendFeedback.d.ts +3 -0
- package/build/types-ts3.8/types-hoist/log.d.ts +5 -0
- package/build/types-ts3.8/types-hoist/metric.d.ts +5 -0
- package/build/types-ts3.8/types-hoist/options.d.ts +37 -2
- package/build/types-ts3.8/types-hoist/span.d.ts +5 -0
- package/build/types-ts3.8/types-hoist/webfetchapi.d.ts +2 -0
- package/build/types-ts3.8/utils/baggage.d.ts +13 -0
- package/build/types-ts3.8/utils/get-default-export.d.ts +22 -0
- package/build/types-ts3.8/utils/normalizationHints.d.ts +9 -0
- package/build/types-ts3.8/utils/object.d.ts +1 -1
- package/build/types-ts3.8/utils/request.d.ts +30 -0
- package/build/types-ts3.8/utils/should-ignore-span.d.ts +3 -1
- package/build/types-ts3.8/utils/spanUtils.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/integrations/express/index.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { debug } from '../../utils/debug-logger';\nimport { captureException } from '../../exports';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type {\n ExpressApplication,\n ExpressErrorMiddleware,\n ExpressExport,\n ExpressHandlerOptions,\n ExpressIntegrationOptions,\n ExpressLayer,\n ExpressMiddleware,\n ExpressModuleExport,\n ExpressRequest,\n ExpressResponse,\n ExpressRouter,\n ExpressRouterv4,\n ExpressRouterv5,\n MiddlewareError,\n} from './types';\nimport {\n defaultShouldHandleError,\n getLayerPath,\n hasDefaultProp,\n isExpressWithoutRouterPrototype,\n isExpressWithRouterPrototype,\n} from './utils';\nimport { wrapMethod } from '../../utils/object';\nimport { patchLayer } from './patch-layer';\nimport { setSDKProcessingMetadata } from './set-sdk-processing-metadata';\n\nconst getExpressExport = (express: ExpressModuleExport): ExpressExport =>\n hasDefaultProp(express) ? express.default : (express as ExpressExport);\n\nfunction isLegacyOptions(\n options: ExpressModuleExport | (ExpressIntegrationOptions & { express: ExpressModuleExport }),\n): options is ExpressIntegrationOptions & { express: ExpressModuleExport } {\n return !!(options as { express: ExpressModuleExport }).express;\n}\n\n// TODO: remove this deprecation handling in v11\nlet didLegacyDeprecationWarning = false;\nfunction deprecationWarning() {\n if (!didLegacyDeprecationWarning) {\n didLegacyDeprecationWarning = true;\n DEBUG_BUILD &&\n debug.warn(\n '[Express] `patchExpressModule(options)` is deprecated. Use `patchExpressModule(moduleExports, getOptions)` instead.',\n );\n }\n}\n\n/**\n * This is a portable instrumentatiton function that works in any environment\n * where Express can be loaded, without depending on OpenTelemetry.\n *\n * @example\n * ```javascript\n * import express from 'express';\n * import * as Sentry from '@sentry/deno'; // or any SDK that extends core\n *\n * Sentry.patchExpressModule(express, () => ({}));\n * ```\n */\nexport function patchExpressModule(\n moduleExports: ExpressModuleExport,\n getOptions: () => ExpressIntegrationOptions,\n): ExpressModuleExport;\n/**\n * @deprecated Pass the Express module export as the first argument and options getter as the second argument.\n */\nexport function patchExpressModule(\n options: ExpressIntegrationOptions & { express: ExpressModuleExport },\n): ExpressModuleExport;\nexport function patchExpressModule(\n optionsOrExports: ExpressModuleExport | (ExpressIntegrationOptions & { express: ExpressModuleExport }),\n maybeGetOptions?: () => ExpressIntegrationOptions,\n): ExpressModuleExport {\n let getOptions: () => ExpressIntegrationOptions;\n let moduleExports: ExpressModuleExport;\n if (!maybeGetOptions && isLegacyOptions(optionsOrExports)) {\n const { express, ...options } = optionsOrExports;\n moduleExports = express;\n getOptions = () => options;\n deprecationWarning();\n } else if (typeof maybeGetOptions !== 'function') {\n throw new TypeError('`patchExpressModule(moduleExports, getOptions)` requires a `getOptions` callback');\n } else {\n getOptions = maybeGetOptions;\n moduleExports = optionsOrExports as ExpressModuleExport;\n }\n\n // pass in the require() or import() result of express\n const express = getExpressExport(moduleExports);\n const routerProto: ExpressRouterv4 | ExpressRouterv5 | undefined = isExpressWithRouterPrototype(express)\n ? express.Router.prototype // Express v5\n : isExpressWithoutRouterPrototype(express)\n ? express.Router // Express v4\n : undefined;\n\n if (!routerProto) {\n throw new TypeError('no valid Express route function to instrument');\n }\n\n // oxlint-disable-next-line @typescript-eslint/unbound-method\n const originalRouteMethod = routerProto.route;\n try {\n wrapMethod(\n routerProto,\n 'route',\n function routeTrace(this: ExpressRouter, ...args: Parameters<typeof originalRouteMethod>[]) {\n const route = originalRouteMethod.apply(this, args);\n const layer = this.stack[this.stack.length - 1] as ExpressLayer;\n patchLayer(getOptions, layer, getLayerPath(args));\n return route;\n },\n );\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch express route method:', e);\n }\n\n // oxlint-disable-next-line @typescript-eslint/unbound-method\n const originalRouterUse = routerProto.use;\n try {\n wrapMethod(\n routerProto,\n 'use',\n function useTrace(this: ExpressApplication, ...args: Parameters<typeof originalRouterUse>) {\n const route = originalRouterUse.apply(this, args);\n const layer = this.stack[this.stack.length - 1];\n if (!layer) {\n return route;\n }\n patchLayer(getOptions, layer, getLayerPath(args));\n return route;\n },\n );\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch express use method:', e);\n }\n\n const { application } = express;\n const originalApplicationUse = application.use;\n try {\n wrapMethod(\n application,\n 'use',\n function appUseTrace(\n this: ExpressApplication & {\n _router?: ExpressRouter;\n router?: ExpressRouter;\n },\n ...args: Parameters<ExpressApplication['use']>\n ) {\n // If we access app.router in express 4.x we trigger an assertion error.\n // This property existed in v3, was removed in v4 and then re-added in v5.\n const route = originalApplicationUse.apply(this, args);\n const router = isExpressWithRouterPrototype(express) ? this.router : this._router;\n if (router) {\n const layer = router.stack[router.stack.length - 1];\n if (layer) {\n patchLayer(getOptions, layer, getLayerPath(args));\n }\n }\n return route;\n },\n );\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch express application.use method:', e);\n }\n\n return express;\n}\n\n/**\n * An Express-compatible error handler, used by setupExpressErrorHandler\n */\nexport function expressErrorHandler(options?: ExpressHandlerOptions): ExpressErrorMiddleware {\n return function sentryErrorMiddleware(\n error: MiddlewareError,\n request: ExpressRequest,\n res: ExpressResponse,\n next: (error: MiddlewareError) => void,\n ): void {\n // When an error happens, the `expressRequestHandler` middleware does not run, so we set it here too\n setSDKProcessingMetadata(request);\n const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError;\n\n if (shouldHandleError(error)) {\n const eventId = captureException(error, {\n mechanism: { type: 'auto.middleware.express', handled: false },\n });\n (res as { sentry?: string }).sentry = eventId;\n }\n\n next(error);\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 * import * as Sentry from 'sentry/deno'; // or any other @sentry/<platform>\n * import * as express from 'express';\n *\n * Sentry.instrumentExpress(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: {\n //oxlint-disable-next-line no-explicit-any\n use: (middleware: any) => unknown;\n },\n options?: ExpressHandlerOptions,\n): void {\n app.use(expressRequestHandler());\n app.use(expressErrorHandler(options));\n}\n\nfunction expressRequestHandler(): ExpressMiddleware {\n return function sentryRequestMiddleware(request: ExpressRequest, _res: ExpressResponse, next: () => void): void {\n setSDKProcessingMetadata(request);\n next();\n };\n}\n"],"names":["hasDefaultProp","DEBUG_BUILD","debug","isExpressWithRouterPrototype","isExpressWithoutRouterPrototype","wrapMethod","patchLayer","getLayerPath","setSDKProcessingMetadata","defaultShouldHandleError","captureException"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/integrations/express/index.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { debug } from '../../utils/debug-logger';\nimport { captureException } from '../../exports';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type {\n ExpressApplication,\n ExpressErrorMiddleware,\n ExpressHandlerOptions,\n ExpressIntegrationOptions,\n ExpressLayer,\n ExpressMiddleware,\n ExpressModuleExport,\n ExpressRequest,\n ExpressResponse,\n ExpressRouter,\n ExpressRouterv4,\n ExpressRouterv5,\n MiddlewareError,\n} from './types';\nimport {\n defaultShouldHandleError,\n getLayerPath,\n isExpressWithoutRouterPrototype,\n isExpressWithRouterPrototype,\n} from './utils';\nimport { wrapMethod } from '../../utils/object';\nimport { patchLayer } from './patch-layer';\nimport { setSDKProcessingMetadata } from './set-sdk-processing-metadata';\nimport { getDefaultExport } from '../../utils/get-default-export';\n\nfunction isLegacyOptions(\n options: ExpressModuleExport | (ExpressIntegrationOptions & { express: ExpressModuleExport }),\n): options is ExpressIntegrationOptions & { express: ExpressModuleExport } {\n return !!(options as { express: ExpressModuleExport }).express;\n}\n\n// TODO: remove this deprecation handling in v11\nlet didLegacyDeprecationWarning = false;\nfunction deprecationWarning() {\n if (!didLegacyDeprecationWarning) {\n didLegacyDeprecationWarning = true;\n DEBUG_BUILD &&\n debug.warn(\n '[Express] `patchExpressModule(options)` is deprecated. Use `patchExpressModule(moduleExports, getOptions)` instead.',\n );\n }\n}\n\n/**\n * This is a portable instrumentatiton function that works in any environment\n * where Express can be loaded, without depending on OpenTelemetry.\n *\n * @example\n * ```javascript\n * import express from 'express';\n * import * as Sentry from '@sentry/deno'; // or any SDK that extends core\n *\n * Sentry.patchExpressModule(express, () => ({}));\n * ```\n */\nexport function patchExpressModule(\n moduleExports: ExpressModuleExport,\n getOptions: () => ExpressIntegrationOptions,\n): ExpressModuleExport;\n/**\n * @deprecated Pass the Express module export as the first argument and options getter as the second argument.\n */\nexport function patchExpressModule(\n options: ExpressIntegrationOptions & { express: ExpressModuleExport },\n): ExpressModuleExport;\nexport function patchExpressModule(\n optionsOrExports: ExpressModuleExport | (ExpressIntegrationOptions & { express: ExpressModuleExport }),\n maybeGetOptions?: () => ExpressIntegrationOptions,\n): ExpressModuleExport {\n let getOptions: () => ExpressIntegrationOptions;\n let moduleExports: ExpressModuleExport;\n if (!maybeGetOptions && isLegacyOptions(optionsOrExports)) {\n const { express, ...options } = optionsOrExports;\n moduleExports = express;\n getOptions = () => options;\n deprecationWarning();\n } else if (typeof maybeGetOptions !== 'function') {\n throw new TypeError('`patchExpressModule(moduleExports, getOptions)` requires a `getOptions` callback');\n } else {\n getOptions = maybeGetOptions;\n moduleExports = optionsOrExports as ExpressModuleExport;\n }\n\n // pass in the require() or import() result of express\n const express = getDefaultExport(moduleExports);\n const routerProto: ExpressRouterv4 | ExpressRouterv5 | undefined = isExpressWithRouterPrototype(express)\n ? express.Router.prototype // Express v5\n : isExpressWithoutRouterPrototype(express)\n ? express.Router // Express v4\n : undefined;\n\n if (!routerProto) {\n throw new TypeError('no valid Express route function to instrument');\n }\n\n // oxlint-disable-next-line @typescript-eslint/unbound-method\n const originalRouteMethod = routerProto.route;\n try {\n wrapMethod(\n routerProto,\n 'route',\n function routeTrace(this: ExpressRouter, ...args: Parameters<typeof originalRouteMethod>[]) {\n const route = originalRouteMethod.apply(this, args);\n const layer = this.stack[this.stack.length - 1] as ExpressLayer;\n patchLayer(getOptions, layer, getLayerPath(args));\n return route;\n },\n );\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch express route method:', e);\n }\n\n // oxlint-disable-next-line @typescript-eslint/unbound-method\n const originalRouterUse = routerProto.use;\n try {\n wrapMethod(\n routerProto,\n 'use',\n function useTrace(this: ExpressApplication, ...args: Parameters<typeof originalRouterUse>) {\n const route = originalRouterUse.apply(this, args);\n const layer = this.stack[this.stack.length - 1];\n if (!layer) {\n return route;\n }\n patchLayer(getOptions, layer, getLayerPath(args));\n return route;\n },\n );\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch express use method:', e);\n }\n\n const { application } = express;\n const originalApplicationUse = application.use;\n try {\n wrapMethod(\n application,\n 'use',\n function appUseTrace(\n this: ExpressApplication & {\n _router?: ExpressRouter;\n router?: ExpressRouter;\n },\n ...args: Parameters<ExpressApplication['use']>\n ) {\n // If we access app.router in express 4.x we trigger an assertion error.\n // This property existed in v3, was removed in v4 and then re-added in v5.\n const route = originalApplicationUse.apply(this, args);\n const router = isExpressWithRouterPrototype(express) ? this.router : this._router;\n if (router) {\n const layer = router.stack[router.stack.length - 1];\n if (layer) {\n patchLayer(getOptions, layer, getLayerPath(args));\n }\n }\n return route;\n },\n );\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch express application.use method:', e);\n }\n\n return express;\n}\n\n/**\n * An Express-compatible error handler, used by setupExpressErrorHandler\n */\nexport function expressErrorHandler(options?: ExpressHandlerOptions): ExpressErrorMiddleware {\n return function sentryErrorMiddleware(\n error: MiddlewareError,\n request: ExpressRequest,\n res: ExpressResponse,\n next: (error: MiddlewareError) => void,\n ): void {\n // When an error happens, the `expressRequestHandler` middleware does not run, so we set it here too\n setSDKProcessingMetadata(request);\n const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError;\n\n if (shouldHandleError(error)) {\n const eventId = captureException(error, {\n mechanism: { type: 'auto.middleware.express', handled: false },\n });\n (res as { sentry?: string }).sentry = eventId;\n }\n\n next(error);\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 * import * as Sentry from 'sentry/deno'; // or any other @sentry/<platform>\n * import * as express from 'express';\n *\n * Sentry.instrumentExpress(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: {\n //oxlint-disable-next-line no-explicit-any\n use: (middleware: any) => unknown;\n },\n options?: ExpressHandlerOptions,\n): void {\n app.use(expressRequestHandler());\n app.use(expressErrorHandler(options));\n}\n\nfunction expressRequestHandler(): ExpressMiddleware {\n return function sentryRequestMiddleware(request: ExpressRequest, _res: ExpressResponse, next: () => void): void {\n setSDKProcessingMetadata(request);\n next();\n };\n}\n"],"names":["DEBUG_BUILD","debug","getDefaultExport","isExpressWithRouterPrototype","isExpressWithoutRouterPrototype","wrapMethod","patchLayer","getLayerPath","setSDKProcessingMetadata","defaultShouldHandleError","captureException"],"mappings":"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"}
|
|
@@ -206,12 +206,6 @@ const isExpressRouterPrototype = (routerProto) =>
|
|
|
206
206
|
const isExpressWithoutRouterPrototype = (express) =>
|
|
207
207
|
isExpressRouterPrototype((express ).Router) && !isExpressWithRouterPrototype(express);
|
|
208
208
|
|
|
209
|
-
// dynamic puts the default on .default, require or normal import are fine
|
|
210
|
-
const hasDefaultProp = (
|
|
211
|
-
express,
|
|
212
|
-
|
|
213
|
-
) => !!express && typeof express === 'object' && 'default' in express && typeof express.default === 'function';
|
|
214
|
-
|
|
215
209
|
function getStatusCodeFromResponse(error) {
|
|
216
210
|
const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;
|
|
217
211
|
return statusCode ? parseInt(statusCode , 10) : 500;
|
|
@@ -230,7 +224,6 @@ exports.getConstructedRoute = getConstructedRoute;
|
|
|
230
224
|
exports.getLayerMetadata = getLayerMetadata;
|
|
231
225
|
exports.getLayerPath = getLayerPath;
|
|
232
226
|
exports.getRouterPath = getRouterPath;
|
|
233
|
-
exports.hasDefaultProp = hasDefaultProp;
|
|
234
227
|
exports.isExpressWithRouterPrototype = isExpressWithRouterPrototype;
|
|
235
228
|
exports.isExpressWithoutRouterPrototype = isExpressWithoutRouterPrototype;
|
|
236
229
|
exports.isLayerIgnored = isLayerIgnored;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../src/integrations/express/utils.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { SpanAttributes } from '../../types-hoist/span';\nimport { getStoredLayers } from './request-layer-store';\nimport type {\n ExpressExport,\n ExpressIntegrationOptions,\n ExpressLayer,\n ExpressLayerType,\n ExpressRequest,\n LayerPathSegment,\n MiddlewareError,\n ExpressRouterv4,\n ExpressExportv5,\n ExpressExportv4,\n} from './types';\nimport {\n ATTR_EXPRESS_NAME,\n ATTR_EXPRESS_TYPE,\n ExpressLayerType_MIDDLEWARE,\n ExpressLayerType_REQUEST_HANDLER,\n ExpressLayerType_ROUTER,\n} from './types';\nimport { stringMatchesSomePattern } from '../../utils/string';\n\n/**\n * Converts a user-provided error value into an error and error message pair\n *\n * @param error - User-provided error value\n * @returns Both an Error or string representation of the value and an error message\n */\nexport const asErrorAndMessage = (error: unknown): [string | Error, string] =>\n error instanceof Error ? [error, error.message] : [String(error), String(error)];\n\n/**\n * Checks if a route contains parameter patterns (e.g., :id, :userId)\n * which are valid even if they don't exactly match the original URL\n */\nexport function isRoutePattern(route: string): boolean {\n return route.includes(':') || route.includes('*');\n}\n\n/**\n * Parse express layer context to retrieve a name and attributes.\n * @param route The route of the layer\n * @param layer Express layer\n * @param [layerPath] if present, the path on which the layer has been mounted\n */\nexport const getLayerMetadata = (\n route: string,\n layer: ExpressLayer,\n layerPath?: string,\n): {\n attributes: SpanAttributes & { [ATTR_EXPRESS_NAME]: string; [ATTR_EXPRESS_TYPE]: ExpressLayerType };\n name: string;\n} => {\n if (layer.name === 'router') {\n const maybeRouterPath = getRouterPath('', layer);\n const extractedRouterPath = maybeRouterPath ? maybeRouterPath : layerPath || route || '/';\n\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: extractedRouterPath,\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_ROUTER,\n },\n name: `router - ${extractedRouterPath}`,\n };\n } else if (layer.name === 'bound dispatch' || layer.name === 'handle') {\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: (route || layerPath) ?? 'request handler',\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_REQUEST_HANDLER,\n },\n name: `request handler${layer.path ? ` - ${route || layerPath}` : ''}`,\n };\n } else {\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: layer.name,\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_MIDDLEWARE,\n },\n name: `middleware - ${layer.name}`,\n };\n }\n};\n\n/**\n * Recursively search the router path from layer stack\n * @param path The path to reconstruct\n * @param layer The layer to reconstruct from\n * @returns The reconstructed path\n */\nexport const getRouterPath = (path: string, layer: ExpressLayer): string => {\n const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : undefined;\n\n if (stackLayer?.route?.path) {\n return `${path}${stackLayer.route.path}`;\n }\n\n if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {\n return getRouterPath(path, stackLayer);\n }\n\n return path;\n};\n\n/**\n * Check whether the given request is ignored by configuration\n * It will not re-throw exceptions from `list` provided by the client\n * @param constant e.g URL of request\n * @param [list] List of ignore patterns\n * @param [onException] callback for doing something when an exception has\n * occurred\n */\nexport type ExpressIsLayerIgnoredOptions = Pick<ExpressIntegrationOptions, 'ignoreLayersType' | 'ignoreLayers'>;\nexport const isLayerIgnored = (\n name: string,\n type: ExpressLayerType,\n config?: ExpressIsLayerIgnoredOptions,\n): boolean => {\n if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {\n return true;\n }\n if (!Array.isArray(config?.ignoreLayers)) {\n return false;\n }\n try {\n return stringMatchesSomePattern(name, config.ignoreLayers, true);\n } catch {}\n\n return false;\n};\n\n/**\n * Extracts the actual matched route from Express request for OpenTelemetry instrumentation.\n * Returns the route that should be used as the http.route attribute.\n *\n * @param req - The Express request object with layers store\n * @param constructedRoute - The constructed route from `getConstructedRoute`\n * @returns The matched route string or undefined if no valid route is found\n */\nexport function getActualMatchedRoute(req: ExpressRequest, constructedRoute: string): string | undefined {\n const layersStore = getStoredLayers(req);\n\n // If no layers are stored, no route can be determined\n if (layersStore.length === 0) {\n return undefined;\n }\n\n // Handle root path case - if all paths are root, only return root if originalUrl is also root\n // The layer store also includes root paths in case a non-existing url was requested\n if (layersStore.every(path => path === '/')) {\n return req.originalUrl === '/' ? '/' : undefined;\n }\n\n if (constructedRoute === '*') {\n return constructedRoute;\n }\n\n // For RegExp routes or route arrays, return the constructed route\n // This handles the case where the route is defined using RegExp or an array\n if (\n constructedRoute.includes('/') &&\n (constructedRoute.includes(',') ||\n constructedRoute.includes('\\\\') ||\n constructedRoute.includes('*') ||\n constructedRoute.includes('['))\n ) {\n return constructedRoute;\n }\n\n // Ensure route starts with '/' if it doesn't already\n const normalizedRoute = constructedRoute.startsWith('/') ? constructedRoute : `/${constructedRoute}`;\n\n // Validate that this appears to be a matched route\n // A route is considered matched if:\n // 1. We have a constructed route\n // 2. The original URL matches or starts with our route pattern\n const isValidRoute =\n normalizedRoute.length > 0 &&\n (req.originalUrl === normalizedRoute ||\n req.originalUrl.startsWith(normalizedRoute) ||\n isRoutePattern(normalizedRoute));\n\n return isValidRoute ? normalizedRoute : undefined;\n}\n\nexport function getConstructedRoute(req: ExpressRequest) {\n const layersStore: string[] = getStoredLayers(req);\n\n let constructedRoute: string = '';\n for (const path of layersStore) {\n if (path === '/' || path === '/*') {\n continue;\n }\n constructedRoute += !constructedRoute || constructedRoute.endsWith('/') ? path : `/${path}`;\n }\n\n return constructedRoute.replace(/\\/{2,}/g, '/');\n}\n\nexport const getLayerPath = (args: unknown[]): string | undefined => {\n const firstArg = args[0];\n\n if (Array.isArray(firstArg)) {\n return firstArg.map(arg => extractLayerPathSegment(arg) || '').join(',');\n }\n\n return extractLayerPathSegment(firstArg as LayerPathSegment);\n};\n\nconst extractLayerPathSegment = (arg: LayerPathSegment): string | undefined =>\n typeof arg === 'string' ? arg : arg instanceof RegExp || typeof arg === 'number' ? String(arg) : undefined;\n\n// v5 we instrument Router.prototype\n// v4 we instrument Router itself\nexport const isExpressWithRouterPrototype = (express: unknown): express is ExpressExportv5 =>\n isExpressRouterPrototype((express as ExpressExportv5)?.Router?.prototype);\n\n// In Express v4, Router is a function (not a plain object), so we need to accept both\nconst isExpressRouterPrototype = (routerProto?: unknown): routerProto is ExpressRouterv4 =>\n (typeof routerProto === 'object' || typeof routerProto === 'function') &&\n !!routerProto &&\n 'route' in routerProto &&\n typeof (routerProto as ExpressRouterv4).route === 'function';\n\nexport const isExpressWithoutRouterPrototype = (express: unknown): express is ExpressExportv4 =>\n isExpressRouterPrototype((express as ExpressExportv4).Router) && !isExpressWithRouterPrototype(express);\n\n// dynamic puts the default on .default, require or normal import are fine\nexport const hasDefaultProp = (\n express: unknown,\n): express is {\n [k: string]: unknown;\n default: ExpressExport;\n} => !!express && typeof express === 'object' && 'default' in express && typeof express.default === 'function';\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 */\nexport function defaultShouldHandleError(error: MiddlewareError): boolean {\n const status = getStatusCodeFromResponse(error);\n return status >= 500;\n}\n"],"names":["ATTR_EXPRESS_NAME","ATTR_EXPRESS_TYPE","ExpressLayerType_ROUTER","ExpressLayerType_REQUEST_HANDLER","ExpressLayerType_MIDDLEWARE","stringMatchesSomePattern","getStoredLayers"],"mappings":";;;;;;AAoDA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,iBAAA,GAAoB,CAAC,KAAK;AACvC,EAAE,KAAA,YAAiB,KAAA,GAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAA,GAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC;;AAEjF;AACA;AACA;AACA;AACO,SAAS,cAAc,CAAC,KAAK,EAAmB;AACvD,EAAE,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAA,IAAK,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;AACnD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,mBAAmB;AAChC,EAAE,KAAK;AACP,EAAE,KAAK;AACP,EAAE,SAAS;;AAIX,KAAK;AACL,EAAE,IAAI,KAAK,CAAC,IAAA,KAAS,QAAQ,EAAE;AAC/B,IAAI,MAAM,kBAAkB,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC;AACpD,IAAI,MAAM,mBAAA,GAAsB,eAAA,GAAkB,eAAA,GAAkB,SAAA,IAAa,KAAA,IAAS,GAAG;;AAE7F,IAAI,OAAO;AACX,MAAM,UAAU,EAAE;AAClB,QAAQ,CAACA,uBAAiB,GAAG,mBAAmB;AAChD,QAAQ,CAACC,uBAAiB,GAAGC,6BAAuB;AACpD,OAAO;AACP,MAAM,IAAI,EAAE,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAA;AACA,KAAA;AACA,EAAA,CAAA,MAAA,IAAA,KAAA,CAAA,IAAA,KAAA,gBAAA,IAAA,KAAA,CAAA,IAAA,KAAA,QAAA,EAAA;AACA,IAAA,OAAA;AACA,MAAA,UAAA,EAAA;AACA,QAAA,CAAAF,uBAAA,GAAA,CAAA,KAAA,IAAA,SAAA,KAAA,iBAAA;AACA,QAAA,CAAAC,uBAAA,GAAAE,sCAAA;AACA,OAAA;AACA,MAAA,IAAA,EAAA,CAAA,eAAA,EAAA,KAAA,CAAA,IAAA,GAAA,CAAA,GAAA,EAAA,KAAA,IAAA,SAAA,CAAA,CAAA,GAAA,EAAA,CAAA,CAAA;AACA,KAAA;AACA,EAAA,CAAA,MAAA;AACA,IAAA,OAAA;AACA,MAAA,UAAA,EAAA;AACA,QAAA,CAAAH,uBAAA,GAAA,KAAA,CAAA,IAAA;AACA,QAAA,CAAAC,uBAAA,GAAAG,iCAAA;AACA,OAAA;AACA,MAAA,IAAA,EAAA,CAAA,aAAA,EAAA,KAAA,CAAA,IAAA,CAAA,CAAA;AACA,KAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,aAAA,GAAA,CAAA,IAAA,EAAA,KAAA,KAAA;AACA,EAAA,MAAA,UAAA,GAAA,KAAA,CAAA,OAAA,CAAA,KAAA,CAAA,MAAA,EAAA,KAAA,CAAA,GAAA,KAAA,CAAA,MAAA,EAAA,KAAA,GAAA,CAAA,CAAA,GAAA,SAAA;;AAEA,EAAA,IAAA,UAAA,EAAA,KAAA,EAAA,IAAA,EAAA;AACA,IAAA,OAAA,CAAA,EAAA,IAAA,CAAA,EAAA,UAAA,CAAA,KAAA,CAAA,IAAA,CAAA,CAAA;AACA,EAAA;;AAEA,EAAA,IAAA,UAAA,IAAA,KAAA,CAAA,OAAA,CAAA,UAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAA;AACA,IAAA,OAAA,aAAA,CAAA,IAAA,EAAA,UAAA,CAAA;AACA,EAAA;;AAEA,EAAA,OAAA,IAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,MAAA,cAAA,GAAA;AACA,EAAA,IAAA;AACA,EAAA,IAAA;AACA,EAAA,MAAA;AACA,KAAA;AACA,EAAA,IAAA,KAAA,CAAA,OAAA,CAAA,MAAA,EAAA,gBAAA,CAAA,IAAA,MAAA,EAAA,gBAAA,EAAA,QAAA,CAAA,IAAA,CAAA,EAAA;AACA,IAAA,OAAA,IAAA;AACA,EAAA;AACA,EAAA,IAAA,CAAA,KAAA,CAAA,OAAA,CAAA,MAAA,EAAA,YAAA,CAAA,EAAA;AACA,IAAA,OAAA,KAAA;AACA,EAAA;AACA,EAAA,IAAA;AACA,IAAA,OAAAC,+BAAA,CAAA,IAAA,EAAA,MAAA,CAAA,YAAA,EAAA,IAAA,CAAA;AACA,EAAA,CAAA,CAAA,MAAA,CAAA;;AAEA,EAAA,OAAA,KAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,GAAA,EAAA,gBAAA,EAAA;AACA,EAAA,MAAA,WAAA,GAAAC,iCAAA,CAAA,GAAA,CAAA;;AAEA;AACA,EAAA,IAAA,WAAA,CAAA,MAAA,KAAA,CAAA,EAAA;AACA,IAAA,OAAA,SAAA;AACA,EAAA;;AAEA;AACA;AACA,EAAA,IAAA,WAAA,CAAA,KAAA,CAAA,IAAA,IAAA,IAAA,KAAA,GAAA,CAAA,EAAA;AACA,IAAA,OAAA,GAAA,CAAA,WAAA,KAAA,GAAA,GAAA,GAAA,GAAA,SAAA;AACA,EAAA;;AAEA,EAAA,IAAA,gBAAA,KAAA,GAAA,EAAA;AACA,IAAA,OAAA,gBAAA;AACA,EAAA;;AAEA;AACA;AACA,EAAA;AACA,IAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,CAAA;AACA,KAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,CAAA;AACA,MAAA,gBAAA,CAAA,QAAA,CAAA,IAAA,CAAA;AACA,MAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,CAAA;AACA,MAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,CAAA;AACA,IAAA;AACA,IAAA,OAAA,gBAAA;AACA,EAAA;;AAEA;AACA,EAAA,MAAA,eAAA,GAAA,gBAAA,CAAA,UAAA,CAAA,GAAA,CAAA,GAAA,gBAAA,GAAA,CAAA,CAAA,EAAA,gBAAA,CAAA,CAAA;;AAEA;AACA;AACA;AACA;AACA,EAAA,MAAA,YAAA;AACA,IAAA,eAAA,CAAA,MAAA,GAAA,CAAA;AACA,KAAA,GAAA,CAAA,WAAA,KAAA,eAAA;AACA,MAAA,GAAA,CAAA,WAAA,CAAA,UAAA,CAAA,eAAA,CAAA;AACA,MAAA,cAAA,CAAA,eAAA,CAAA,CAAA;;AAEA,EAAA,OAAA,YAAA,GAAA,eAAA,GAAA,SAAA;AACA;;AAEA,SAAA,mBAAA,CAAA,GAAA,EAAA;AACA,EAAA,MAAA,WAAA,GAAAA,iCAAA,CAAA,GAAA,CAAA;;AAEA,EAAA,IAAA,gBAAA,GAAA,EAAA;AACA,EAAA,KAAA,MAAA,IAAA,IAAA,WAAA,EAAA;AACA,IAAA,IAAA,IAAA,KAAA,GAAA,IAAA,IAAA,KAAA,IAAA,EAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA,gBAAA,IAAA,CAAA,gBAAA,IAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,GAAA,IAAA,GAAA,CAAA,CAAA,EAAA,IAAA,CAAA,CAAA;AACA,EAAA;;AAEA,EAAA,OAAA,gBAAA,CAAA,OAAA,CAAA,SAAA,EAAA,GAAA,CAAA;AACA;;AAEA,MAAA,YAAA,GAAA,CAAA,IAAA,KAAA;AACA,EAAA,MAAA,QAAA,GAAA,IAAA,CAAA,CAAA,CAAA;;AAEA,EAAA,IAAA,KAAA,CAAA,OAAA,CAAA,QAAA,CAAA,EAAA;AACA,IAAA,OAAA,QAAA,CAAA,GAAA,CAAA,GAAA,IAAA,uBAAA,CAAA,GAAA,CAAA,IAAA,EAAA,CAAA,CAAA,IAAA,CAAA,GAAA,CAAA;AACA,EAAA;;AAEA,EAAA,OAAA,uBAAA,CAAA,QAAA,EAAA;AACA;;AAEA,MAAA,uBAAA,GAAA,CAAA,GAAA;AACA,EAAA,OAAA,GAAA,KAAA,QAAA,GAAA,GAAA,GAAA,GAAA,YAAA,MAAA,IAAA,OAAA,GAAA,KAAA,QAAA,GAAA,MAAA,CAAA,GAAA,CAAA,GAAA,SAAA;;AAEA;AACA;AACA,MAAA,4BAAA,GAAA,CAAA,OAAA;AACA,EAAA,wBAAA,CAAA,CAAA,OAAA,IAAA,MAAA,EAAA,SAAA;;AAEA;AACA,MAAA,wBAAA,GAAA,CAAA,WAAA;AACA,EAAA,CAAA,OAAA,WAAA,KAAA,QAAA,IAAA,OAAA,WAAA,KAAA,UAAA;AACA,EAAA,CAAA,CAAA,WAAA;AACA,EAAA,OAAA,IAAA,WAAA;AACA,EAAA,OAAA,CAAA,WAAA,GAAA,KAAA,KAAA,UAAA;;AAEA,MAAA,+BAAA,GAAA,CAAA,OAAA;AACA,EAAA,wBAAA,CAAA,CAAA,OAAA,GAAA,MAAA,CAAA,IAAA,CAAA,4BAAA,CAAA,OAAA;;AAEA;AACA,MAAA,cAAA,GAAA;AACA,EAAA,OAAA;;AAIA,KAAA,CAAA,CAAA,OAAA,IAAA,OAAA,OAAA,KAAA,QAAA,IAAA,SAAA,IAAA,OAAA,IAAA,OAAA,OAAA,CAAA,OAAA,KAAA;;AAEA,SAAA,yBAAA,CAAA,KAAA,EAAA;AACA,EAAA,MAAA,UAAA,GAAA,KAAA,CAAA,MAAA,IAAA,KAAA,CAAA,UAAA,IAAA,KAAA,CAAA,WAAA,IAAA,KAAA,CAAA,MAAA,EAAA,UAAA;AACA,EAAA,OAAA,UAAA,GAAA,QAAA,CAAA,UAAA,GAAA,EAAA,CAAA,GAAA,GAAA;AACA;;AAEA;AACA,SAAA,wBAAA,CAAA,KAAA,EAAA;AACA,EAAA,MAAA,MAAA,GAAA,yBAAA,CAAA,KAAA,CAAA;AACA,EAAA,OAAA,MAAA,IAAA,GAAA;AACA;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/integrations/express/utils.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { SpanAttributes } from '../../types-hoist/span';\nimport { getStoredLayers } from './request-layer-store';\nimport type {\n ExpressIntegrationOptions,\n ExpressLayer,\n ExpressLayerType,\n ExpressRequest,\n LayerPathSegment,\n MiddlewareError,\n ExpressRouterv4,\n ExpressExportv5,\n ExpressExportv4,\n} from './types';\nimport {\n ATTR_EXPRESS_NAME,\n ATTR_EXPRESS_TYPE,\n ExpressLayerType_MIDDLEWARE,\n ExpressLayerType_REQUEST_HANDLER,\n ExpressLayerType_ROUTER,\n} from './types';\nimport { stringMatchesSomePattern } from '../../utils/string';\n\n/**\n * Converts a user-provided error value into an error and error message pair\n *\n * @param error - User-provided error value\n * @returns Both an Error or string representation of the value and an error message\n */\nexport const asErrorAndMessage = (error: unknown): [string | Error, string] =>\n error instanceof Error ? [error, error.message] : [String(error), String(error)];\n\n/**\n * Checks if a route contains parameter patterns (e.g., :id, :userId)\n * which are valid even if they don't exactly match the original URL\n */\nexport function isRoutePattern(route: string): boolean {\n return route.includes(':') || route.includes('*');\n}\n\n/**\n * Parse express layer context to retrieve a name and attributes.\n * @param route The route of the layer\n * @param layer Express layer\n * @param [layerPath] if present, the path on which the layer has been mounted\n */\nexport const getLayerMetadata = (\n route: string,\n layer: ExpressLayer,\n layerPath?: string,\n): {\n attributes: SpanAttributes & { [ATTR_EXPRESS_NAME]: string; [ATTR_EXPRESS_TYPE]: ExpressLayerType };\n name: string;\n} => {\n if (layer.name === 'router') {\n const maybeRouterPath = getRouterPath('', layer);\n const extractedRouterPath = maybeRouterPath ? maybeRouterPath : layerPath || route || '/';\n\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: extractedRouterPath,\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_ROUTER,\n },\n name: `router - ${extractedRouterPath}`,\n };\n } else if (layer.name === 'bound dispatch' || layer.name === 'handle') {\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: (route || layerPath) ?? 'request handler',\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_REQUEST_HANDLER,\n },\n name: `request handler${layer.path ? ` - ${route || layerPath}` : ''}`,\n };\n } else {\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: layer.name,\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_MIDDLEWARE,\n },\n name: `middleware - ${layer.name}`,\n };\n }\n};\n\n/**\n * Recursively search the router path from layer stack\n * @param path The path to reconstruct\n * @param layer The layer to reconstruct from\n * @returns The reconstructed path\n */\nexport const getRouterPath = (path: string, layer: ExpressLayer): string => {\n const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : undefined;\n\n if (stackLayer?.route?.path) {\n return `${path}${stackLayer.route.path}`;\n }\n\n if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {\n return getRouterPath(path, stackLayer);\n }\n\n return path;\n};\n\n/**\n * Check whether the given request is ignored by configuration\n * It will not re-throw exceptions from `list` provided by the client\n * @param constant e.g URL of request\n * @param [list] List of ignore patterns\n * @param [onException] callback for doing something when an exception has\n * occurred\n */\nexport type ExpressIsLayerIgnoredOptions = Pick<ExpressIntegrationOptions, 'ignoreLayersType' | 'ignoreLayers'>;\nexport const isLayerIgnored = (\n name: string,\n type: ExpressLayerType,\n config?: ExpressIsLayerIgnoredOptions,\n): boolean => {\n if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {\n return true;\n }\n if (!Array.isArray(config?.ignoreLayers)) {\n return false;\n }\n try {\n return stringMatchesSomePattern(name, config.ignoreLayers, true);\n } catch {}\n\n return false;\n};\n\n/**\n * Extracts the actual matched route from Express request for OpenTelemetry instrumentation.\n * Returns the route that should be used as the http.route attribute.\n *\n * @param req - The Express request object with layers store\n * @param constructedRoute - The constructed route from `getConstructedRoute`\n * @returns The matched route string or undefined if no valid route is found\n */\nexport function getActualMatchedRoute(req: ExpressRequest, constructedRoute: string): string | undefined {\n const layersStore = getStoredLayers(req);\n\n // If no layers are stored, no route can be determined\n if (layersStore.length === 0) {\n return undefined;\n }\n\n // Handle root path case - if all paths are root, only return root if originalUrl is also root\n // The layer store also includes root paths in case a non-existing url was requested\n if (layersStore.every(path => path === '/')) {\n return req.originalUrl === '/' ? '/' : undefined;\n }\n\n if (constructedRoute === '*') {\n return constructedRoute;\n }\n\n // For RegExp routes or route arrays, return the constructed route\n // This handles the case where the route is defined using RegExp or an array\n if (\n constructedRoute.includes('/') &&\n (constructedRoute.includes(',') ||\n constructedRoute.includes('\\\\') ||\n constructedRoute.includes('*') ||\n constructedRoute.includes('['))\n ) {\n return constructedRoute;\n }\n\n // Ensure route starts with '/' if it doesn't already\n const normalizedRoute = constructedRoute.startsWith('/') ? constructedRoute : `/${constructedRoute}`;\n\n // Validate that this appears to be a matched route\n // A route is considered matched if:\n // 1. We have a constructed route\n // 2. The original URL matches or starts with our route pattern\n const isValidRoute =\n normalizedRoute.length > 0 &&\n (req.originalUrl === normalizedRoute ||\n req.originalUrl.startsWith(normalizedRoute) ||\n isRoutePattern(normalizedRoute));\n\n return isValidRoute ? normalizedRoute : undefined;\n}\n\nexport function getConstructedRoute(req: ExpressRequest) {\n const layersStore: string[] = getStoredLayers(req);\n\n let constructedRoute: string = '';\n for (const path of layersStore) {\n if (path === '/' || path === '/*') {\n continue;\n }\n constructedRoute += !constructedRoute || constructedRoute.endsWith('/') ? path : `/${path}`;\n }\n\n return constructedRoute.replace(/\\/{2,}/g, '/');\n}\n\nexport const getLayerPath = (args: unknown[]): string | undefined => {\n const firstArg = args[0];\n\n if (Array.isArray(firstArg)) {\n return firstArg.map(arg => extractLayerPathSegment(arg) || '').join(',');\n }\n\n return extractLayerPathSegment(firstArg as LayerPathSegment);\n};\n\nconst extractLayerPathSegment = (arg: LayerPathSegment): string | undefined =>\n typeof arg === 'string' ? arg : arg instanceof RegExp || typeof arg === 'number' ? String(arg) : undefined;\n\n// v5 we instrument Router.prototype\n// v4 we instrument Router itself\nexport const isExpressWithRouterPrototype = (express: unknown): express is ExpressExportv5 =>\n isExpressRouterPrototype((express as ExpressExportv5)?.Router?.prototype);\n\n// In Express v4, Router is a function (not a plain object), so we need to accept both\nconst isExpressRouterPrototype = (routerProto?: unknown): routerProto is ExpressRouterv4 =>\n (typeof routerProto === 'object' || typeof routerProto === 'function') &&\n !!routerProto &&\n 'route' in routerProto &&\n typeof (routerProto as ExpressRouterv4).route === 'function';\n\nexport const isExpressWithoutRouterPrototype = (express: unknown): express is ExpressExportv4 =>\n isExpressRouterPrototype((express as ExpressExportv4).Router) && !isExpressWithRouterPrototype(express);\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 */\nexport function defaultShouldHandleError(error: MiddlewareError): boolean {\n const status = getStatusCodeFromResponse(error);\n return status >= 500;\n}\n"],"names":["ATTR_EXPRESS_NAME","ATTR_EXPRESS_TYPE","ExpressLayerType_ROUTER","ExpressLayerType_REQUEST_HANDLER","ExpressLayerType_MIDDLEWARE","stringMatchesSomePattern","getStoredLayers"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ const integration = require('../integration.js');
|
|
|
5
5
|
const debugLogger = require('../utils/debug-logger.js');
|
|
6
6
|
const is = require('../utils/is.js');
|
|
7
7
|
const normalize = require('../utils/normalize.js');
|
|
8
|
-
const
|
|
8
|
+
const normalizationHints = require('../utils/normalizationHints.js');
|
|
9
9
|
const string = require('../utils/string.js');
|
|
10
10
|
|
|
11
11
|
const INTEGRATION_NAME = 'ExtraErrorData';
|
|
@@ -50,7 +50,7 @@ function _enhanceEventWithErrorData(
|
|
|
50
50
|
if (is.isPlainObject(normalizedErrorData)) {
|
|
51
51
|
// We mark the error data as "already normalized" here, because we don't want other normalization procedures to
|
|
52
52
|
// potentially truncate the data we just already normalized, with a certain depth setting.
|
|
53
|
-
|
|
53
|
+
normalizationHints.setSkipNormalizationHint(normalizedErrorData);
|
|
54
54
|
contexts[exceptionName] = normalizedErrorData;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extraerrordata.js","sources":["../../../src/integrations/extraerrordata.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport { defineIntegration } from '../integration';\nimport type { Contexts } from '../types-hoist/context';\nimport type { ExtendedError } from '../types-hoist/error';\nimport type { Event, EventHint } from '../types-hoist/event';\nimport type { IntegrationFn } from '../types-hoist/integration';\nimport { debug } from '../utils/debug-logger';\nimport { isError, isPlainObject } from '../utils/is';\nimport { normalize } from '../utils/normalize';\nimport {
|
|
1
|
+
{"version":3,"file":"extraerrordata.js","sources":["../../../src/integrations/extraerrordata.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport { defineIntegration } from '../integration';\nimport type { Contexts } from '../types-hoist/context';\nimport type { ExtendedError } from '../types-hoist/error';\nimport type { Event, EventHint } from '../types-hoist/event';\nimport type { IntegrationFn } from '../types-hoist/integration';\nimport { debug } from '../utils/debug-logger';\nimport { isError, isPlainObject } from '../utils/is';\nimport { normalize } from '../utils/normalize';\nimport { setSkipNormalizationHint } from '../utils/normalizationHints';\nimport { truncate } from '../utils/string';\n\nconst INTEGRATION_NAME = 'ExtraErrorData';\n\ninterface ExtraErrorDataOptions {\n /**\n * The object depth up to which to capture data on error objects.\n */\n depth: number;\n\n /**\n * Whether to capture error causes. Defaults to true.\n *\n * More information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause\n */\n captureErrorCause: boolean;\n}\n\n/**\n * Extract additional data for from original exceptions.\n */\nconst _extraErrorDataIntegration = ((options: Partial<ExtraErrorDataOptions> = {}) => {\n const { depth = 3, captureErrorCause = true } = options;\n return {\n name: INTEGRATION_NAME,\n processEvent(event, hint, client) {\n const { maxValueLength } = client.getOptions();\n return _enhanceEventWithErrorData(event, hint, depth, captureErrorCause, maxValueLength);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const extraErrorDataIntegration = defineIntegration(_extraErrorDataIntegration);\n\nfunction _enhanceEventWithErrorData(\n event: Event,\n hint: EventHint = {},\n depth: number,\n captureErrorCause: boolean,\n maxValueLength: number | undefined,\n): Event {\n if (!hint.originalException || !isError(hint.originalException)) {\n return event;\n }\n const exceptionName = (hint.originalException as ExtendedError).name || hint.originalException.constructor.name;\n\n const errorData = _extractErrorData(hint.originalException as ExtendedError, captureErrorCause, maxValueLength);\n\n if (errorData) {\n const contexts: Contexts = {\n ...event.contexts,\n };\n\n const normalizedErrorData = normalize(errorData, depth);\n\n if (isPlainObject(normalizedErrorData)) {\n // We mark the error data as \"already normalized\" here, because we don't want other normalization procedures to\n // potentially truncate the data we just already normalized, with a certain depth setting.\n setSkipNormalizationHint(normalizedErrorData);\n contexts[exceptionName] = normalizedErrorData;\n }\n\n return {\n ...event,\n contexts,\n };\n }\n\n return event;\n}\n\n/**\n * Extract extra information from the Error object\n */\nfunction _extractErrorData(\n error: ExtendedError,\n captureErrorCause: boolean,\n maxValueLength: number | undefined,\n): Record<string, unknown> | null {\n // We are trying to enhance already existing event, so no harm done if it won't succeed\n try {\n const nativeKeys = [\n 'name',\n 'message',\n 'stack',\n 'line',\n 'column',\n 'fileName',\n 'lineNumber',\n 'columnNumber',\n 'toJSON',\n ];\n\n const extraErrorInfo: Record<string, unknown> = {};\n\n // We want only enumerable properties, thus `getOwnPropertyNames` is redundant here, as we filter keys anyway.\n for (const key of Object.keys(error)) {\n if (nativeKeys.indexOf(key) !== -1) {\n continue;\n }\n const value = error[key];\n extraErrorInfo[key] =\n isError(value) || typeof value === 'string'\n ? maxValueLength\n ? truncate(`${value}`, maxValueLength)\n : `${value}`\n : value;\n }\n\n // Error.cause is a standard property that is non enumerable, we therefore need to access it separately.\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause\n if (captureErrorCause && error.cause !== undefined) {\n if (isError(error.cause)) {\n const errorName = error.cause.name || error.cause.constructor.name;\n extraErrorInfo.cause = { [errorName]: _extractErrorData(error.cause as ExtendedError, false, maxValueLength) };\n } else {\n extraErrorInfo.cause = error.cause;\n }\n }\n\n // Check if someone attached `toJSON` method to grab even more properties (eg. axios is doing that)\n if (typeof error.toJSON === 'function') {\n const serializedError = error.toJSON() as Record<string, unknown>;\n\n for (const key of Object.keys(serializedError)) {\n const value = serializedError[key];\n extraErrorInfo[key] = isError(value) ? value.toString() : value;\n }\n }\n\n return extraErrorInfo;\n } catch (oO) {\n DEBUG_BUILD && debug.error('Unable to extract extra data from the Error object:', oO);\n }\n\n return null;\n}\n"],"names":["defineIntegration","isError","normalize","isPlainObject","setSkipNormalizationHint","truncate","DEBUG_BUILD","debug"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const breadcrumbs = require('../../breadcrumbs.js');
|
|
4
|
+
const breadcrumbLogLevel = require('../../utils/breadcrumb-log-level.js');
|
|
5
|
+
const url = require('../../utils/url.js');
|
|
6
|
+
const getRequestUrl = require('./get-request-url.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a breadcrumb for a finished outgoing HTTP request.
|
|
10
|
+
*/
|
|
11
|
+
function addOutgoingRequestBreadcrumb(
|
|
12
|
+
request,
|
|
13
|
+
response,
|
|
14
|
+
) {
|
|
15
|
+
const url$1 = getRequestUrl.getRequestUrlFromClientRequest(request);
|
|
16
|
+
const parsedUrl = url.parseUrl(url$1);
|
|
17
|
+
|
|
18
|
+
const statusCode = response?.statusCode;
|
|
19
|
+
const level = breadcrumbLogLevel.getBreadcrumbLogLevelFromHttpStatusCode(statusCode);
|
|
20
|
+
|
|
21
|
+
breadcrumbs.addBreadcrumb(
|
|
22
|
+
{
|
|
23
|
+
category: 'http',
|
|
24
|
+
data: {
|
|
25
|
+
status_code: statusCode,
|
|
26
|
+
url: url.getSanitizedUrlString(parsedUrl),
|
|
27
|
+
'http.method': request.method || 'GET',
|
|
28
|
+
...(parsedUrl.search ? { 'http.query': parsedUrl.search } : {}),
|
|
29
|
+
...(parsedUrl.hash ? { 'http.fragment': parsedUrl.hash } : {}),
|
|
30
|
+
},
|
|
31
|
+
type: 'http',
|
|
32
|
+
level,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
event: 'response',
|
|
36
|
+
request,
|
|
37
|
+
response,
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.addOutgoingRequestBreadcrumb = addOutgoingRequestBreadcrumb;
|
|
43
|
+
//# sourceMappingURL=add-outgoing-request-breadcrumb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-outgoing-request-breadcrumb.js","sources":["../../../../src/integrations/http/add-outgoing-request-breadcrumb.ts"],"sourcesContent":["import { addBreadcrumb } from '../../breadcrumbs';\nimport { getBreadcrumbLogLevelFromHttpStatusCode } from '../../utils/breadcrumb-log-level';\nimport { getSanitizedUrlString, parseUrl } from '../../utils/url';\nimport { getRequestUrlFromClientRequest } from './get-request-url';\nimport type { HttpClientRequest, HttpIncomingMessage } from './types';\n\n/**\n * Create a breadcrumb for a finished outgoing HTTP request.\n */\nexport function addOutgoingRequestBreadcrumb(\n request: HttpClientRequest,\n response: HttpIncomingMessage | undefined,\n): void {\n const url = getRequestUrlFromClientRequest(request);\n const parsedUrl = parseUrl(url);\n\n const statusCode = response?.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n ...(parsedUrl.search ? { 'http.query': parsedUrl.search } : {}),\n ...(parsedUrl.hash ? { 'http.fragment': parsedUrl.hash } : {}),\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n"],"names":["url","getRequestUrlFromClientRequest","parseUrl","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","getSanitizedUrlString"],"mappings":";;;;;;;AAMA;AACA;AACA;AACO,SAAS,4BAA4B;AAC5C,EAAE,OAAO;AACT,EAAE,QAAQ;AACV,EAAQ;AACR,EAAE,MAAMA,KAAA,GAAMC,4CAA8B,CAAC,OAAO,CAAC;AACrD,EAAE,MAAM,SAAA,GAAYC,YAAQ,CAACF,KAAG,CAAC;;AAEjC,EAAE,MAAM,UAAA,GAAa,QAAQ,EAAE,UAAU;AACzC,EAAE,MAAM,KAAA,GAAQG,0DAAuC,CAAC,UAAU,CAAC;;AAEnE,EAAEC,yBAAa;AACf,IAAI;AACJ,MAAM,QAAQ,EAAE,MAAM;AACtB,MAAM,IAAI,EAAE;AACZ,QAAQ,WAAW,EAAE,UAAU;AAC/B,QAAQ,GAAG,EAAEC,yBAAqB,CAAC,SAAS,CAAC;AAC7C,QAAQ,aAAa,EAAE,OAAO,CAAC,MAAA,IAAU,KAAK;AAC9C,QAAQ,IAAI,SAAS,CAAC,MAAA,GAAS,EAAE,YAAY,EAAE,SAAS,CAAC,MAAA,EAAO,GAAI,EAAE,CAAC;AACvE,QAAQ,IAAI,SAAS,CAAC,IAAA,GAAO,EAAE,eAAe,EAAE,SAAS,CAAC,IAAA,EAAK,GAAI,EAAE,CAAC;AACtE,OAAO;AACP,MAAM,IAAI,EAAE,MAAM;AAClB,MAAM,KAAK;AACX,KAAK;AACL,IAAI;AACJ,MAAM,KAAK,EAAE,UAAU;AACvB,MAAM,OAAO;AACb,MAAM,QAAQ;AACd,KAAK;AACL,GAAG;AACH;;;;"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const getDefaultExport = require('../../utils/get-default-export.js');
|
|
4
|
+
const constants = require('./constants.js');
|
|
5
|
+
const object = require('../../utils/object.js');
|
|
6
|
+
const clientSubscriptions = require('./client-subscriptions.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Platform-portable HTTP(S) outgoing-request patching integration
|
|
10
|
+
*
|
|
11
|
+
* Patches the `http` and `https` Node.js built-in module exports to create
|
|
12
|
+
* Sentry spans for outgoing requests and optionally inject distributed trace
|
|
13
|
+
* propagation headers.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*
|
|
17
|
+
* This Sentry integration is a derivative work based on the OpenTelemetry
|
|
18
|
+
* HTTP instrumentation.
|
|
19
|
+
*
|
|
20
|
+
* <https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http>
|
|
21
|
+
*
|
|
22
|
+
* Extended under the terms of the Apache 2.0 license linked below:
|
|
23
|
+
*
|
|
24
|
+
* ----
|
|
25
|
+
*
|
|
26
|
+
* Copyright The OpenTelemetry Authors
|
|
27
|
+
*
|
|
28
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
29
|
+
* you may not use this file except in compliance with the License.
|
|
30
|
+
* You may obtain a copy of the License at
|
|
31
|
+
*
|
|
32
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
33
|
+
*
|
|
34
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
35
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
36
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
37
|
+
* See the License for the specific language governing permissions and
|
|
38
|
+
* limitations under the License.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
function patchHttpRequest(httpModule, options) {
|
|
43
|
+
// avoid double-wrap
|
|
44
|
+
if (!object.getOriginalFunction(httpModule.request)) {
|
|
45
|
+
const { [constants.HTTP_ON_CLIENT_REQUEST]: onHttpClientRequestCreated } = clientSubscriptions.getHttpClientSubscriptions({
|
|
46
|
+
...options,
|
|
47
|
+
http: httpModule,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const originalRequest = httpModule.request;
|
|
51
|
+
object.wrapMethod(httpModule, 'request', function patchedRequest( ...args) {
|
|
52
|
+
const request = originalRequest.apply(this, args) ;
|
|
53
|
+
onHttpClientRequestCreated({ request }, constants.HTTP_ON_CLIENT_REQUEST);
|
|
54
|
+
return request;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// This simply ensures that http.get calls http.request, which we patched.
|
|
60
|
+
// Call it from the object each time, to ensure that any subsequent patches
|
|
61
|
+
// or other mutations are also respected.
|
|
62
|
+
function patchHttpGet(httpModule) {
|
|
63
|
+
if (!object.getOriginalFunction(httpModule.get)) {
|
|
64
|
+
// match node's normalization to exactly 3 arguments.
|
|
65
|
+
object.wrapMethod(httpModule, 'get', function patchedGet( input, options, cb) {
|
|
66
|
+
// http.get is like http.request but automatically calls .end()
|
|
67
|
+
const request = httpModule.request.call(this, input, options, cb) ;
|
|
68
|
+
request.end();
|
|
69
|
+
return request;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function patchModule(httpModuleExport, options = {}) {
|
|
75
|
+
const httpDefault = getDefaultExport.getDefaultExport(httpModuleExport);
|
|
76
|
+
const httpModule = httpModuleExport ;
|
|
77
|
+
// if we have a default, patch that, and copy to the import container
|
|
78
|
+
if (httpDefault !== httpModuleExport) {
|
|
79
|
+
patchModule(httpDefault, options);
|
|
80
|
+
// copy with defineProperty because these might be configured oddly
|
|
81
|
+
for (const method of ['get', 'request']) {
|
|
82
|
+
const desc = Object.getOwnPropertyDescriptor(httpDefault, method);
|
|
83
|
+
/* v8 ignore start - will always be set at this point */
|
|
84
|
+
if (desc) {
|
|
85
|
+
Object.defineProperty(httpModule, method, desc);
|
|
86
|
+
}
|
|
87
|
+
/* v8 ignore stop */
|
|
88
|
+
}
|
|
89
|
+
return httpModule;
|
|
90
|
+
}
|
|
91
|
+
patchHttpRequest(httpModule, options);
|
|
92
|
+
patchHttpGet(httpModule);
|
|
93
|
+
return httpModuleExport;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Patch an `node:http` or `node:https` module-shaped export so that every
|
|
98
|
+
* outgoing request is tracked by Sentry.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```javascript
|
|
102
|
+
* import http from 'http';
|
|
103
|
+
* import { patchHttpModule } from '@sentry/core';
|
|
104
|
+
* patchHttpModule(http, { propagateTrace: true });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
const patchHttpModuleClient = (
|
|
108
|
+
httpModuleExport,
|
|
109
|
+
options = {},
|
|
110
|
+
) => patchModule(httpModuleExport, options);
|
|
111
|
+
|
|
112
|
+
exports.patchHttpModuleClient = patchHttpModuleClient;
|
|
113
|
+
//# sourceMappingURL=client-patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-patch.js","sources":["../../../../src/integrations/http/client-patch.ts"],"sourcesContent":["/**\n * Platform-portable HTTP(S) outgoing-request patching integration\n *\n * Patches the `http` and `https` Node.js built-in module exports to create\n * Sentry spans for outgoing requests and optionally inject distributed trace\n * propagation headers.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * HTTP instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getDefaultExport } from '../../utils/get-default-export';\nimport { HTTP_ON_CLIENT_REQUEST } from './constants';\nimport type { HttpExport, HttpModuleExport, HttpInstrumentationOptions, HttpClientRequest } from './types';\nimport { getOriginalFunction, wrapMethod } from '../../utils/object';\nimport { getHttpClientSubscriptions } from './client-subscriptions';\n\nfunction patchHttpRequest(httpModule: HttpExport, options: HttpInstrumentationOptions): void {\n // avoid double-wrap\n if (!getOriginalFunction(httpModule.request)) {\n const { [HTTP_ON_CLIENT_REQUEST]: onHttpClientRequestCreated } = getHttpClientSubscriptions({\n ...options,\n http: httpModule,\n });\n\n const originalRequest = httpModule.request;\n wrapMethod(httpModule, 'request', function patchedRequest(this: HttpExport, ...args: unknown[]) {\n const request = originalRequest.apply(this, args) as HttpClientRequest;\n onHttpClientRequestCreated({ request }, HTTP_ON_CLIENT_REQUEST);\n return request;\n });\n }\n}\n\n// This simply ensures that http.get calls http.request, which we patched.\n// Call it from the object each time, to ensure that any subsequent patches\n// or other mutations are also respected.\nfunction patchHttpGet(httpModule: HttpExport) {\n if (!getOriginalFunction(httpModule.get)) {\n // match node's normalization to exactly 3 arguments.\n wrapMethod(httpModule, 'get', function patchedGet(this: HttpExport, input: unknown, options: unknown, cb: unknown) {\n // http.get is like http.request but automatically calls .end()\n const request = httpModule.request.call(this, input, options, cb) as HttpClientRequest;\n request.end();\n return request;\n });\n }\n}\n\nfunction patchModule(httpModuleExport: HttpModuleExport, options: HttpInstrumentationOptions = {}): HttpModuleExport {\n const httpDefault = getDefaultExport(httpModuleExport);\n const httpModule = httpModuleExport as HttpExport;\n // if we have a default, patch that, and copy to the import container\n if (httpDefault !== httpModuleExport) {\n patchModule(httpDefault, options);\n // copy with defineProperty because these might be configured oddly\n for (const method of ['get', 'request']) {\n const desc = Object.getOwnPropertyDescriptor(httpDefault, method);\n /* v8 ignore start - will always be set at this point */\n if (desc) {\n Object.defineProperty(httpModule, method, desc);\n }\n /* v8 ignore stop */\n }\n return httpModule;\n }\n patchHttpRequest(httpModule, options);\n patchHttpGet(httpModule);\n return httpModuleExport;\n}\n\n/**\n * Patch an `node:http` or `node:https` module-shaped export so that every\n * outgoing request is tracked by Sentry.\n *\n * @example\n * ```javascript\n * import http from 'http';\n * import { patchHttpModule } from '@sentry/core';\n * patchHttpModule(http, { propagateTrace: true });\n * ```\n */\nexport const patchHttpModuleClient = (\n httpModuleExport: HttpModuleExport,\n options: HttpInstrumentationOptions = {},\n): HttpModuleExport => patchModule(httpModuleExport, options);\n"],"names":["getOriginalFunction","HTTP_ON_CLIENT_REQUEST","getHttpClientSubscriptions","wrapMethod","getDefaultExport"],"mappings":";;;;;;;AAAA;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;;;AAQA,SAAS,gBAAgB,CAAC,UAAU,EAAc,OAAO,EAAoC;AAC7F;AACA,EAAE,IAAI,CAACA,0BAAmB,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;AAChD,IAAI,MAAM,EAAE,CAACC,gCAAsB,GAAG,0BAAA,EAA2B,GAAIC,8CAA0B,CAAC;AAChG,MAAM,GAAG,OAAO;AAChB,MAAM,IAAI,EAAE,UAAU;AACtB,KAAK,CAAC;;AAEN,IAAI,MAAM,eAAA,GAAkB,UAAU,CAAC,OAAO;AAC9C,IAAIC,iBAAU,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,cAAc,EAAmB,GAAG,IAAI,EAAa;AACpG,MAAM,MAAM,OAAA,GAAU,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAA;AACtD,MAAM,0BAA0B,CAAC,EAAE,SAAS,EAAEF,gCAAsB,CAAC;AACrE,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC,CAAC;AACN,EAAE;AACF;;AAEA;AACA;AACA;AACA,SAAS,YAAY,CAAC,UAAU,EAAc;AAC9C,EAAE,IAAI,CAACD,0BAAmB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC5C;AACA,IAAIG,iBAAU,CAAC,UAAU,EAAE,KAAK,EAAE,SAAS,UAAU,EAAmB,KAAK,EAAW,OAAO,EAAW,EAAE,EAAW;AACvH;AACA,MAAM,MAAM,OAAA,GAAU,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAA;AACtE,MAAM,OAAO,CAAC,GAAG,EAAE;AACnB,MAAM,OAAO,OAAO;AACpB,IAAI,CAAC,CAAC;AACN,EAAE;AACF;;AAEA,SAAS,WAAW,CAAC,gBAAgB,EAAoB,OAAO,GAA+B,EAAE,EAAoB;AACrH,EAAE,MAAM,WAAA,GAAcC,iCAAgB,CAAC,gBAAgB,CAAC;AACxD,EAAE,MAAM,UAAA,GAAa,gBAAA;AACrB;AACA,EAAE,IAAI,WAAA,KAAgB,gBAAgB,EAAE;AACxC,IAAI,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC;AACrC;AACA,IAAI,KAAK,MAAM,MAAA,IAAU,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE;AAC7C,MAAM,MAAM,IAAA,GAAO,MAAM,CAAC,wBAAwB,CAAC,WAAW,EAAE,MAAM,CAAC;AACvE;AACA,MAAM,IAAI,IAAI,EAAE;AAChB,QAAQ,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC;AACvD,MAAM;AACN;AACA,IAAI;AACJ,IAAI,OAAO,UAAU;AACrB,EAAE;AACF,EAAE,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC;AACvC,EAAE,YAAY,CAAC,UAAU,CAAC;AAC1B,EAAE,OAAO,gBAAgB;AACzB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,wBAAwB;AACrC,EAAE,gBAAgB;AAClB,EAAE,OAAO,GAA+B,EAAE;AAC1C,KAAuB,WAAW,CAAC,gBAAgB,EAAE,OAAO;;;;"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const addOutgoingRequestBreadcrumb = require('./add-outgoing-request-breadcrumb.js');
|
|
4
|
+
const debugBuild = require('../../debug-build.js');
|
|
5
|
+
const debugLogger = require('../../utils/debug-logger.js');
|
|
6
|
+
const currentScopes = require('../../currentScopes.js');
|
|
7
|
+
const spanstatus = require('../../tracing/spanstatus.js');
|
|
8
|
+
const hasSpansEnabled = require('../../utils/hasSpansEnabled.js');
|
|
9
|
+
const trace = require('../../tracing/trace.js');
|
|
10
|
+
const lru = require('../../utils/lru.js');
|
|
11
|
+
const getOutgoingSpanData = require('./get-outgoing-span-data.js');
|
|
12
|
+
const getRequestUrl = require('./get-request-url.js');
|
|
13
|
+
const injectTracePropagationHeaders = require('./inject-trace-propagation-headers.js');
|
|
14
|
+
const constants = require('./constants.js');
|
|
15
|
+
const doubleWrapWarning = require('./double-wrap-warning.js');
|
|
16
|
+
|
|
17
|
+
function getHttpClientSubscriptions(options) {
|
|
18
|
+
const propagationDecisionMap = new lru.LRUMap(100);
|
|
19
|
+
const getConfig = () => currentScopes.getClient()?.getOptions();
|
|
20
|
+
|
|
21
|
+
const onHttpClientRequestCreated = (data) => {
|
|
22
|
+
// Skip all instrumentation if tracing is suppressed
|
|
23
|
+
// (e.g., Sentry's own transport uses this to avoid self-instrumentation)
|
|
24
|
+
if (currentScopes.getCurrentScope().getScopeData().sdkProcessingMetadata[trace.SUPPRESS_TRACING_KEY] === true) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const clientOptions = getConfig();
|
|
29
|
+
const {
|
|
30
|
+
errorMonitor = 'error',
|
|
31
|
+
spans: createSpans = clientOptions ? hasSpansEnabled.hasSpansEnabled(clientOptions) : true,
|
|
32
|
+
propagateTrace = false,
|
|
33
|
+
breadcrumbs = true,
|
|
34
|
+
http,
|
|
35
|
+
https,
|
|
36
|
+
suppressOtelWarning = false,
|
|
37
|
+
} = options;
|
|
38
|
+
|
|
39
|
+
const { request } = data ;
|
|
40
|
+
|
|
41
|
+
// check if request is ignored. if so, we do nothing at all.
|
|
42
|
+
if (options.ignoreOutgoingRequests?.(getRequestUrl.getRequestUrlFromClientRequest(request), request)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// guard against adding breadcrumbs multiple times, or when not enabled
|
|
47
|
+
let addedBreadcrumbs = false;
|
|
48
|
+
function addBreadcrumbs(request, response) {
|
|
49
|
+
if (!addedBreadcrumbs) {
|
|
50
|
+
addedBreadcrumbs = true;
|
|
51
|
+
addOutgoingRequestBreadcrumb.addOutgoingRequestBreadcrumb(request, response);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// called if spans and/or trace propagation are disabled
|
|
56
|
+
function breadcrumbsOnly(request) {
|
|
57
|
+
request.on(errorMonitor, () => addBreadcrumbs(request, undefined));
|
|
58
|
+
request.prependListener('response', response => {
|
|
59
|
+
if (request.listenerCount('response') <= 1) {
|
|
60
|
+
response.resume();
|
|
61
|
+
}
|
|
62
|
+
response.on('end', () => addBreadcrumbs(request, response));
|
|
63
|
+
response.on(errorMonitor, () => addBreadcrumbs(request, response));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!createSpans) {
|
|
68
|
+
// no spans, but maybe tracing and/or breadcrumbs
|
|
69
|
+
if (breadcrumbs) {
|
|
70
|
+
breadcrumbsOnly(request);
|
|
71
|
+
}
|
|
72
|
+
if (propagateTrace) {
|
|
73
|
+
injectTracePropagationHeaders.injectTracePropagationHeaders(request, propagationDecisionMap);
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// guard against OTel wrapping the same module and emitting double-spans
|
|
79
|
+
// this doesn't prevent it, just prints a debug warning for the user.
|
|
80
|
+
if (!suppressOtelWarning) {
|
|
81
|
+
if (http) doubleWrapWarning.doubleWrapWarning(http);
|
|
82
|
+
if (https) doubleWrapWarning.doubleWrapWarning(https);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// spans are enabled
|
|
86
|
+
const span = trace.startInactiveSpan(getOutgoingSpanData.getOutgoingRequestSpanData(request));
|
|
87
|
+
options.outgoingRequestHook?.(span, request);
|
|
88
|
+
|
|
89
|
+
// Inject trace headers after span creation so sentry-trace contains the
|
|
90
|
+
// outgoing span's ID (not the parent's), enabling downstream services to
|
|
91
|
+
// link to this span.
|
|
92
|
+
if (propagateTrace) {
|
|
93
|
+
if (span.isRecording()) {
|
|
94
|
+
trace.withActiveSpan(span, () => {
|
|
95
|
+
injectTracePropagationHeaders.injectTracePropagationHeaders(request, propagationDecisionMap);
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
injectTracePropagationHeaders.injectTracePropagationHeaders(request, propagationDecisionMap);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let spanEnded = false;
|
|
103
|
+
function endSpan(status) {
|
|
104
|
+
if (!spanEnded) {
|
|
105
|
+
spanEnded = true;
|
|
106
|
+
span.setStatus(status);
|
|
107
|
+
span.end();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Fallback: end span if the connection closes before any response.
|
|
112
|
+
// This is removed if we do get a response, because in that case
|
|
113
|
+
// we want to only end the span when the response is finished.
|
|
114
|
+
const requestOnClose = () => endSpan({ code: spanstatus.SPAN_STATUS_UNSET });
|
|
115
|
+
request.on('close', requestOnClose);
|
|
116
|
+
|
|
117
|
+
request.on(errorMonitor, error => {
|
|
118
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'outgoingRequest on request error()', error);
|
|
119
|
+
if (breadcrumbs) {
|
|
120
|
+
addBreadcrumbs(request, undefined);
|
|
121
|
+
}
|
|
122
|
+
endSpan({ code: spanstatus.SPAN_STATUS_ERROR });
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
request.prependListener('response', response => {
|
|
126
|
+
// no longer need this, listen on response now.
|
|
127
|
+
// do not end the span until the response finishes
|
|
128
|
+
request.removeListener('close', requestOnClose);
|
|
129
|
+
if (request.listenerCount('response') <= 1) {
|
|
130
|
+
response.resume();
|
|
131
|
+
}
|
|
132
|
+
getOutgoingSpanData.setIncomingResponseSpanData(response, span);
|
|
133
|
+
options.outgoingResponseHook?.(span, response);
|
|
134
|
+
|
|
135
|
+
let finished = false;
|
|
136
|
+
function finishWithResponse(error) {
|
|
137
|
+
if (!finished) {
|
|
138
|
+
finished = true;
|
|
139
|
+
if (error) {
|
|
140
|
+
debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'outgoingRequest on response error()', error);
|
|
141
|
+
}
|
|
142
|
+
if (breadcrumbs) {
|
|
143
|
+
addBreadcrumbs(request, response);
|
|
144
|
+
}
|
|
145
|
+
const aborted = response.aborted && !response.complete;
|
|
146
|
+
const status =
|
|
147
|
+
error || typeof response.statusCode !== 'number' || aborted
|
|
148
|
+
? { code: spanstatus.SPAN_STATUS_ERROR }
|
|
149
|
+
: spanstatus.getSpanStatusFromHttpCode(response.statusCode);
|
|
150
|
+
options.applyCustomAttributesOnSpan?.(span, request, response);
|
|
151
|
+
endSpan(status);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
response.on('end', () => finishWithResponse());
|
|
156
|
+
response.on(errorMonitor, finishWithResponse);
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
[constants.HTTP_ON_CLIENT_REQUEST]: onHttpClientRequestCreated,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
exports.getHttpClientSubscriptions = getHttpClientSubscriptions;
|
|
166
|
+
//# sourceMappingURL=client-subscriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-subscriptions.js","sources":["../../../../src/integrations/http/client-subscriptions.ts"],"sourcesContent":["/**\n * Define the channels and subscription methods to subscribe to in order to\n * instrument the `node:http` module. Note that this does *not* actually\n * register the subscriptions, it simply returns a data object with the\n * channel names and the subscription handlers. Attach these to diagnostic\n * channels on Node versions where they are supported (ie, >=22.12.0).\n *\n * If any other platforms that do support diagnostic channels eventually add\n * channel coverage for the `node:http` client, then these methods can be\n * used on those platforms as well.\n *\n * This implementation is used in the client-patch strategy, by simply\n * calling the handlers with the relevant data at the appropriate time.\n */\n\nimport type { SpanStatus } from '../../types-hoist/spanStatus';\nimport { addOutgoingRequestBreadcrumb } from './add-outgoing-request-breadcrumb';\nimport {\n getSpanStatusFromHttpCode,\n SPAN_STATUS_ERROR,\n SPAN_STATUS_UNSET,\n startInactiveSpan,\n SUPPRESS_TRACING_KEY,\n withActiveSpan,\n} from '../../tracing';\nimport { debug } from '../../utils/debug-logger';\nimport { LRUMap } from '../../utils/lru';\nimport { getOutgoingRequestSpanData, setIncomingResponseSpanData } from './get-outgoing-span-data';\nimport { getRequestUrlFromClientRequest } from './get-request-url';\nimport { injectTracePropagationHeaders } from './inject-trace-propagation-headers';\nimport type { HttpInstrumentationOptions, HttpClientRequest, HttpIncomingMessage } from './types';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { LOG_PREFIX, HTTP_ON_CLIENT_REQUEST } from './constants';\nimport type { ClientSubscriptionName } from './constants';\nimport { getClient, getCurrentScope } from '../../currentScopes';\nimport { hasSpansEnabled } from '../../utils/hasSpansEnabled';\nimport { doubleWrapWarning } from './double-wrap-warning';\n\ntype ChannelListener = (message: unknown, name: string | symbol) => void;\n\nexport type HttpClientSubscriptions = Record<ClientSubscriptionName, ChannelListener>;\n\nexport function getHttpClientSubscriptions(options: HttpInstrumentationOptions): HttpClientSubscriptions {\n const propagationDecisionMap = new LRUMap<string, boolean>(100);\n const getConfig = () => getClient()?.getOptions();\n\n const onHttpClientRequestCreated: ChannelListener = (data: unknown): void => {\n // Skip all instrumentation if tracing is suppressed\n // (e.g., Sentry's own transport uses this to avoid self-instrumentation)\n if (getCurrentScope().getScopeData().sdkProcessingMetadata[SUPPRESS_TRACING_KEY] === true) {\n return;\n }\n\n const clientOptions = getConfig();\n const {\n errorMonitor = 'error',\n spans: createSpans = clientOptions ? hasSpansEnabled(clientOptions) : true,\n propagateTrace = false,\n breadcrumbs = true,\n http,\n https,\n suppressOtelWarning = false,\n } = options;\n\n const { request } = data as { request: HttpClientRequest };\n\n // check if request is ignored. if so, we do nothing at all.\n if (options.ignoreOutgoingRequests?.(getRequestUrlFromClientRequest(request), request)) {\n return;\n }\n\n // guard against adding breadcrumbs multiple times, or when not enabled\n let addedBreadcrumbs = false;\n function addBreadcrumbs(request: HttpClientRequest, response: HttpIncomingMessage | undefined) {\n if (!addedBreadcrumbs) {\n addedBreadcrumbs = true;\n addOutgoingRequestBreadcrumb(request, response);\n }\n }\n\n // called if spans and/or trace propagation are disabled\n function breadcrumbsOnly(request: HttpClientRequest) {\n request.on(errorMonitor, () => addBreadcrumbs(request, undefined));\n request.prependListener('response', response => {\n if (request.listenerCount('response') <= 1) {\n response.resume();\n }\n response.on('end', () => addBreadcrumbs(request, response));\n response.on(errorMonitor, () => addBreadcrumbs(request, response));\n });\n }\n\n if (!createSpans) {\n // no spans, but maybe tracing and/or breadcrumbs\n if (breadcrumbs) {\n breadcrumbsOnly(request);\n }\n if (propagateTrace) {\n injectTracePropagationHeaders(request, propagationDecisionMap);\n }\n return;\n }\n\n // guard against OTel wrapping the same module and emitting double-spans\n // this doesn't prevent it, just prints a debug warning for the user.\n if (!suppressOtelWarning) {\n if (http) doubleWrapWarning(http);\n if (https) doubleWrapWarning(https);\n }\n\n // spans are enabled\n const span = startInactiveSpan(getOutgoingRequestSpanData(request));\n options.outgoingRequestHook?.(span, request);\n\n // Inject trace headers after span creation so sentry-trace contains the\n // outgoing span's ID (not the parent's), enabling downstream services to\n // link to this span.\n if (propagateTrace) {\n if (span.isRecording()) {\n withActiveSpan(span, () => {\n injectTracePropagationHeaders(request, propagationDecisionMap);\n });\n } else {\n injectTracePropagationHeaders(request, propagationDecisionMap);\n }\n }\n\n let spanEnded = false;\n function endSpan(status: SpanStatus): void {\n if (!spanEnded) {\n spanEnded = true;\n span.setStatus(status);\n span.end();\n }\n }\n\n // Fallback: end span if the connection closes before any response.\n // This is removed if we do get a response, because in that case\n // we want to only end the span when the response is finished.\n const requestOnClose = () => endSpan({ code: SPAN_STATUS_UNSET });\n request.on('close', requestOnClose);\n\n request.on(errorMonitor, error => {\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'outgoingRequest on request error()', error);\n if (breadcrumbs) {\n addBreadcrumbs(request, undefined);\n }\n endSpan({ code: SPAN_STATUS_ERROR });\n });\n\n request.prependListener('response', response => {\n // no longer need this, listen on response now.\n // do not end the span until the response finishes\n request.removeListener('close', requestOnClose);\n if (request.listenerCount('response') <= 1) {\n response.resume();\n }\n setIncomingResponseSpanData(response, span);\n options.outgoingResponseHook?.(span, response);\n\n let finished = false;\n function finishWithResponse(error?: unknown): void {\n if (!finished) {\n finished = true;\n if (error) {\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'outgoingRequest on response error()', error);\n }\n if (breadcrumbs) {\n addBreadcrumbs(request, response);\n }\n const aborted = response.aborted && !response.complete;\n const status: SpanStatus =\n error || typeof response.statusCode !== 'number' || aborted\n ? { code: SPAN_STATUS_ERROR }\n : getSpanStatusFromHttpCode(response.statusCode);\n options.applyCustomAttributesOnSpan?.(span, request, response);\n endSpan(status);\n }\n }\n\n response.on('end', () => finishWithResponse());\n response.on(errorMonitor, finishWithResponse);\n });\n };\n\n return {\n [HTTP_ON_CLIENT_REQUEST]: onHttpClientRequestCreated,\n };\n}\n"],"names":["LRUMap","getClient","getCurrentScope","SUPPRESS_TRACING_KEY","hasSpansEnabled","getRequestUrlFromClientRequest","addOutgoingRequestBreadcrumb","injectTracePropagationHeaders","doubleWrapWarning","startInactiveSpan","getOutgoingRequestSpanData","withActiveSpan","SPAN_STATUS_UNSET","DEBUG_BUILD","debug","LOG_PREFIX","SPAN_STATUS_ERROR","setIncomingResponseSpanData","getSpanStatusFromHttpCode","HTTP_ON_CLIENT_REQUEST"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const LOG_PREFIX = '@sentry/instrumentation-http';
|
|
4
|
+
const HTTP_ON_CLIENT_REQUEST = 'http.client.request.created';
|
|
5
|
+
const HTTP_ON_SERVER_REQUEST = 'http.server.request.start';
|
|
6
|
+
|
|
7
|
+
exports.HTTP_ON_CLIENT_REQUEST = HTTP_ON_CLIENT_REQUEST;
|
|
8
|
+
exports.HTTP_ON_SERVER_REQUEST = HTTP_ON_SERVER_REQUEST;
|
|
9
|
+
exports.LOG_PREFIX = LOG_PREFIX;
|
|
10
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../../src/integrations/http/constants.ts"],"sourcesContent":["export const LOG_PREFIX = '@sentry/instrumentation-http';\nexport const HTTP_ON_CLIENT_REQUEST = 'http.client.request.created';\nexport const HTTP_ON_SERVER_REQUEST = 'http.server.request.start';\nexport type ClientSubscriptionName = typeof HTTP_ON_CLIENT_REQUEST;\nexport type ServerSubscriptionName = typeof HTTP_ON_SERVER_REQUEST;\n"],"names":[],"mappings":";;AAAO,MAAM,UAAA,GAAa;AACnB,MAAM,sBAAA,GAAyB;AAC/B,MAAM,sBAAA,GAAyB;;;;;;"}
|