@sentry/core 10.50.0 → 10.51.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 +27 -3
- 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/index.js +10 -5
- 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/extraerrordata.js +2 -2
- package/build/cjs/integrations/extraerrordata.js.map +1 -1
- package/build/cjs/integrations/postgresjs.js +10 -1
- package/build/cjs/integrations/postgresjs.js.map +1 -1
- package/build/cjs/integrations/requestdata.js +9 -5
- 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/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 +125 -0
- 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 +1 -0
- package/build/cjs/tracing/trace.js.map +1 -1
- package/build/cjs/trpc.js +2 -3
- package/build/cjs/trpc.js.map +1 -1
- 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 +63 -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/version.js +1 -1
- package/build/esm/client.js +27 -3
- 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/index.js +3 -2
- 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/extraerrordata.js +2 -2
- package/build/esm/integrations/extraerrordata.js.map +1 -1
- package/build/esm/integrations/postgresjs.js +10 -1
- package/build/esm/integrations/postgresjs.js.map +1 -1
- package/build/esm/integrations/requestdata.js +9 -5
- 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/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 +126 -2
- 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 +1 -0
- package/build/esm/tracing/trace.js.map +1 -1
- package/build/esm/trpc.js +2 -3
- package/build/esm/trpc.js.map +1 -1
- 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 +63 -12
- 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/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/index.d.ts +4 -2
- 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/postgresjs.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/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/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 +10 -0
- 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/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/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/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.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-ts3.8/client.d.ts +12 -1
- package/build/types-ts3.8/index.d.ts +4 -2
- 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/server-runtime-client.d.ts +5 -0
- 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 +10 -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/options.d.ts +37 -2
- package/build/types-ts3.8/types-hoist/span.d.ts +5 -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/should-ignore-span.d.ts +3 -1
- package/package.json +1 -1
package/build/cjs/index.js
CHANGED
|
@@ -91,11 +91,11 @@ const index$6 = require('./tracing/openai/index.js');
|
|
|
91
91
|
const constants$5 = require('./tracing/openai/constants.js');
|
|
92
92
|
const index$3 = require('./tracing/anthropic-ai/index.js');
|
|
93
93
|
const constants = require('./tracing/anthropic-ai/constants.js');
|
|
94
|
-
const index$
|
|
94
|
+
const index$5 = require('./tracing/google-genai/index.js');
|
|
95
95
|
const constants$2 = require('./tracing/google-genai/constants.js');
|
|
96
96
|
const index$1 = require('./tracing/langchain/index.js');
|
|
97
97
|
const constants$3 = require('./tracing/langchain/constants.js');
|
|
98
|
-
const index$
|
|
98
|
+
const index$4 = require('./tracing/langgraph/index.js');
|
|
99
99
|
const constants$4 = require('./tracing/langgraph/constants.js');
|
|
100
100
|
const spanBuffer = require('./tracing/spans/spanBuffer.js');
|
|
101
101
|
const hasSpanStreamingEnabled = require('./tracing/spans/hasSpanStreamingEnabled.js');
|
|
@@ -118,6 +118,7 @@ const debugLogger = require('./utils/debug-logger.js');
|
|
|
118
118
|
const misc = require('./utils/misc.js');
|
|
119
119
|
const node = require('./utils/node.js');
|
|
120
120
|
const normalize = require('./utils/normalize.js');
|
|
121
|
+
const normalizationHints = require('./utils/normalizationHints.js');
|
|
121
122
|
const object = require('./utils/object.js');
|
|
122
123
|
const path = require('./utils/path.js');
|
|
123
124
|
const promisebuffer = require('./utils/promisebuffer.js');
|
|
@@ -181,6 +182,7 @@ exports.sampleSpan = sampling.sampleSpan;
|
|
|
181
182
|
exports.logSpanEnd = logSpans.logSpanEnd;
|
|
182
183
|
exports.logSpanStart = logSpans.logSpanStart;
|
|
183
184
|
exports.captureSpan = captureSpan.captureSpan;
|
|
185
|
+
exports.safeSetSpanJSONAttributes = captureSpan.safeSetSpanJSONAttributes;
|
|
184
186
|
exports.GEN_AI_CONVERSATION_ID_ATTRIBUTE = semanticAttributes.GEN_AI_CONVERSATION_ID_ATTRIBUTE;
|
|
185
187
|
exports.SEMANTIC_ATTRIBUTE_CACHE_HIT = semanticAttributes.SEMANTIC_ATTRIBUTE_CACHE_HIT;
|
|
186
188
|
exports.SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE = semanticAttributes.SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE;
|
|
@@ -366,12 +368,13 @@ exports.instrumentOpenAiClient = index$6.instrumentOpenAiClient;
|
|
|
366
368
|
exports.OPENAI_INTEGRATION_NAME = constants$5.OPENAI_INTEGRATION_NAME;
|
|
367
369
|
exports.instrumentAnthropicAiClient = index$3.instrumentAnthropicAiClient;
|
|
368
370
|
exports.ANTHROPIC_AI_INTEGRATION_NAME = constants.ANTHROPIC_AI_INTEGRATION_NAME;
|
|
369
|
-
exports.instrumentGoogleGenAIClient = index$
|
|
371
|
+
exports.instrumentGoogleGenAIClient = index$5.instrumentGoogleGenAIClient;
|
|
370
372
|
exports.GOOGLE_GENAI_INTEGRATION_NAME = constants$2.GOOGLE_GENAI_INTEGRATION_NAME;
|
|
371
373
|
exports.createLangChainCallbackHandler = index$1.createLangChainCallbackHandler;
|
|
372
374
|
exports.LANGCHAIN_INTEGRATION_NAME = constants$3.LANGCHAIN_INTEGRATION_NAME;
|
|
373
|
-
exports.
|
|
374
|
-
exports.
|
|
375
|
+
exports.instrumentCreateReactAgent = index$4.instrumentCreateReactAgent;
|
|
376
|
+
exports.instrumentLangGraph = index$4.instrumentLangGraph;
|
|
377
|
+
exports.instrumentStateGraphCompile = index$4.instrumentStateGraphCompile;
|
|
375
378
|
exports.LANGGRAPH_INTEGRATION_NAME = constants$4.LANGGRAPH_INTEGRATION_NAME;
|
|
376
379
|
exports.SpanBuffer = spanBuffer.SpanBuffer;
|
|
377
380
|
exports.hasSpanStreamingEnabled = hasSpanStreamingEnabled.hasSpanStreamingEnabled;
|
|
@@ -433,6 +436,8 @@ exports.loadModule = node.loadModule;
|
|
|
433
436
|
exports.normalize = normalize.normalize;
|
|
434
437
|
exports.normalizeToSize = normalize.normalizeToSize;
|
|
435
438
|
exports.normalizeUrlToBase = normalize.normalizeUrlToBase;
|
|
439
|
+
exports.setNormalizationDepthOverrideHint = normalizationHints.setNormalizationDepthOverrideHint;
|
|
440
|
+
exports.setSkipNormalizationHint = normalizationHints.setSkipNormalizationHint;
|
|
436
441
|
exports.addNonEnumerableProperty = object.addNonEnumerableProperty;
|
|
437
442
|
exports.convertToPlainObject = object.convertToPlainObject;
|
|
438
443
|
exports.dropUndefinedKeys = object.dropUndefinedKeys;
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -7,14 +7,16 @@ const handlers = require('./handlers.js');
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Add an instrumentation handler for when a console.xxx method is called.
|
|
10
|
+
* Returns a function to remove the handler.
|
|
10
11
|
*
|
|
11
12
|
* Use at your own risk, this might break without changelog notice, only used internally.
|
|
12
13
|
* @hidden
|
|
13
14
|
*/
|
|
14
15
|
function addConsoleInstrumentationHandler(handler) {
|
|
15
16
|
const type = 'console';
|
|
16
|
-
handlers.addHandler(type, handler);
|
|
17
|
+
const removeHandler = handlers.addHandler(type, handler);
|
|
17
18
|
handlers.maybeInstrument(type, instrumentConsole);
|
|
19
|
+
return removeHandler;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function instrumentConsole() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.js","sources":["../../../src/instrument/console.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/ban-types */\nimport type { ConsoleLevel, HandlerDataConsole } from '../types-hoist/instrument';\nimport { CONSOLE_LEVELS, originalConsoleMethods } from '../utils/debug-logger';\nimport { fill } from '../utils/object';\nimport { GLOBAL_OBJ } from '../utils/worldwide';\nimport { addHandler, maybeInstrument, triggerHandlers } from './handlers';\n\n/**\n * Add an instrumentation handler for when a console.xxx method is called.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addConsoleInstrumentationHandler(handler: (data: HandlerDataConsole) => void): void {\n const type = 'console';\n addHandler(type, handler);\n maybeInstrument(type, instrumentConsole);\n}\n\nfunction instrumentConsole(): void {\n if (!('console' in GLOBAL_OBJ)) {\n return;\n }\n\n CONSOLE_LEVELS.forEach(function (level: ConsoleLevel): void {\n if (!(level in GLOBAL_OBJ.console)) {\n return;\n }\n\n fill(GLOBAL_OBJ.console, level, function (originalConsoleMethod: () => any): Function {\n originalConsoleMethods[level] = originalConsoleMethod;\n\n return function (...args: any[]): void {\n triggerHandlers('console', { args, level } as HandlerDataConsole);\n\n const log = originalConsoleMethods[level];\n log?.apply(GLOBAL_OBJ.console, args);\n };\n });\n });\n}\n"],"names":["addHandler","maybeInstrument","GLOBAL_OBJ","CONSOLE_LEVELS","fill","originalConsoleMethods","triggerHandlers"],"mappings":";;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"console.js","sources":["../../../src/instrument/console.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/ban-types */\nimport type { ConsoleLevel, HandlerDataConsole } from '../types-hoist/instrument';\nimport { CONSOLE_LEVELS, originalConsoleMethods } from '../utils/debug-logger';\nimport { fill } from '../utils/object';\nimport { GLOBAL_OBJ } from '../utils/worldwide';\nimport { addHandler, maybeInstrument, triggerHandlers } from './handlers';\n\n/**\n * Add an instrumentation handler for when a console.xxx method is called.\n * Returns a function to remove the handler.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addConsoleInstrumentationHandler(handler: (data: HandlerDataConsole) => void): () => void {\n const type = 'console';\n const removeHandler = addHandler(type, handler);\n maybeInstrument(type, instrumentConsole);\n return removeHandler;\n}\n\nfunction instrumentConsole(): void {\n if (!('console' in GLOBAL_OBJ)) {\n return;\n }\n\n CONSOLE_LEVELS.forEach(function (level: ConsoleLevel): void {\n if (!(level in GLOBAL_OBJ.console)) {\n return;\n }\n\n fill(GLOBAL_OBJ.console, level, function (originalConsoleMethod: () => any): Function {\n originalConsoleMethods[level] = originalConsoleMethod;\n\n return function (...args: any[]): void {\n triggerHandlers('console', { args, level } as HandlerDataConsole);\n\n const log = originalConsoleMethods[level];\n log?.apply(GLOBAL_OBJ.console, args);\n };\n });\n });\n}\n"],"names":["addHandler","maybeInstrument","GLOBAL_OBJ","CONSOLE_LEVELS","fill","originalConsoleMethods","triggerHandlers"],"mappings":";;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,CAAC,OAAO,EAAkD;AAC1G,EAAE,MAAM,IAAA,GAAO,SAAS;AACxB,EAAE,MAAM,gBAAgBA,mBAAU,CAAC,IAAI,EAAE,OAAO,CAAC;AACjD,EAAEC,wBAAe,CAAC,IAAI,EAAE,iBAAiB,CAAC;AAC1C,EAAE,OAAO,aAAa;AACtB;;AAEA,SAAS,iBAAiB,GAAS;AACnC,EAAE,IAAI,EAAE,aAAaC,oBAAU,CAAC,EAAE;AAClC,IAAI;AACJ,EAAE;;AAEF,EAAEC,0BAAc,CAAC,OAAO,CAAC,UAAU,KAAK,EAAsB;AAC9D,IAAI,IAAI,EAAE,KAAA,IAASD,oBAAU,CAAC,OAAO,CAAC,EAAE;AACxC,MAAM;AACN,IAAI;;AAEJ,IAAIE,WAAI,CAACF,oBAAU,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,qBAAqB,EAAuB;AAC1F,MAAMG,kCAAsB,CAAC,KAAK,CAAA,GAAI,qBAAqB;;AAE3D,MAAM,OAAO,UAAU,GAAG,IAAI,EAAe;AAC7C,QAAQC,wBAAe,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAA,EAAM,EAAwB;;AAEzE,QAAQ,MAAM,GAAA,GAAMD,kCAAsB,CAAC,KAAK,CAAC;AACjD,QAAQ,GAAG,EAAE,KAAK,CAACH,oBAAU,CAAC,OAAO,EAAE,IAAI,CAAC;AAC5C,MAAM,CAAC;AACP,IAAI,CAAC,CAAC;AACN,EAAE,CAAC,CAAC;AACJ;;;;"}
|
|
@@ -14,6 +14,7 @@ const handlers = require('./handlers.js');
|
|
|
14
14
|
* Add an instrumentation handler for when a fetch request happens.
|
|
15
15
|
* The handler function is called once when the request starts and once when it ends,
|
|
16
16
|
* which can be identified by checking if it has an `endTimestamp`.
|
|
17
|
+
* Returns a function to remove the handler.
|
|
17
18
|
*
|
|
18
19
|
* Use at your own risk, this might break without changelog notice, only used internally.
|
|
19
20
|
* @hidden
|
|
@@ -23,22 +24,25 @@ function addFetchInstrumentationHandler(
|
|
|
23
24
|
skipNativeFetchCheck,
|
|
24
25
|
) {
|
|
25
26
|
const type = 'fetch';
|
|
26
|
-
handlers.addHandler(type, handler);
|
|
27
|
+
const removeHandler = handlers.addHandler(type, handler);
|
|
27
28
|
handlers.maybeInstrument(type, () => instrumentFetch(undefined, skipNativeFetchCheck));
|
|
29
|
+
return removeHandler;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Add an instrumentation handler for long-lived fetch requests, like consuming server-sent events (SSE) via fetch.
|
|
32
34
|
* The handler will resolve the request body and emit the actual `endTimestamp`, so that the
|
|
33
35
|
* span can be updated accordingly.
|
|
36
|
+
* Returns a function to remove the handler.
|
|
34
37
|
*
|
|
35
38
|
* Only used internally
|
|
36
39
|
* @hidden
|
|
37
40
|
*/
|
|
38
41
|
function addFetchEndInstrumentationHandler(handler) {
|
|
39
42
|
const type = 'fetch-body-resolved';
|
|
40
|
-
handlers.addHandler(type, handler);
|
|
43
|
+
const removeHandler = handlers.addHandler(type, handler);
|
|
41
44
|
handlers.maybeInstrument(type, () => instrumentFetch(streamHandler));
|
|
45
|
+
return removeHandler;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
function instrumentFetch(onFetchResolved, skipNativeFetchCheck = false) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sources":["../../../src/instrument/fetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { getClient } from '../currentScopes';\nimport type { HandlerDataFetch } from '../types-hoist/instrument';\nimport type { WebFetchHeaders } from '../types-hoist/webfetchapi';\nimport { isError, isRequest } from '../utils/is';\nimport { addNonEnumerableProperty, fill } from '../utils/object';\nimport { supportsNativeFetch } from '../utils/supports';\nimport { timestampInSeconds } from '../utils/time';\nimport { GLOBAL_OBJ } from '../utils/worldwide';\nimport { addHandler, maybeInstrument, triggerHandlers } from './handlers';\n\ntype FetchResource = string | { toString(): string } | { url: string };\n\n/**\n * Add an instrumentation handler for when a fetch request happens.\n * The handler function is called once when the request starts and once when it ends,\n * which can be identified by checking if it has an `endTimestamp`.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addFetchInstrumentationHandler(\n handler: (data: HandlerDataFetch) => void,\n skipNativeFetchCheck?: boolean,\n): void {\n const type = 'fetch';\n addHandler(type, handler);\n maybeInstrument(type, () => instrumentFetch(undefined, skipNativeFetchCheck));\n}\n\n/**\n * Add an instrumentation handler for long-lived fetch requests, like consuming server-sent events (SSE) via fetch.\n * The handler will resolve the request body and emit the actual `endTimestamp`, so that the\n * span can be updated accordingly.\n *\n * Only used internally\n * @hidden\n */\nexport function addFetchEndInstrumentationHandler(handler: (data: HandlerDataFetch) => void): void {\n const type = 'fetch-body-resolved';\n addHandler(type, handler);\n maybeInstrument(type, () => instrumentFetch(streamHandler));\n}\n\nfunction instrumentFetch(onFetchResolved?: (response: Response) => void, skipNativeFetchCheck: boolean = false): void {\n if (skipNativeFetchCheck && !supportsNativeFetch()) {\n return;\n }\n\n fill(GLOBAL_OBJ, 'fetch', function (originalFetch: () => void): () => void {\n return function (...args: any[]): void {\n // We capture the error right here and not in the Promise error callback because Safari (and probably other\n // browsers too) will wipe the stack trace up to this point, only leaving us with this file which is useless.\n\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your fetch call did not\n // have a stack trace, so the SDK backfilled the stack trace so\n // you can see which fetch call failed.\n const virtualError = new Error();\n\n const { method, url } = parseFetchArgs(args);\n const handlerData: HandlerDataFetch = {\n args,\n fetchData: {\n method,\n url,\n },\n startTimestamp: timestampInSeconds() * 1000,\n // // Adding the error to be able to fingerprint the failed fetch event in HttpClient instrumentation\n virtualError,\n headers: getHeadersFromFetchArgs(args),\n };\n\n // if there is no callback, fetch is instrumented directly\n if (!onFetchResolved) {\n triggerHandlers('fetch', {\n ...handlerData,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return originalFetch.apply(GLOBAL_OBJ, args).then(\n async (response: Response) => {\n if (onFetchResolved) {\n onFetchResolved(response);\n } else {\n triggerHandlers('fetch', {\n ...handlerData,\n endTimestamp: timestampInSeconds() * 1000,\n response,\n });\n }\n\n return response;\n },\n (error: Error) => {\n triggerHandlers('fetch', {\n ...handlerData,\n endTimestamp: timestampInSeconds() * 1000,\n error,\n });\n\n if (isError(error) && error.stack === undefined) {\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your fetch call did not\n // have a stack trace, so the SDK backfilled the stack trace so\n // you can see which fetch call failed.\n error.stack = virtualError.stack;\n addNonEnumerableProperty(error, 'framesToPop', 1);\n }\n\n // We enhance fetch error messages with hostname information based on the configuration.\n // Possible messages we handle here:\n // * \"Failed to fetch\" (chromium)\n // * \"Load failed\" (webkit)\n // * \"NetworkError when attempting to fetch resource.\" (firefox)\n const client = getClient();\n const enhanceOption = client?.getOptions().enhanceFetchErrorMessages ?? 'always';\n const shouldEnhance = enhanceOption !== false;\n\n if (\n shouldEnhance &&\n error instanceof TypeError &&\n (error.message === 'Failed to fetch' ||\n error.message === 'Load failed' ||\n error.message === 'NetworkError when attempting to fetch resource.')\n ) {\n try {\n const url = new URL(handlerData.fetchData.url);\n const hostname = url.host;\n\n if (enhanceOption === 'always') {\n // Modify the error message directly\n error.message = `${error.message} (${hostname})`;\n } else {\n // Store hostname as non-enumerable property for Sentry-only enhancement\n // This preserves the original error message for third-party packages\n addNonEnumerableProperty(error, '__sentry_fetch_url_host__', hostname);\n }\n } catch {\n // ignore it if errors happen here\n }\n }\n\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the sentry.javascript SDK caught an error invoking your application code.\n // This is expected behavior and NOT indicative of a bug with sentry.javascript.\n throw error;\n },\n );\n };\n });\n}\n\nasync function resolveResponse(res: Response | undefined, onFinishedResolving: () => void): Promise<void> {\n if (res?.body) {\n const body = res.body;\n const responseReader = body.getReader();\n\n // Define a maximum duration after which we just cancel\n const maxFetchDurationTimeout = setTimeout(\n () => {\n body.cancel().then(null, () => {\n // noop\n });\n },\n 90 * 1000, // 90s\n );\n\n let readingActive = true;\n while (readingActive) {\n let chunkTimeout;\n try {\n // abort reading if read op takes more than 5s\n chunkTimeout = setTimeout(() => {\n body.cancel().then(null, () => {\n // noop on error\n });\n }, 5000);\n\n // This .read() call will reject/throw when we abort due to timeouts through `body.cancel()`\n const { done } = await responseReader.read();\n\n clearTimeout(chunkTimeout);\n\n if (done) {\n onFinishedResolving();\n readingActive = false;\n }\n } catch {\n readingActive = false;\n } finally {\n clearTimeout(chunkTimeout);\n }\n }\n\n clearTimeout(maxFetchDurationTimeout);\n\n responseReader.releaseLock();\n body.cancel().then(null, () => {\n // noop on error\n });\n }\n}\n\nfunction streamHandler(response: Response): void {\n // clone response for awaiting stream\n let clonedResponseForResolving: Response;\n try {\n clonedResponseForResolving = response.clone();\n } catch {\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n resolveResponse(clonedResponseForResolving, () => {\n triggerHandlers('fetch-body-resolved', {\n endTimestamp: timestampInSeconds() * 1000,\n response,\n });\n });\n}\n\nfunction hasProp<T extends string>(obj: unknown, prop: T): obj is Record<string, string> {\n return !!obj && typeof obj === 'object' && !!(obj as Record<string, string>)[prop];\n}\n\nfunction getUrlFromResource(resource: FetchResource): string {\n if (typeof resource === 'string') {\n return resource;\n }\n\n if (!resource) {\n return '';\n }\n\n if (hasProp(resource, 'url')) {\n return resource.url;\n }\n\n if (resource.toString) {\n return resource.toString();\n }\n\n return '';\n}\n\n/**\n * Parses the fetch arguments to find the used Http method and the url of the request.\n * Exported for tests only.\n */\nexport function parseFetchArgs(fetchArgs: unknown[]): { method: string; url: string } {\n if (fetchArgs.length === 0) {\n return { method: 'GET', url: '' };\n }\n\n if (fetchArgs.length === 2) {\n const [resource, options] = fetchArgs as [FetchResource, object];\n\n return {\n url: getUrlFromResource(resource),\n method: hasProp(options, 'method')\n ? String(options.method).toUpperCase()\n : // Request object as first argument\n isRequest(resource) && hasProp(resource, 'method')\n ? String(resource.method).toUpperCase()\n : 'GET',\n };\n }\n\n const arg = fetchArgs[0];\n return {\n url: getUrlFromResource(arg as FetchResource),\n method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',\n };\n}\n\nfunction getHeadersFromFetchArgs(fetchArgs: unknown[]): WebFetchHeaders | undefined {\n const [requestArgument, optionsArgument] = fetchArgs;\n\n try {\n if (\n typeof optionsArgument === 'object' &&\n optionsArgument !== null &&\n 'headers' in optionsArgument &&\n optionsArgument.headers\n ) {\n return new Headers(optionsArgument.headers as any);\n }\n\n if (isRequest(requestArgument)) {\n return new Headers(requestArgument.headers);\n }\n } catch {\n // noop\n }\n\n return;\n}\n"],"names":["addHandler","maybeInstrument","supportsNativeFetch","fill","GLOBAL_OBJ","timestampInSeconds","triggerHandlers","isError","addNonEnumerableProperty","getClient","isRequest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetch.js","sources":["../../../src/instrument/fetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { getClient } from '../currentScopes';\nimport type { HandlerDataFetch } from '../types-hoist/instrument';\nimport type { WebFetchHeaders } from '../types-hoist/webfetchapi';\nimport { isError, isRequest } from '../utils/is';\nimport { addNonEnumerableProperty, fill } from '../utils/object';\nimport { supportsNativeFetch } from '../utils/supports';\nimport { timestampInSeconds } from '../utils/time';\nimport { GLOBAL_OBJ } from '../utils/worldwide';\nimport { addHandler, maybeInstrument, triggerHandlers } from './handlers';\n\ntype FetchResource = string | { toString(): string } | { url: string };\n\n/**\n * Add an instrumentation handler for when a fetch request happens.\n * The handler function is called once when the request starts and once when it ends,\n * which can be identified by checking if it has an `endTimestamp`.\n * Returns a function to remove the handler.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addFetchInstrumentationHandler(\n handler: (data: HandlerDataFetch) => void,\n skipNativeFetchCheck?: boolean,\n): () => void {\n const type = 'fetch';\n const removeHandler = addHandler(type, handler);\n maybeInstrument(type, () => instrumentFetch(undefined, skipNativeFetchCheck));\n return removeHandler;\n}\n\n/**\n * Add an instrumentation handler for long-lived fetch requests, like consuming server-sent events (SSE) via fetch.\n * The handler will resolve the request body and emit the actual `endTimestamp`, so that the\n * span can be updated accordingly.\n * Returns a function to remove the handler.\n *\n * Only used internally\n * @hidden\n */\nexport function addFetchEndInstrumentationHandler(handler: (data: HandlerDataFetch) => void): () => void {\n const type = 'fetch-body-resolved';\n const removeHandler = addHandler(type, handler);\n maybeInstrument(type, () => instrumentFetch(streamHandler));\n return removeHandler;\n}\n\nfunction instrumentFetch(onFetchResolved?: (response: Response) => void, skipNativeFetchCheck: boolean = false): void {\n if (skipNativeFetchCheck && !supportsNativeFetch()) {\n return;\n }\n\n fill(GLOBAL_OBJ, 'fetch', function (originalFetch: () => void): () => void {\n return function (...args: any[]): void {\n // We capture the error right here and not in the Promise error callback because Safari (and probably other\n // browsers too) will wipe the stack trace up to this point, only leaving us with this file which is useless.\n\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your fetch call did not\n // have a stack trace, so the SDK backfilled the stack trace so\n // you can see which fetch call failed.\n const virtualError = new Error();\n\n const { method, url } = parseFetchArgs(args);\n const handlerData: HandlerDataFetch = {\n args,\n fetchData: {\n method,\n url,\n },\n startTimestamp: timestampInSeconds() * 1000,\n // // Adding the error to be able to fingerprint the failed fetch event in HttpClient instrumentation\n virtualError,\n headers: getHeadersFromFetchArgs(args),\n };\n\n // if there is no callback, fetch is instrumented directly\n if (!onFetchResolved) {\n triggerHandlers('fetch', {\n ...handlerData,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return originalFetch.apply(GLOBAL_OBJ, args).then(\n async (response: Response) => {\n if (onFetchResolved) {\n onFetchResolved(response);\n } else {\n triggerHandlers('fetch', {\n ...handlerData,\n endTimestamp: timestampInSeconds() * 1000,\n response,\n });\n }\n\n return response;\n },\n (error: Error) => {\n triggerHandlers('fetch', {\n ...handlerData,\n endTimestamp: timestampInSeconds() * 1000,\n error,\n });\n\n if (isError(error) && error.stack === undefined) {\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your fetch call did not\n // have a stack trace, so the SDK backfilled the stack trace so\n // you can see which fetch call failed.\n error.stack = virtualError.stack;\n addNonEnumerableProperty(error, 'framesToPop', 1);\n }\n\n // We enhance fetch error messages with hostname information based on the configuration.\n // Possible messages we handle here:\n // * \"Failed to fetch\" (chromium)\n // * \"Load failed\" (webkit)\n // * \"NetworkError when attempting to fetch resource.\" (firefox)\n const client = getClient();\n const enhanceOption = client?.getOptions().enhanceFetchErrorMessages ?? 'always';\n const shouldEnhance = enhanceOption !== false;\n\n if (\n shouldEnhance &&\n error instanceof TypeError &&\n (error.message === 'Failed to fetch' ||\n error.message === 'Load failed' ||\n error.message === 'NetworkError when attempting to fetch resource.')\n ) {\n try {\n const url = new URL(handlerData.fetchData.url);\n const hostname = url.host;\n\n if (enhanceOption === 'always') {\n // Modify the error message directly\n error.message = `${error.message} (${hostname})`;\n } else {\n // Store hostname as non-enumerable property for Sentry-only enhancement\n // This preserves the original error message for third-party packages\n addNonEnumerableProperty(error, '__sentry_fetch_url_host__', hostname);\n }\n } catch {\n // ignore it if errors happen here\n }\n }\n\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the sentry.javascript SDK caught an error invoking your application code.\n // This is expected behavior and NOT indicative of a bug with sentry.javascript.\n throw error;\n },\n );\n };\n });\n}\n\nasync function resolveResponse(res: Response | undefined, onFinishedResolving: () => void): Promise<void> {\n if (res?.body) {\n const body = res.body;\n const responseReader = body.getReader();\n\n // Define a maximum duration after which we just cancel\n const maxFetchDurationTimeout = setTimeout(\n () => {\n body.cancel().then(null, () => {\n // noop\n });\n },\n 90 * 1000, // 90s\n );\n\n let readingActive = true;\n while (readingActive) {\n let chunkTimeout;\n try {\n // abort reading if read op takes more than 5s\n chunkTimeout = setTimeout(() => {\n body.cancel().then(null, () => {\n // noop on error\n });\n }, 5000);\n\n // This .read() call will reject/throw when we abort due to timeouts through `body.cancel()`\n const { done } = await responseReader.read();\n\n clearTimeout(chunkTimeout);\n\n if (done) {\n onFinishedResolving();\n readingActive = false;\n }\n } catch {\n readingActive = false;\n } finally {\n clearTimeout(chunkTimeout);\n }\n }\n\n clearTimeout(maxFetchDurationTimeout);\n\n responseReader.releaseLock();\n body.cancel().then(null, () => {\n // noop on error\n });\n }\n}\n\nfunction streamHandler(response: Response): void {\n // clone response for awaiting stream\n let clonedResponseForResolving: Response;\n try {\n clonedResponseForResolving = response.clone();\n } catch {\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n resolveResponse(clonedResponseForResolving, () => {\n triggerHandlers('fetch-body-resolved', {\n endTimestamp: timestampInSeconds() * 1000,\n response,\n });\n });\n}\n\nfunction hasProp<T extends string>(obj: unknown, prop: T): obj is Record<string, string> {\n return !!obj && typeof obj === 'object' && !!(obj as Record<string, string>)[prop];\n}\n\nfunction getUrlFromResource(resource: FetchResource): string {\n if (typeof resource === 'string') {\n return resource;\n }\n\n if (!resource) {\n return '';\n }\n\n if (hasProp(resource, 'url')) {\n return resource.url;\n }\n\n if (resource.toString) {\n return resource.toString();\n }\n\n return '';\n}\n\n/**\n * Parses the fetch arguments to find the used Http method and the url of the request.\n * Exported for tests only.\n */\nexport function parseFetchArgs(fetchArgs: unknown[]): { method: string; url: string } {\n if (fetchArgs.length === 0) {\n return { method: 'GET', url: '' };\n }\n\n if (fetchArgs.length === 2) {\n const [resource, options] = fetchArgs as [FetchResource, object];\n\n return {\n url: getUrlFromResource(resource),\n method: hasProp(options, 'method')\n ? String(options.method).toUpperCase()\n : // Request object as first argument\n isRequest(resource) && hasProp(resource, 'method')\n ? String(resource.method).toUpperCase()\n : 'GET',\n };\n }\n\n const arg = fetchArgs[0];\n return {\n url: getUrlFromResource(arg as FetchResource),\n method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',\n };\n}\n\nfunction getHeadersFromFetchArgs(fetchArgs: unknown[]): WebFetchHeaders | undefined {\n const [requestArgument, optionsArgument] = fetchArgs;\n\n try {\n if (\n typeof optionsArgument === 'object' &&\n optionsArgument !== null &&\n 'headers' in optionsArgument &&\n optionsArgument.headers\n ) {\n return new Headers(optionsArgument.headers as any);\n }\n\n if (isRequest(requestArgument)) {\n return new Headers(requestArgument.headers);\n }\n } catch {\n // noop\n }\n\n return;\n}\n"],"names":["addHandler","maybeInstrument","supportsNativeFetch","fill","GLOBAL_OBJ","timestampInSeconds","triggerHandlers","isError","addNonEnumerableProperty","getClient","isRequest"],"mappings":"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"}
|
|
@@ -8,10 +8,20 @@ const stacktrace = require('../utils/stacktrace.js');
|
|
|
8
8
|
const handlers = {};
|
|
9
9
|
const instrumented = {};
|
|
10
10
|
|
|
11
|
-
/** Add a handler function. */
|
|
11
|
+
/** Add a handler function. Returns a function to remove the handler. */
|
|
12
12
|
function addHandler(type, handler) {
|
|
13
13
|
handlers[type] = handlers[type] || [];
|
|
14
14
|
handlers[type].push(handler);
|
|
15
|
+
|
|
16
|
+
return () => {
|
|
17
|
+
const typeHandlers = handlers[type];
|
|
18
|
+
if (typeHandlers) {
|
|
19
|
+
const index = typeHandlers.indexOf(handler);
|
|
20
|
+
if (index !== -1) {
|
|
21
|
+
typeHandlers.splice(index, 1);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sources":["../../../src/instrument/handlers.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport { debug } from '../utils/debug-logger';\nimport { getFunctionName } from '../utils/stacktrace';\n\nexport type InstrumentHandlerType =\n | 'console'\n | 'dom'\n | 'fetch'\n | 'fetch-body-resolved'\n | 'history'\n | 'xhr'\n | 'error'\n | 'unhandledrejection';\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type InstrumentHandlerCallback = (data: any) => void;\n\n// We keep the handlers globally\nconst handlers: { [key in InstrumentHandlerType]?: InstrumentHandlerCallback[] } = {};\nconst instrumented: { [key in InstrumentHandlerType]?: boolean } = {};\n\n/** Add a handler function. */\nexport function addHandler(type: InstrumentHandlerType, handler: InstrumentHandlerCallback): void {\n handlers[type] = handlers[type] || [];\n handlers[type].push(handler);\n}\n\n/**\n * Reset all instrumentation handlers.\n * This can be used by tests to ensure we have a clean slate of instrumentation handlers.\n */\nexport function resetInstrumentationHandlers(): void {\n Object.keys(handlers).forEach(key => {\n handlers[key as InstrumentHandlerType] = undefined;\n });\n}\n\n/** Maybe run an instrumentation function, unless it was already called. */\nexport function maybeInstrument(type: InstrumentHandlerType, instrumentFn: () => void): void {\n if (!instrumented[type]) {\n instrumented[type] = true;\n try {\n instrumentFn();\n } catch (e) {\n DEBUG_BUILD && debug.error(`Error while instrumenting ${type}`, e);\n }\n }\n}\n\n/** Trigger handlers for a given instrumentation type. */\nexport function triggerHandlers(type: InstrumentHandlerType, data: unknown): void {\n const typeHandlers = type && handlers[type];\n if (!typeHandlers) {\n return;\n }\n\n for (const handler of typeHandlers) {\n try {\n handler(data);\n } catch (e) {\n DEBUG_BUILD &&\n debug.error(\n `Error while triggering instrumentation handler.\\nType: ${type}\\nName: ${getFunctionName(handler)}\\nError:`,\n e,\n );\n }\n }\n}\n"],"names":["DEBUG_BUILD","debug","getFunctionName"],"mappings":";;;;;;AAgBA;AACA,MAAM,QAAQ,GAAqE,EAAE;AACrF,MAAM,YAAY,GAAiD,EAAE;;AAErE;AACO,SAAS,UAAU,CAAC,IAAI,EAAyB,OAAO,
|
|
1
|
+
{"version":3,"file":"handlers.js","sources":["../../../src/instrument/handlers.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../debug-build';\nimport { debug } from '../utils/debug-logger';\nimport { getFunctionName } from '../utils/stacktrace';\n\nexport type InstrumentHandlerType =\n | 'console'\n | 'dom'\n | 'fetch'\n | 'fetch-body-resolved'\n | 'history'\n | 'xhr'\n | 'error'\n | 'unhandledrejection';\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type InstrumentHandlerCallback = (data: any) => void;\n\n// We keep the handlers globally\nconst handlers: { [key in InstrumentHandlerType]?: InstrumentHandlerCallback[] } = {};\nconst instrumented: { [key in InstrumentHandlerType]?: boolean } = {};\n\n/** Add a handler function. Returns a function to remove the handler. */\nexport function addHandler(type: InstrumentHandlerType, handler: InstrumentHandlerCallback): () => void {\n handlers[type] = handlers[type] || [];\n handlers[type].push(handler);\n\n return () => {\n const typeHandlers = handlers[type];\n if (typeHandlers) {\n const index = typeHandlers.indexOf(handler);\n if (index !== -1) {\n typeHandlers.splice(index, 1);\n }\n }\n };\n}\n\n/**\n * Reset all instrumentation handlers.\n * This can be used by tests to ensure we have a clean slate of instrumentation handlers.\n */\nexport function resetInstrumentationHandlers(): void {\n Object.keys(handlers).forEach(key => {\n handlers[key as InstrumentHandlerType] = undefined;\n });\n}\n\n/** Maybe run an instrumentation function, unless it was already called. */\nexport function maybeInstrument(type: InstrumentHandlerType, instrumentFn: () => void): void {\n if (!instrumented[type]) {\n instrumented[type] = true;\n try {\n instrumentFn();\n } catch (e) {\n DEBUG_BUILD && debug.error(`Error while instrumenting ${type}`, e);\n }\n }\n}\n\n/** Trigger handlers for a given instrumentation type. */\nexport function triggerHandlers(type: InstrumentHandlerType, data: unknown): void {\n const typeHandlers = type && handlers[type];\n if (!typeHandlers) {\n return;\n }\n\n for (const handler of typeHandlers) {\n try {\n handler(data);\n } catch (e) {\n DEBUG_BUILD &&\n debug.error(\n `Error while triggering instrumentation handler.\\nType: ${type}\\nName: ${getFunctionName(handler)}\\nError:`,\n e,\n );\n }\n }\n}\n"],"names":["DEBUG_BUILD","debug","getFunctionName"],"mappings":";;;;;;AAgBA;AACA,MAAM,QAAQ,GAAqE,EAAE;AACrF,MAAM,YAAY,GAAiD,EAAE;;AAErE;AACO,SAAS,UAAU,CAAC,IAAI,EAAyB,OAAO,EAAyC;AACxG,EAAE,QAAQ,CAAC,IAAI,CAAA,GAAI,QAAQ,CAAC,IAAI,CAAA,IAAK,EAAE;AACvC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;;AAE9B,EAAE,OAAO,MAAM;AACf,IAAI,MAAM,YAAA,GAAe,QAAQ,CAAC,IAAI,CAAC;AACvC,IAAI,IAAI,YAAY,EAAE;AACtB,MAAM,MAAM,QAAQ,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC;AACjD,MAAM,IAAI,KAAA,KAAU,EAAE,EAAE;AACxB,QAAQ,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AACrC,MAAM;AACN,IAAI;AACJ,EAAE,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,4BAA4B,GAAS;AACrD,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAA,IAAO;AACvC,IAAI,QAAQ,CAAC,GAAA,EAAI,GAA4B,SAAS;AACtD,EAAE,CAAC,CAAC;AACJ;;AAEA;AACO,SAAS,eAAe,CAAC,IAAI,EAAyB,YAAY,EAAoB;AAC7F,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE;AAC3B,IAAI,YAAY,CAAC,IAAI,CAAA,GAAI,IAAI;AAC7B,IAAI,IAAI;AACR,MAAM,YAAY,EAAE;AACpB,IAAI,CAAA,CAAE,OAAO,CAAC,EAAE;AAChB,MAAMA,sBAAA,IAAeC,iBAAK,CAAC,KAAK,CAAC,CAAC,0BAA0B,EAAE,IAAI,CAAC,CAAA,EAAA,CAAA,CAAA;AACA,IAAA;AACA,EAAA;AACA;;AAEA;AACA,SAAA,eAAA,CAAA,IAAA,EAAA,IAAA,EAAA;AACA,EAAA,MAAA,YAAA,GAAA,IAAA,IAAA,QAAA,CAAA,IAAA,CAAA;AACA,EAAA,IAAA,CAAA,YAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,KAAA,MAAA,OAAA,IAAA,YAAA,EAAA;AACA,IAAA,IAAA;AACA,MAAA,OAAA,CAAA,IAAA,CAAA;AACA,IAAA,CAAA,CAAA,OAAA,CAAA,EAAA;AACA,MAAAD,sBAAA;AACA,QAAAC,iBAAA,CAAA,KAAA;AACA,UAAA,CAAA,uDAAA,EAAA,IAAA,CAAA,QAAA,EAAAC,0BAAA,CAAA,OAAA,CAAA,CAAA,QAAA,CAAA;AACA,UAAA,CAAA;AACA,SAAA;AACA,IAAA;AACA,EAAA;AACA;;;;;;;"}
|
|
@@ -32,13 +32,15 @@ const consoleIntegration = integration.defineIntegration((options = {}) => {
|
|
|
32
32
|
return {
|
|
33
33
|
name: INTEGRATION_NAME,
|
|
34
34
|
setup(client) {
|
|
35
|
-
console.addConsoleInstrumentationHandler(({ args, level }) => {
|
|
35
|
+
const unsubscribe = console.addConsoleInstrumentationHandler(({ args, level }) => {
|
|
36
36
|
if (currentScopes.getClient() !== client || !levels.has(level)) {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
addConsoleBreadcrumb(level, args);
|
|
41
41
|
});
|
|
42
|
+
|
|
43
|
+
client.registerCleanup(unsubscribe);
|
|
42
44
|
},
|
|
43
45
|
};
|
|
44
46
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.js","sources":["../../../src/integrations/console.ts"],"sourcesContent":["import { addBreadcrumb } from '../breadcrumbs';\nimport { getClient } from '../currentScopes';\nimport { addConsoleInstrumentationHandler } from '../instrument/console';\nimport { defineIntegration } from '../integration';\nimport type { ConsoleLevel } from '../types-hoist/instrument';\nimport { CONSOLE_LEVELS } from '../utils/debug-logger';\nimport { severityLevelFromString } from '../utils/severity';\nimport { safeJoin } from '../utils/string';\nimport { GLOBAL_OBJ } from '../utils/worldwide';\n\ninterface ConsoleIntegrationOptions {\n levels: ConsoleLevel[];\n}\n\ntype GlobalObjectWithUtil = typeof GLOBAL_OBJ & {\n util: {\n format: (...args: unknown[]) => string;\n };\n};\n\nconst INTEGRATION_NAME = 'Console';\n\n/**\n * Captures calls to the `console` API as breadcrumbs in Sentry.\n *\n * By default the integration instruments `console.debug`, `console.info`, `console.warn`, `console.error`,\n * `console.log`, `console.trace`, and `console.assert`. You can use the `levels` option to customize which\n * levels are captured.\n *\n * @example\n *\n * ```js\n * Sentry.init({\n * integrations: [Sentry.consoleIntegration({ levels: ['error', 'warn'] })],\n * });\n * ```\n */\nexport const consoleIntegration = defineIntegration((options: Partial<ConsoleIntegrationOptions> = {}) => {\n const levels = new Set(options.levels || CONSOLE_LEVELS);\n\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n addConsoleInstrumentationHandler(({ args, level }) => {\n if (getClient() !== client || !levels.has(level)) {\n return;\n }\n\n addConsoleBreadcrumb(level, args);\n });\n },\n };\n});\n\n/**\n * Capture a console breadcrumb.\n *\n * Exported just for tests.\n */\nexport function addConsoleBreadcrumb(level: ConsoleLevel, args: unknown[]): void {\n const breadcrumb = {\n category: 'console',\n data: {\n arguments: args,\n logger: 'console',\n },\n level: severityLevelFromString(level),\n message: formatConsoleArgs(args),\n };\n\n if (level === 'assert') {\n if (args[0] === false) {\n const assertionArgs = args.slice(1);\n breadcrumb.message =\n assertionArgs.length > 0 ? `Assertion failed: ${formatConsoleArgs(assertionArgs)}` : 'Assertion failed';\n breadcrumb.data.arguments = assertionArgs;\n } else {\n // Don't capture a breadcrumb for passed assertions\n return;\n }\n }\n\n addBreadcrumb(breadcrumb, {\n input: args,\n level,\n });\n}\n\nfunction formatConsoleArgs(values: unknown[]): string {\n return 'util' in GLOBAL_OBJ && typeof (GLOBAL_OBJ as GlobalObjectWithUtil).util.format === 'function'\n ? (GLOBAL_OBJ as GlobalObjectWithUtil).util.format(...values)\n : safeJoin(values, ' ');\n}\n"],"names":["defineIntegration","CONSOLE_LEVELS","addConsoleInstrumentationHandler","getClient","severityLevelFromString","addBreadcrumb","GLOBAL_OBJ","safeJoin"],"mappings":";;;;;;;;;;;AAoBA,MAAM,gBAAA,GAAmB,SAAS;;AAElC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,kBAAA,GAAqBA,6BAAiB,CAAC,CAAC,OAAO,GAAuC,EAAE,KAAK;AAC1G,EAAE,MAAM,MAAA,GAAS,IAAI,GAAG,CAAC,OAAO,CAAC,MAAA,IAAUC,0BAAc,CAAC;;AAE1D,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,
|
|
1
|
+
{"version":3,"file":"console.js","sources":["../../../src/integrations/console.ts"],"sourcesContent":["import { addBreadcrumb } from '../breadcrumbs';\nimport { getClient } from '../currentScopes';\nimport { addConsoleInstrumentationHandler } from '../instrument/console';\nimport { defineIntegration } from '../integration';\nimport type { ConsoleLevel } from '../types-hoist/instrument';\nimport { CONSOLE_LEVELS } from '../utils/debug-logger';\nimport { severityLevelFromString } from '../utils/severity';\nimport { safeJoin } from '../utils/string';\nimport { GLOBAL_OBJ } from '../utils/worldwide';\n\ninterface ConsoleIntegrationOptions {\n levels: ConsoleLevel[];\n}\n\ntype GlobalObjectWithUtil = typeof GLOBAL_OBJ & {\n util: {\n format: (...args: unknown[]) => string;\n };\n};\n\nconst INTEGRATION_NAME = 'Console';\n\n/**\n * Captures calls to the `console` API as breadcrumbs in Sentry.\n *\n * By default the integration instruments `console.debug`, `console.info`, `console.warn`, `console.error`,\n * `console.log`, `console.trace`, and `console.assert`. You can use the `levels` option to customize which\n * levels are captured.\n *\n * @example\n *\n * ```js\n * Sentry.init({\n * integrations: [Sentry.consoleIntegration({ levels: ['error', 'warn'] })],\n * });\n * ```\n */\nexport const consoleIntegration = defineIntegration((options: Partial<ConsoleIntegrationOptions> = {}) => {\n const levels = new Set(options.levels || CONSOLE_LEVELS);\n\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n const unsubscribe = addConsoleInstrumentationHandler(({ args, level }) => {\n if (getClient() !== client || !levels.has(level)) {\n return;\n }\n\n addConsoleBreadcrumb(level, args);\n });\n\n client.registerCleanup(unsubscribe);\n },\n };\n});\n\n/**\n * Capture a console breadcrumb.\n *\n * Exported just for tests.\n */\nexport function addConsoleBreadcrumb(level: ConsoleLevel, args: unknown[]): void {\n const breadcrumb = {\n category: 'console',\n data: {\n arguments: args,\n logger: 'console',\n },\n level: severityLevelFromString(level),\n message: formatConsoleArgs(args),\n };\n\n if (level === 'assert') {\n if (args[0] === false) {\n const assertionArgs = args.slice(1);\n breadcrumb.message =\n assertionArgs.length > 0 ? `Assertion failed: ${formatConsoleArgs(assertionArgs)}` : 'Assertion failed';\n breadcrumb.data.arguments = assertionArgs;\n } else {\n // Don't capture a breadcrumb for passed assertions\n return;\n }\n }\n\n addBreadcrumb(breadcrumb, {\n input: args,\n level,\n });\n}\n\nfunction formatConsoleArgs(values: unknown[]): string {\n return 'util' in GLOBAL_OBJ && typeof (GLOBAL_OBJ as GlobalObjectWithUtil).util.format === 'function'\n ? (GLOBAL_OBJ as GlobalObjectWithUtil).util.format(...values)\n : safeJoin(values, ' ');\n}\n"],"names":["defineIntegration","CONSOLE_LEVELS","addConsoleInstrumentationHandler","getClient","severityLevelFromString","addBreadcrumb","GLOBAL_OBJ","safeJoin"],"mappings":";;;;;;;;;;;AAoBA,MAAM,gBAAA,GAAmB,SAAS;;AAElC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,kBAAA,GAAqBA,6BAAiB,CAAC,CAAC,OAAO,GAAuC,EAAE,KAAK;AAC1G,EAAE,MAAM,MAAA,GAAS,IAAI,GAAG,CAAC,OAAO,CAAC,MAAA,IAAUC,0BAAc,CAAC;;AAE1D,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,MAAM,WAAA,GAAcC,wCAAgC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAA,EAAO,KAAK;AAChF,QAAQ,IAAIC,uBAAS,OAAO,MAAA,IAAU,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;AAC1D,UAAU;AACV,QAAQ;;AAER,QAAQ,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC;AACzC,MAAM,CAAC,CAAC;;AAER,MAAM,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC;AACzC,IAAI,CAAC;AACL,GAAG;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA;AACO,SAAS,oBAAoB,CAAC,KAAK,EAAgB,IAAI,EAAmB;AACjF,EAAE,MAAM,aAAa;AACrB,IAAI,QAAQ,EAAE,SAAS;AACvB,IAAI,IAAI,EAAE;AACV,MAAM,SAAS,EAAE,IAAI;AACrB,MAAM,MAAM,EAAE,SAAS;AACvB,KAAK;AACL,IAAI,KAAK,EAAEC,gCAAuB,CAAC,KAAK,CAAC;AACzC,IAAI,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC;AACpC,GAAG;;AAEH,EAAE,IAAI,KAAA,KAAU,QAAQ,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,CAAC,CAAA,KAAM,KAAK,EAAE;AAC3B,MAAM,MAAM,gBAAgB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,MAAM,UAAU,CAAC,OAAA;AACjB,QAAQ,aAAa,CAAC,MAAA,GAAS,IAAI,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAA,GAAA,kBAAA;AACA,MAAA,UAAA,CAAA,IAAA,CAAA,SAAA,GAAA,aAAA;AACA,IAAA,CAAA,MAAA;AACA;AACA,MAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAAC,yBAAA,CAAA,UAAA,EAAA;AACA,IAAA,KAAA,EAAA,IAAA;AACA,IAAA,KAAA;AACA,GAAA,CAAA;AACA;;AAEA,SAAA,iBAAA,CAAA,MAAA,EAAA;AACA,EAAA,OAAA,MAAA,IAAAC,oBAAA,IAAA,OAAA,CAAAA,oBAAA,GAAA,IAAA,CAAA,MAAA,KAAA;AACA,MAAA,CAAAA,oBAAA,GAAA,IAAA,CAAA,MAAA,CAAA,GAAA,MAAA;AACA,MAAAC,eAAA,CAAA,MAAA,EAAA,GAAA,CAAA;AACA;;;;;"}
|
|
@@ -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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"}
|
|
@@ -323,6 +323,8 @@ function _reconstructQuery(strings) {
|
|
|
323
323
|
return strings.reduce((acc, str, i) => (i === 0 ? str : `${acc}$${i}${str}`), '');
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
let integerLiteralRE;
|
|
327
|
+
|
|
326
328
|
/**
|
|
327
329
|
* Sanitize SQL query as per the OTEL semantic conventions
|
|
328
330
|
* https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext
|
|
@@ -337,6 +339,13 @@ function _sanitizeSqlQuery(sqlQuery) {
|
|
|
337
339
|
return 'Unknown SQL Query';
|
|
338
340
|
}
|
|
339
341
|
|
|
342
|
+
// Lazy init: constructing this at module scope would evaluate the lookbehind
|
|
343
|
+
// on import and crash Safari <16.4 browser bundles that reach this file via
|
|
344
|
+
// the core barrel. Building it on first call keeps the cost off the import path.
|
|
345
|
+
if (!integerLiteralRE) {
|
|
346
|
+
integerLiteralRE = new RegExp('(?<!\\$)-?\\b\\d+\\b', 'g');
|
|
347
|
+
}
|
|
348
|
+
|
|
340
349
|
return (
|
|
341
350
|
sqlQuery
|
|
342
351
|
// Remove comments first (they may contain newlines and extra spaces)
|
|
@@ -359,7 +368,7 @@ function _sanitizeSqlQuery(sqlQuery) {
|
|
|
359
368
|
.replace(/-?\b\d+\.?\d*[eE][+-]?\d+\b/g, '?') // Scientific notation
|
|
360
369
|
.replace(/-?\b\d+\.\d+\b/g, '?') // Decimals
|
|
361
370
|
.replace(/-?\.\d+\b/g, '?') // Decimals starting with dot
|
|
362
|
-
.replace(
|
|
371
|
+
.replace(integerLiteralRE, '?') // Integers (NOT $n placeholders)
|
|
363
372
|
// Collapse IN clauses for cardinality (both ? and $n variants)
|
|
364
373
|
.replace(/\bIN\b\s*\(\s*\?(?:\s*,\s*\?)*\s*\)/gi, 'IN (?)')
|
|
365
374
|
.replace(/\bIN\b\s*\(\s*\$\d+(?:\s*,\s*\$\d+)*\s*\)/gi, 'IN ($?)')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgresjs.js","sources":["../../../src/integrations/postgresjs.ts"],"sourcesContent":["// Portable instrumentation for https://github.com/porsager/postgres\n// This can be used in any environment (Node.js, Cloudflare Workers, etc.)\n// without depending on OpenTelemetry module hooking.\n\nimport { DEBUG_BUILD } from '../debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes';\nimport { SPAN_STATUS_ERROR, startSpanManual } from '../tracing';\nimport type { Span } from '../types-hoist/span';\nimport { debug } from '../utils/debug-logger';\nimport { getActiveSpan } from '../utils/spanUtils';\n\nconst SQL_OPERATION_REGEX = /^(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i;\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string;\n ATTR_SERVER_ADDRESS?: string;\n ATTR_SERVER_PORT?: string;\n};\n\ninterface PostgresJsSqlInstrumentationOptions {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n}\n\nconst CONNECTION_CONTEXT_SYMBOL = Symbol('sentryPostgresConnectionContext');\n\n// Use the same Symbol.for() markers as the Node.js OTel instrumentation\n// so that both approaches recognize each other and prevent double-wrapping.\nconst INSTRUMENTED_MARKER = Symbol.for('sentry.instrumented.postgresjs');\n// Marker to track if a query was created from an instrumented sql instance.\n// This prevents double-spanning when both the wrapper and the Node.js Query.prototype\n// fallback patch are active simultaneously.\nconst QUERY_FROM_INSTRUMENTED_SQL = Symbol.for('sentry.query.from.instrumented.sql');\n\n/**\n * Instruments a postgres.js `sql` instance with Sentry tracing.\n *\n * This is a portable instrumentation function that works in any environment\n * (Node.js, Cloudflare Workers, etc.) without depending on OpenTelemetry.\n *\n * @example\n * ```javascript\n * import postgres from 'postgres';\n * import * as Sentry from '@sentry/cloudflare'; // or '@sentry/deno'\n *\n * const sql = Sentry.instrumentPostgresJsSql(\n * postgres({ host: 'localhost', database: 'mydb' })\n * );\n *\n * // All queries now create Sentry spans\n * await sql`SELECT * FROM users WHERE id = ${userId}`;\n * ```\n */\nexport function instrumentPostgresJsSql<T>(sql: T, options?: PostgresJsSqlInstrumentationOptions): T {\n if (!sql || typeof sql !== 'function') {\n DEBUG_BUILD && debug.warn('instrumentPostgresJsSql: provided value is not a valid postgres.js sql instance');\n return sql;\n }\n\n return _instrumentSqlInstance(sql, { requireParentSpan: true, ...options }) as T;\n}\n\n/**\n * Instruments a sql instance by wrapping its query execution methods.\n */\nfunction _instrumentSqlInstance(\n sql: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n parentConnectionContext?: PostgresConnectionContext,\n): unknown {\n // Check if already instrumented to prevent double-wrapping\n // Using Symbol.for() ensures the marker survives proxying\n if ((sql as Record<symbol, unknown>)[INSTRUMENTED_MARKER]) {\n return sql;\n }\n\n // Wrap the sql function to intercept query creation\n const proxiedSql: unknown = new Proxy(sql as (...args: unknown[]) => unknown, {\n apply(target, thisArg, argumentsList: unknown[]) {\n const query = Reflect.apply(target, thisArg, argumentsList);\n\n if (query && typeof query === 'object' && 'handle' in query) {\n _wrapSingleQueryHandle(query as { handle: unknown; strings?: string[] }, proxiedSql, options);\n }\n\n return query;\n },\n get(target, prop) {\n const original = (target as unknown as Record<string | symbol, unknown>)[prop];\n\n if (typeof prop !== 'string' || typeof original !== 'function') {\n return original;\n }\n\n // Wrap methods that return PendingQuery objects (unsafe, file)\n if (prop === 'unsafe' || prop === 'file') {\n return _wrapQueryMethod(original as (...args: unknown[]) => unknown, target, proxiedSql, options);\n }\n\n // Wrap begin and reserve (not savepoint to avoid duplicate spans)\n if (prop === 'begin' || prop === 'reserve') {\n return _wrapCallbackMethod(original as (...args: unknown[]) => unknown, target, proxiedSql, options);\n }\n\n return original;\n },\n });\n\n // Use provided parent context if available, otherwise extract from sql.options\n if (parentConnectionContext) {\n (proxiedSql as Record<symbol, unknown>)[CONNECTION_CONTEXT_SYMBOL] = parentConnectionContext;\n } else {\n _attachConnectionContext(sql, proxiedSql as Record<symbol, unknown>);\n }\n\n // Mark both the original and proxy as instrumented to prevent double-wrapping\n (sql as Record<symbol, unknown>)[INSTRUMENTED_MARKER] = true;\n (proxiedSql as Record<symbol, unknown>)[INSTRUMENTED_MARKER] = true;\n\n return proxiedSql;\n}\n\n/**\n * Wraps query-returning methods (unsafe, file) to ensure their queries are instrumented.\n */\nfunction _wrapQueryMethod(\n original: (...args: unknown[]) => unknown,\n target: unknown,\n proxiedSql: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n): (...args: unknown[]) => unknown {\n return function (this: unknown, ...args: unknown[]): unknown {\n const query = Reflect.apply(original, target, args);\n\n if (query && typeof query === 'object' && 'handle' in query) {\n _wrapSingleQueryHandle(query as { handle: unknown; strings?: string[] }, proxiedSql, options);\n }\n\n return query;\n };\n}\n\n/**\n * Wraps callback-based methods (begin, reserve) to recursively instrument Sql instances.\n * Note: These methods can also be used as tagged templates, which we pass through unchanged.\n *\n * Savepoint is not wrapped to avoid complex nested transaction instrumentation issues.\n * Queries within savepoint callbacks are still instrumented through the parent transaction's Sql instance.\n */\nfunction _wrapCallbackMethod(\n original: (...args: unknown[]) => unknown,\n target: unknown,\n parentSqlInstance: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n): (...args: unknown[]) => unknown {\n return function (this: unknown, ...args: unknown[]): unknown {\n // Extract parent context to propagate to child instances\n const parentContext = (parentSqlInstance as Record<symbol, unknown>)[CONNECTION_CONTEXT_SYMBOL] as\n | PostgresConnectionContext\n | undefined;\n\n // Check if this is a callback-based call by verifying the last argument is a function\n const isCallbackBased = typeof args[args.length - 1] === 'function';\n\n if (!isCallbackBased) {\n // Not a callback-based call - could be tagged template or promise-based\n const result = Reflect.apply(original, target, args);\n // If result is a Promise (e.g., reserve() without callback), instrument the resolved Sql instance\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n return (result as Promise<unknown>).then((sqlInstance: unknown) => {\n return _instrumentSqlInstance(sqlInstance, options, parentContext);\n });\n }\n return result;\n }\n\n // Callback-based call: wrap the callback to instrument the Sql instance\n const callback = (args.length === 1 ? args[0] : args[1]) as (sql: unknown) => unknown;\n const wrappedCallback = function (sqlInstance: unknown): unknown {\n const instrumentedSql = _instrumentSqlInstance(sqlInstance, options, parentContext);\n return callback(instrumentedSql);\n };\n\n const newArgs = args.length === 1 ? [wrappedCallback] : [args[0], wrappedCallback];\n return Reflect.apply(original, target, newArgs);\n };\n}\n\n/**\n * Wraps a single query's handle method to create spans.\n */\nfunction _wrapSingleQueryHandle(\n query: { handle: unknown; strings?: string[]; __sentryWrapped?: boolean },\n sqlInstance: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n): void {\n // Prevent double wrapping - check if the handle itself is already wrapped\n if ((query.handle as { __sentryWrapped?: boolean })?.__sentryWrapped) {\n return;\n }\n\n // Mark this query as coming from an instrumented sql instance.\n // This prevents the Node.js Query.prototype fallback patch from double-spanning.\n (query as Record<symbol, unknown>)[QUERY_FROM_INSTRUMENTED_SQL] = true;\n\n const originalHandle = query.handle as (...args: unknown[]) => Promise<unknown>;\n\n // IMPORTANT: We must replace the handle function directly, not use a Proxy,\n // because Query.then() internally calls this.handle(), which would bypass a Proxy wrapper.\n const wrappedHandle = async function (this: unknown, ...args: unknown[]): Promise<unknown> {\n if (!_shouldCreateSpans(options)) {\n return originalHandle.apply(this, args);\n }\n\n const fullQuery = _reconstructQuery(query.strings);\n const sanitizedSqlQuery = _sanitizeSqlQuery(fullQuery);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.postgresjs');\n\n span.setAttributes({\n 'db.system.name': 'postgres',\n 'db.query.text': sanitizedSqlQuery,\n });\n\n const connectionContext = sqlInstance\n ? ((sqlInstance as Record<symbol, unknown>)[CONNECTION_CONTEXT_SYMBOL] as\n | PostgresConnectionContext\n | undefined)\n : undefined;\n\n _setConnectionAttributes(span, connectionContext);\n\n if (options.requestHook) {\n try {\n options.requestHook(span, sanitizedSqlQuery, connectionContext);\n } catch (e) {\n span.setAttribute('sentry.hook.error', 'requestHook failed');\n DEBUG_BUILD && debug.error('Error in requestHook for PostgresJs instrumentation:', e);\n }\n }\n\n const queryWithCallbacks = this as {\n resolve: unknown;\n reject: unknown;\n };\n\n queryWithCallbacks.resolve = new Proxy(queryWithCallbacks.resolve as (...args: unknown[]) => unknown, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n try {\n _setOperationName(span, sanitizedSqlQuery, resolveArgs?.[0]?.command);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in resolve callback:', e);\n }\n\n return Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n },\n });\n\n queryWithCallbacks.reject = new Proxy(queryWithCallbacks.reject as (...args: unknown[]) => unknown, {\n apply: (rejectTarget, rejectThisArg, rejectArgs: { message?: string; code?: string; name?: string }[]) => {\n try {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n\n span.setAttribute('db.response.status_code', rejectArgs?.[0]?.code || 'unknown');\n span.setAttribute('error.type', rejectArgs?.[0]?.name || 'unknown');\n\n _setOperationName(span, sanitizedSqlQuery);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in reject callback:', e);\n }\n return Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n },\n });\n\n // Handle synchronous errors that might occur before promise is created\n try {\n return originalHandle.apply(this, args);\n } catch (e) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: e instanceof Error ? e.message : 'unknown_error',\n });\n span.end();\n throw e;\n }\n },\n );\n };\n\n (wrappedHandle as { __sentryWrapped?: boolean }).__sentryWrapped = true;\n query.handle = wrappedHandle;\n}\n\n/**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the options, a span will\n * only be created if there is a parent span available.\n */\nfunction _shouldCreateSpans(options: PostgresJsSqlInstrumentationOptions): boolean {\n const hasParentSpan = getActiveSpan() !== undefined;\n return hasParentSpan || !options.requireParentSpan;\n}\n\n/**\n * Reconstructs the full SQL query from template strings with PostgreSQL placeholders.\n *\n * For sql`SELECT * FROM users WHERE id = ${123} AND name = ${'foo'}`:\n * strings = [\"SELECT * FROM users WHERE id = \", \" AND name = \", \"\"]\n * returns: \"SELECT * FROM users WHERE id = $1 AND name = $2\"\n *\n * @internal Exported for testing only\n */\nexport function _reconstructQuery(strings: string[] | undefined): string | undefined {\n if (!strings?.length) {\n return undefined;\n }\n if (strings.length === 1) {\n return strings[0] || undefined;\n }\n // Join template parts with PostgreSQL placeholders ($1, $2, etc.)\n return strings.reduce((acc, str, i) => (i === 0 ? str : `${acc}$${i}${str}`), '');\n}\n\n/**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n *\n * PostgreSQL $n placeholders are preserved per OTEL spec - they're parameterized queries,\n * not sensitive literals. Only actual values (strings, numbers, booleans) are sanitized.\n *\n * @internal Exported for testing only\n */\nexport function _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n return (\n sqlQuery\n // Remove comments first (they may contain newlines and extra spaces)\n .replace(/--.*$/gm, '') // Single line comments (multiline mode)\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n // Collapse whitespace to a single space (after removing comments)\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces and trim\n // Sanitize hex/binary literals before string literals\n .replace(/\\bX'[0-9A-Fa-f]*'/gi, '?') // Hex string literals\n .replace(/\\bB'[01]*'/gi, '?') // Binary string literals\n // Sanitize string literals (handles escaped quotes)\n .replace(/'(?:[^']|'')*'/g, '?')\n // Sanitize hex numbers\n .replace(/\\b0x[0-9A-Fa-f]+/gi, '?')\n // Sanitize boolean literals\n .replace(/\\b(?:TRUE|FALSE)\\b/gi, '?')\n // Sanitize numeric literals (preserve $n placeholders via negative lookbehind)\n .replace(/-?\\b\\d+\\.?\\d*[eE][+-]?\\d+\\b/g, '?') // Scientific notation\n .replace(/-?\\b\\d+\\.\\d+\\b/g, '?') // Decimals\n .replace(/-?\\.\\d+\\b/g, '?') // Decimals starting with dot\n .replace(/(?<!\\$)-?\\b\\d+\\b/g, '?') // Integers (NOT $n placeholders)\n // Collapse IN clauses for cardinality (both ? and $n variants)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/gi, 'IN (?)')\n .replace(/\\bIN\\b\\s*\\(\\s*\\$\\d+(?:\\s*,\\s*\\$\\d+)*\\s*\\)/gi, 'IN ($?)')\n );\n}\n\n/**\n * Sets connection context attributes on a span.\n */\nfunction _setConnectionAttributes(span: Span, connectionContext: PostgresConnectionContext | undefined): void {\n if (!connectionContext) {\n return;\n }\n if (connectionContext.ATTR_DB_NAMESPACE) {\n span.setAttribute('db.namespace', connectionContext.ATTR_DB_NAMESPACE);\n }\n if (connectionContext.ATTR_SERVER_ADDRESS) {\n span.setAttribute('server.address', connectionContext.ATTR_SERVER_ADDRESS);\n }\n if (connectionContext.ATTR_SERVER_PORT !== undefined) {\n // Port is stored as string in PostgresConnectionContext for requestHook backwards compatibility,\n // but semantic conventions expect port as a number for span attributes\n const portNumber = parseInt(connectionContext.ATTR_SERVER_PORT, 10);\n if (!isNaN(portNumber)) {\n span.setAttribute('server.port', portNumber);\n }\n }\n}\n\n/**\n * Extracts DB operation name from SQL query and sets it on the span.\n */\nfunction _setOperationName(span: Span, sanitizedQuery: string | undefined, command?: string): void {\n if (command) {\n span.setAttribute('db.operation.name', command);\n return;\n }\n // Fallback: extract operation from the SQL query\n const operationMatch = sanitizedQuery?.match(SQL_OPERATION_REGEX);\n if (operationMatch?.[1]) {\n span.setAttribute('db.operation.name', operationMatch[1].toUpperCase());\n }\n}\n\n/**\n * Extracts and stores connection context from sql.options.\n */\nfunction _attachConnectionContext(sql: unknown, proxiedSql: Record<symbol, unknown>): void {\n const sqlInstance = sql as { options?: { host?: string[]; port?: number[]; database?: string } };\n if (!sqlInstance.options || typeof sqlInstance.options !== 'object') {\n return;\n }\n\n const opts = sqlInstance.options;\n // postgres.js stores parsed options with host and port as arrays\n // The library defaults to 'localhost' and 5432 if not specified, but we're defensive here\n const host = opts.host?.[0] || 'localhost';\n const port = opts.port?.[0] || 5432;\n\n const connectionContext: PostgresConnectionContext = {\n ATTR_DB_NAMESPACE: typeof opts.database === 'string' && opts.database !== '' ? opts.database : undefined,\n ATTR_SERVER_ADDRESS: host,\n ATTR_SERVER_PORT: String(port),\n };\n\n proxiedSql[CONNECTION_CONTEXT_SYMBOL] = connectionContext;\n}\n"],"names":["DEBUG_BUILD","debug","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SPAN_STATUS_ERROR","getActiveSpan"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"postgresjs.js","sources":["../../../src/integrations/postgresjs.ts"],"sourcesContent":["// Portable instrumentation for https://github.com/porsager/postgres\n// This can be used in any environment (Node.js, Cloudflare Workers, etc.)\n// without depending on OpenTelemetry module hooking.\n\nimport { DEBUG_BUILD } from '../debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes';\nimport { SPAN_STATUS_ERROR, startSpanManual } from '../tracing';\nimport type { Span } from '../types-hoist/span';\nimport { debug } from '../utils/debug-logger';\nimport { getActiveSpan } from '../utils/spanUtils';\n\nconst SQL_OPERATION_REGEX = /^(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i;\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string;\n ATTR_SERVER_ADDRESS?: string;\n ATTR_SERVER_PORT?: string;\n};\n\ninterface PostgresJsSqlInstrumentationOptions {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n}\n\nconst CONNECTION_CONTEXT_SYMBOL = Symbol('sentryPostgresConnectionContext');\n\n// Use the same Symbol.for() markers as the Node.js OTel instrumentation\n// so that both approaches recognize each other and prevent double-wrapping.\nconst INSTRUMENTED_MARKER = Symbol.for('sentry.instrumented.postgresjs');\n// Marker to track if a query was created from an instrumented sql instance.\n// This prevents double-spanning when both the wrapper and the Node.js Query.prototype\n// fallback patch are active simultaneously.\nconst QUERY_FROM_INSTRUMENTED_SQL = Symbol.for('sentry.query.from.instrumented.sql');\n\n/**\n * Instruments a postgres.js `sql` instance with Sentry tracing.\n *\n * This is a portable instrumentation function that works in any environment\n * (Node.js, Cloudflare Workers, etc.) without depending on OpenTelemetry.\n *\n * @example\n * ```javascript\n * import postgres from 'postgres';\n * import * as Sentry from '@sentry/cloudflare'; // or '@sentry/deno'\n *\n * const sql = Sentry.instrumentPostgresJsSql(\n * postgres({ host: 'localhost', database: 'mydb' })\n * );\n *\n * // All queries now create Sentry spans\n * await sql`SELECT * FROM users WHERE id = ${userId}`;\n * ```\n */\nexport function instrumentPostgresJsSql<T>(sql: T, options?: PostgresJsSqlInstrumentationOptions): T {\n if (!sql || typeof sql !== 'function') {\n DEBUG_BUILD && debug.warn('instrumentPostgresJsSql: provided value is not a valid postgres.js sql instance');\n return sql;\n }\n\n return _instrumentSqlInstance(sql, { requireParentSpan: true, ...options }) as T;\n}\n\n/**\n * Instruments a sql instance by wrapping its query execution methods.\n */\nfunction _instrumentSqlInstance(\n sql: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n parentConnectionContext?: PostgresConnectionContext,\n): unknown {\n // Check if already instrumented to prevent double-wrapping\n // Using Symbol.for() ensures the marker survives proxying\n if ((sql as Record<symbol, unknown>)[INSTRUMENTED_MARKER]) {\n return sql;\n }\n\n // Wrap the sql function to intercept query creation\n const proxiedSql: unknown = new Proxy(sql as (...args: unknown[]) => unknown, {\n apply(target, thisArg, argumentsList: unknown[]) {\n const query = Reflect.apply(target, thisArg, argumentsList);\n\n if (query && typeof query === 'object' && 'handle' in query) {\n _wrapSingleQueryHandle(query as { handle: unknown; strings?: string[] }, proxiedSql, options);\n }\n\n return query;\n },\n get(target, prop) {\n const original = (target as unknown as Record<string | symbol, unknown>)[prop];\n\n if (typeof prop !== 'string' || typeof original !== 'function') {\n return original;\n }\n\n // Wrap methods that return PendingQuery objects (unsafe, file)\n if (prop === 'unsafe' || prop === 'file') {\n return _wrapQueryMethod(original as (...args: unknown[]) => unknown, target, proxiedSql, options);\n }\n\n // Wrap begin and reserve (not savepoint to avoid duplicate spans)\n if (prop === 'begin' || prop === 'reserve') {\n return _wrapCallbackMethod(original as (...args: unknown[]) => unknown, target, proxiedSql, options);\n }\n\n return original;\n },\n });\n\n // Use provided parent context if available, otherwise extract from sql.options\n if (parentConnectionContext) {\n (proxiedSql as Record<symbol, unknown>)[CONNECTION_CONTEXT_SYMBOL] = parentConnectionContext;\n } else {\n _attachConnectionContext(sql, proxiedSql as Record<symbol, unknown>);\n }\n\n // Mark both the original and proxy as instrumented to prevent double-wrapping\n (sql as Record<symbol, unknown>)[INSTRUMENTED_MARKER] = true;\n (proxiedSql as Record<symbol, unknown>)[INSTRUMENTED_MARKER] = true;\n\n return proxiedSql;\n}\n\n/**\n * Wraps query-returning methods (unsafe, file) to ensure their queries are instrumented.\n */\nfunction _wrapQueryMethod(\n original: (...args: unknown[]) => unknown,\n target: unknown,\n proxiedSql: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n): (...args: unknown[]) => unknown {\n return function (this: unknown, ...args: unknown[]): unknown {\n const query = Reflect.apply(original, target, args);\n\n if (query && typeof query === 'object' && 'handle' in query) {\n _wrapSingleQueryHandle(query as { handle: unknown; strings?: string[] }, proxiedSql, options);\n }\n\n return query;\n };\n}\n\n/**\n * Wraps callback-based methods (begin, reserve) to recursively instrument Sql instances.\n * Note: These methods can also be used as tagged templates, which we pass through unchanged.\n *\n * Savepoint is not wrapped to avoid complex nested transaction instrumentation issues.\n * Queries within savepoint callbacks are still instrumented through the parent transaction's Sql instance.\n */\nfunction _wrapCallbackMethod(\n original: (...args: unknown[]) => unknown,\n target: unknown,\n parentSqlInstance: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n): (...args: unknown[]) => unknown {\n return function (this: unknown, ...args: unknown[]): unknown {\n // Extract parent context to propagate to child instances\n const parentContext = (parentSqlInstance as Record<symbol, unknown>)[CONNECTION_CONTEXT_SYMBOL] as\n | PostgresConnectionContext\n | undefined;\n\n // Check if this is a callback-based call by verifying the last argument is a function\n const isCallbackBased = typeof args[args.length - 1] === 'function';\n\n if (!isCallbackBased) {\n // Not a callback-based call - could be tagged template or promise-based\n const result = Reflect.apply(original, target, args);\n // If result is a Promise (e.g., reserve() without callback), instrument the resolved Sql instance\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n return (result as Promise<unknown>).then((sqlInstance: unknown) => {\n return _instrumentSqlInstance(sqlInstance, options, parentContext);\n });\n }\n return result;\n }\n\n // Callback-based call: wrap the callback to instrument the Sql instance\n const callback = (args.length === 1 ? args[0] : args[1]) as (sql: unknown) => unknown;\n const wrappedCallback = function (sqlInstance: unknown): unknown {\n const instrumentedSql = _instrumentSqlInstance(sqlInstance, options, parentContext);\n return callback(instrumentedSql);\n };\n\n const newArgs = args.length === 1 ? [wrappedCallback] : [args[0], wrappedCallback];\n return Reflect.apply(original, target, newArgs);\n };\n}\n\n/**\n * Wraps a single query's handle method to create spans.\n */\nfunction _wrapSingleQueryHandle(\n query: { handle: unknown; strings?: string[]; __sentryWrapped?: boolean },\n sqlInstance: unknown,\n options: PostgresJsSqlInstrumentationOptions,\n): void {\n // Prevent double wrapping - check if the handle itself is already wrapped\n if ((query.handle as { __sentryWrapped?: boolean })?.__sentryWrapped) {\n return;\n }\n\n // Mark this query as coming from an instrumented sql instance.\n // This prevents the Node.js Query.prototype fallback patch from double-spanning.\n (query as Record<symbol, unknown>)[QUERY_FROM_INSTRUMENTED_SQL] = true;\n\n const originalHandle = query.handle as (...args: unknown[]) => Promise<unknown>;\n\n // IMPORTANT: We must replace the handle function directly, not use a Proxy,\n // because Query.then() internally calls this.handle(), which would bypass a Proxy wrapper.\n const wrappedHandle = async function (this: unknown, ...args: unknown[]): Promise<unknown> {\n if (!_shouldCreateSpans(options)) {\n return originalHandle.apply(this, args);\n }\n\n const fullQuery = _reconstructQuery(query.strings);\n const sanitizedSqlQuery = _sanitizeSqlQuery(fullQuery);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.postgresjs');\n\n span.setAttributes({\n 'db.system.name': 'postgres',\n 'db.query.text': sanitizedSqlQuery,\n });\n\n const connectionContext = sqlInstance\n ? ((sqlInstance as Record<symbol, unknown>)[CONNECTION_CONTEXT_SYMBOL] as\n | PostgresConnectionContext\n | undefined)\n : undefined;\n\n _setConnectionAttributes(span, connectionContext);\n\n if (options.requestHook) {\n try {\n options.requestHook(span, sanitizedSqlQuery, connectionContext);\n } catch (e) {\n span.setAttribute('sentry.hook.error', 'requestHook failed');\n DEBUG_BUILD && debug.error('Error in requestHook for PostgresJs instrumentation:', e);\n }\n }\n\n const queryWithCallbacks = this as {\n resolve: unknown;\n reject: unknown;\n };\n\n queryWithCallbacks.resolve = new Proxy(queryWithCallbacks.resolve as (...args: unknown[]) => unknown, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n try {\n _setOperationName(span, sanitizedSqlQuery, resolveArgs?.[0]?.command);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in resolve callback:', e);\n }\n\n return Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n },\n });\n\n queryWithCallbacks.reject = new Proxy(queryWithCallbacks.reject as (...args: unknown[]) => unknown, {\n apply: (rejectTarget, rejectThisArg, rejectArgs: { message?: string; code?: string; name?: string }[]) => {\n try {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n\n span.setAttribute('db.response.status_code', rejectArgs?.[0]?.code || 'unknown');\n span.setAttribute('error.type', rejectArgs?.[0]?.name || 'unknown');\n\n _setOperationName(span, sanitizedSqlQuery);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in reject callback:', e);\n }\n return Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n },\n });\n\n // Handle synchronous errors that might occur before promise is created\n try {\n return originalHandle.apply(this, args);\n } catch (e) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: e instanceof Error ? e.message : 'unknown_error',\n });\n span.end();\n throw e;\n }\n },\n );\n };\n\n (wrappedHandle as { __sentryWrapped?: boolean }).__sentryWrapped = true;\n query.handle = wrappedHandle;\n}\n\n/**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the options, a span will\n * only be created if there is a parent span available.\n */\nfunction _shouldCreateSpans(options: PostgresJsSqlInstrumentationOptions): boolean {\n const hasParentSpan = getActiveSpan() !== undefined;\n return hasParentSpan || !options.requireParentSpan;\n}\n\n/**\n * Reconstructs the full SQL query from template strings with PostgreSQL placeholders.\n *\n * For sql`SELECT * FROM users WHERE id = ${123} AND name = ${'foo'}`:\n * strings = [\"SELECT * FROM users WHERE id = \", \" AND name = \", \"\"]\n * returns: \"SELECT * FROM users WHERE id = $1 AND name = $2\"\n *\n * @internal Exported for testing only\n */\nexport function _reconstructQuery(strings: string[] | undefined): string | undefined {\n if (!strings?.length) {\n return undefined;\n }\n if (strings.length === 1) {\n return strings[0] || undefined;\n }\n // Join template parts with PostgreSQL placeholders ($1, $2, etc.)\n return strings.reduce((acc, str, i) => (i === 0 ? str : `${acc}$${i}${str}`), '');\n}\n\nlet integerLiteralRE: RegExp | undefined;\n\n/**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n *\n * PostgreSQL $n placeholders are preserved per OTEL spec - they're parameterized queries,\n * not sensitive literals. Only actual values (strings, numbers, booleans) are sanitized.\n *\n * @internal Exported for testing only\n */\nexport function _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n // Lazy init: constructing this at module scope would evaluate the lookbehind\n // on import and crash Safari <16.4 browser bundles that reach this file via\n // the core barrel. Building it on first call keeps the cost off the import path.\n if (!integerLiteralRE) {\n integerLiteralRE = new RegExp('(?<!\\\\$)-?\\\\b\\\\d+\\\\b', 'g');\n }\n\n return (\n sqlQuery\n // Remove comments first (they may contain newlines and extra spaces)\n .replace(/--.*$/gm, '') // Single line comments (multiline mode)\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n // Collapse whitespace to a single space (after removing comments)\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces and trim\n // Sanitize hex/binary literals before string literals\n .replace(/\\bX'[0-9A-Fa-f]*'/gi, '?') // Hex string literals\n .replace(/\\bB'[01]*'/gi, '?') // Binary string literals\n // Sanitize string literals (handles escaped quotes)\n .replace(/'(?:[^']|'')*'/g, '?')\n // Sanitize hex numbers\n .replace(/\\b0x[0-9A-Fa-f]+/gi, '?')\n // Sanitize boolean literals\n .replace(/\\b(?:TRUE|FALSE)\\b/gi, '?')\n // Sanitize numeric literals (preserve $n placeholders via negative lookbehind)\n .replace(/-?\\b\\d+\\.?\\d*[eE][+-]?\\d+\\b/g, '?') // Scientific notation\n .replace(/-?\\b\\d+\\.\\d+\\b/g, '?') // Decimals\n .replace(/-?\\.\\d+\\b/g, '?') // Decimals starting with dot\n .replace(integerLiteralRE, '?') // Integers (NOT $n placeholders)\n // Collapse IN clauses for cardinality (both ? and $n variants)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/gi, 'IN (?)')\n .replace(/\\bIN\\b\\s*\\(\\s*\\$\\d+(?:\\s*,\\s*\\$\\d+)*\\s*\\)/gi, 'IN ($?)')\n );\n}\n\n/**\n * Sets connection context attributes on a span.\n */\nfunction _setConnectionAttributes(span: Span, connectionContext: PostgresConnectionContext | undefined): void {\n if (!connectionContext) {\n return;\n }\n if (connectionContext.ATTR_DB_NAMESPACE) {\n span.setAttribute('db.namespace', connectionContext.ATTR_DB_NAMESPACE);\n }\n if (connectionContext.ATTR_SERVER_ADDRESS) {\n span.setAttribute('server.address', connectionContext.ATTR_SERVER_ADDRESS);\n }\n if (connectionContext.ATTR_SERVER_PORT !== undefined) {\n // Port is stored as string in PostgresConnectionContext for requestHook backwards compatibility,\n // but semantic conventions expect port as a number for span attributes\n const portNumber = parseInt(connectionContext.ATTR_SERVER_PORT, 10);\n if (!isNaN(portNumber)) {\n span.setAttribute('server.port', portNumber);\n }\n }\n}\n\n/**\n * Extracts DB operation name from SQL query and sets it on the span.\n */\nfunction _setOperationName(span: Span, sanitizedQuery: string | undefined, command?: string): void {\n if (command) {\n span.setAttribute('db.operation.name', command);\n return;\n }\n // Fallback: extract operation from the SQL query\n const operationMatch = sanitizedQuery?.match(SQL_OPERATION_REGEX);\n if (operationMatch?.[1]) {\n span.setAttribute('db.operation.name', operationMatch[1].toUpperCase());\n }\n}\n\n/**\n * Extracts and stores connection context from sql.options.\n */\nfunction _attachConnectionContext(sql: unknown, proxiedSql: Record<symbol, unknown>): void {\n const sqlInstance = sql as { options?: { host?: string[]; port?: number[]; database?: string } };\n if (!sqlInstance.options || typeof sqlInstance.options !== 'object') {\n return;\n }\n\n const opts = sqlInstance.options;\n // postgres.js stores parsed options with host and port as arrays\n // The library defaults to 'localhost' and 5432 if not specified, but we're defensive here\n const host = opts.host?.[0] || 'localhost';\n const port = opts.port?.[0] || 5432;\n\n const connectionContext: PostgresConnectionContext = {\n ATTR_DB_NAMESPACE: typeof opts.database === 'string' && opts.database !== '' ? opts.database : undefined,\n ATTR_SERVER_ADDRESS: host,\n ATTR_SERVER_PORT: String(port),\n };\n\n proxiedSql[CONNECTION_CONTEXT_SYMBOL] = connectionContext;\n}\n"],"names":["DEBUG_BUILD","debug","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SPAN_STATUS_ERROR","getActiveSpan"],"mappings":"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"}
|
|
@@ -89,12 +89,16 @@ function extractNormalizedRequestData(
|
|
|
89
89
|
delete (headers ).cookie;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
// Remove IP headers in case IP data should not be included in the event
|
|
92
|
+
// Remove IP headers in case IP data should not be included in the event.
|
|
93
|
+
// Match case-insensitively — same as getClientIPAddress — so lowercase keys are stripped too.
|
|
93
94
|
if (!include.ip) {
|
|
94
|
-
getIpAddress.ipHeaderNames.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
const ipHeaderNamesLower = new Set(getIpAddress.ipHeaderNames.map(name => name.toLowerCase()));
|
|
96
|
+
for (const key of Object.keys(headers)) {
|
|
97
|
+
if (ipHeaderNamesLower.has(key.toLowerCase())) {
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
99
|
+
delete (headers )[key];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestdata.js","sources":["../../../src/integrations/requestdata.ts"],"sourcesContent":["import { defineIntegration } from '../integration';\nimport type { Event } from '../types-hoist/event';\nimport type { IntegrationFn } from '../types-hoist/integration';\nimport type { RequestEventData } from '../types-hoist/request';\nimport { parseCookie } from '../utils/cookie';\nimport { getClientIPAddress, ipHeaderNames } from '../vendor/getIpAddress';\n\ninterface RequestDataIncludeOptions {\n cookies?: boolean;\n data?: boolean;\n headers?: boolean;\n ip?: boolean;\n query_string?: boolean;\n url?: boolean;\n}\n\ntype RequestDataIntegrationOptions = {\n /**\n * Controls what data is pulled from the request and added to the event.\n */\n include?: RequestDataIncludeOptions;\n};\n\n// TODO(v11): Change defaults based on `sendDefaultPii`\nconst DEFAULT_INCLUDE: RequestDataIncludeOptions = {\n cookies: true,\n data: true,\n headers: true,\n query_string: true,\n url: true,\n};\n\nconst INTEGRATION_NAME = 'RequestData';\n\nconst _requestDataIntegration = ((options: RequestDataIntegrationOptions = {}) => {\n const include = {\n ...DEFAULT_INCLUDE,\n ...options.include,\n };\n\n return {\n name: INTEGRATION_NAME,\n processEvent(event, _hint, client) {\n const { sdkProcessingMetadata = {} } = event;\n const { normalizedRequest, ipAddress } = sdkProcessingMetadata;\n\n const includeWithDefaultPiiApplied: RequestDataIncludeOptions = {\n ...include,\n ip: include.ip ?? client.getOptions().sendDefaultPii,\n };\n\n if (normalizedRequest) {\n addNormalizedRequestDataToEvent(event, normalizedRequest, { ipAddress }, includeWithDefaultPiiApplied);\n }\n\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Add data about a request to an event. Primarily for use in Node-based SDKs, but included in `@sentry/core`\n * so it can be used in cross-platform SDKs like `@sentry/nextjs`.\n */\nexport const requestDataIntegration = defineIntegration(_requestDataIntegration);\n\n/**\n * Add already normalized request data to an event.\n * This mutates the passed in event.\n */\nfunction addNormalizedRequestDataToEvent(\n event: Event,\n req: RequestEventData,\n // Data that should not go into `event.request` but is somehow related to requests\n additionalData: { ipAddress?: string },\n include: RequestDataIncludeOptions,\n): void {\n event.request = {\n ...event.request,\n ...extractNormalizedRequestData(req, include),\n };\n\n if (include.ip) {\n const ip = (req.headers && getClientIPAddress(req.headers)) || additionalData.ipAddress;\n if (ip) {\n event.user = {\n ...event.user,\n ip_address: ip,\n };\n }\n }\n}\n\nfunction extractNormalizedRequestData(\n normalizedRequest: RequestEventData,\n include: RequestDataIncludeOptions,\n): RequestEventData {\n const requestData: RequestEventData = {};\n const headers = { ...normalizedRequest.headers };\n\n if (include.headers) {\n requestData.headers = headers;\n\n // Remove the Cookie header in case cookie data should not be included in the event\n if (!include.cookies) {\n delete (headers as { cookie?: string }).cookie;\n }\n\n // Remove IP headers in case IP data should not be included in the event
|
|
1
|
+
{"version":3,"file":"requestdata.js","sources":["../../../src/integrations/requestdata.ts"],"sourcesContent":["import { defineIntegration } from '../integration';\nimport type { Event } from '../types-hoist/event';\nimport type { IntegrationFn } from '../types-hoist/integration';\nimport type { RequestEventData } from '../types-hoist/request';\nimport { parseCookie } from '../utils/cookie';\nimport { getClientIPAddress, ipHeaderNames } from '../vendor/getIpAddress';\n\ninterface RequestDataIncludeOptions {\n cookies?: boolean;\n data?: boolean;\n headers?: boolean;\n ip?: boolean;\n query_string?: boolean;\n url?: boolean;\n}\n\ntype RequestDataIntegrationOptions = {\n /**\n * Controls what data is pulled from the request and added to the event.\n */\n include?: RequestDataIncludeOptions;\n};\n\n// TODO(v11): Change defaults based on `sendDefaultPii`\nconst DEFAULT_INCLUDE: RequestDataIncludeOptions = {\n cookies: true,\n data: true,\n headers: true,\n query_string: true,\n url: true,\n};\n\nconst INTEGRATION_NAME = 'RequestData';\n\nconst _requestDataIntegration = ((options: RequestDataIntegrationOptions = {}) => {\n const include = {\n ...DEFAULT_INCLUDE,\n ...options.include,\n };\n\n return {\n name: INTEGRATION_NAME,\n processEvent(event, _hint, client) {\n const { sdkProcessingMetadata = {} } = event;\n const { normalizedRequest, ipAddress } = sdkProcessingMetadata;\n\n const includeWithDefaultPiiApplied: RequestDataIncludeOptions = {\n ...include,\n ip: include.ip ?? client.getOptions().sendDefaultPii,\n };\n\n if (normalizedRequest) {\n addNormalizedRequestDataToEvent(event, normalizedRequest, { ipAddress }, includeWithDefaultPiiApplied);\n }\n\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Add data about a request to an event. Primarily for use in Node-based SDKs, but included in `@sentry/core`\n * so it can be used in cross-platform SDKs like `@sentry/nextjs`.\n */\nexport const requestDataIntegration = defineIntegration(_requestDataIntegration);\n\n/**\n * Add already normalized request data to an event.\n * This mutates the passed in event.\n */\nfunction addNormalizedRequestDataToEvent(\n event: Event,\n req: RequestEventData,\n // Data that should not go into `event.request` but is somehow related to requests\n additionalData: { ipAddress?: string },\n include: RequestDataIncludeOptions,\n): void {\n event.request = {\n ...event.request,\n ...extractNormalizedRequestData(req, include),\n };\n\n if (include.ip) {\n const ip = (req.headers && getClientIPAddress(req.headers)) || additionalData.ipAddress;\n if (ip) {\n event.user = {\n ...event.user,\n ip_address: ip,\n };\n }\n }\n}\n\nfunction extractNormalizedRequestData(\n normalizedRequest: RequestEventData,\n include: RequestDataIncludeOptions,\n): RequestEventData {\n const requestData: RequestEventData = {};\n const headers = { ...normalizedRequest.headers };\n\n if (include.headers) {\n requestData.headers = headers;\n\n // Remove the Cookie header in case cookie data should not be included in the event\n if (!include.cookies) {\n delete (headers as { cookie?: string }).cookie;\n }\n\n // Remove IP headers in case IP data should not be included in the event.\n // Match case-insensitively — same as getClientIPAddress — so lowercase keys are stripped too.\n if (!include.ip) {\n const ipHeaderNamesLower = new Set(ipHeaderNames.map(name => name.toLowerCase()));\n for (const key of Object.keys(headers)) {\n if (ipHeaderNamesLower.has(key.toLowerCase())) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete (headers as Record<string, unknown>)[key];\n }\n }\n }\n }\n\n requestData.method = normalizedRequest.method;\n\n if (include.url) {\n requestData.url = normalizedRequest.url;\n }\n\n if (include.cookies) {\n const cookies = normalizedRequest.cookies || (headers?.cookie ? parseCookie(headers.cookie) : undefined);\n requestData.cookies = cookies || {};\n }\n\n if (include.query_string) {\n requestData.query_string = normalizedRequest.query_string;\n }\n\n if (include.data) {\n requestData.data = normalizedRequest.data;\n }\n\n return requestData;\n}\n"],"names":["defineIntegration","getClientIPAddress","ipHeaderNames","parseCookie"],"mappings":"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"}
|