From ecb41114ca1e3364c7530977f554a84144ab1587 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Wed, 14 Jan 2026 15:18:18 +0100 Subject: [PATCH 01/10] fix(node): Profiling debug ID matching --- packages/core/src/utils/debug-ids.ts | 15 +- .../core/test/lib/utils/debug-ids.test.ts | 165 ++++++++++++++++++ 2 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 packages/core/test/lib/utils/debug-ids.test.ts diff --git a/packages/core/src/utils/debug-ids.ts b/packages/core/src/utils/debug-ids.ts index fd31009ae32d..7b11e4ebc280 100644 --- a/packages/core/src/utils/debug-ids.ts +++ b/packages/core/src/utils/debug-ids.ts @@ -101,12 +101,15 @@ export function getDebugImagesForResources( const images: DebugImage[] = []; for (const path of resource_paths) { - if (path && filenameDebugIdMap[path]) { - images.push({ - type: 'sourcemap', - code_file: path, - debug_id: filenameDebugIdMap[path], - }); + if (path) { + const normalizedPath = path.startsWith('file://') ? path.slice(7) : path; + if (filenameDebugIdMap[normalizedPath]) { + images.push({ + type: 'sourcemap', + code_file: path, + debug_id: filenameDebugIdMap[normalizedPath], + }); + } } } diff --git a/packages/core/test/lib/utils/debug-ids.test.ts b/packages/core/test/lib/utils/debug-ids.test.ts new file mode 100644 index 000000000000..6235c37cf628 --- /dev/null +++ b/packages/core/test/lib/utils/debug-ids.test.ts @@ -0,0 +1,165 @@ +import { beforeEach, describe, expect, it } from 'vitest'; +import type { StackParser } from '../../../src/types-hoist/stacktrace'; +import { getDebugImagesForResources, getFilenameToDebugIdMap } from '../../../src/utils/debug-ids'; + +describe('getDebugImagesForResources', () => { + const mockStackParser: StackParser = (stack: string) => { + // Simple mock that extracts filename from a stack string + const match = stack.match(/at .* \((.*?):\d+:\d+\)/); + if (match) { + return [{ filename: match[1], function: 'mockFunction', lineno: 1, colno: 1 }]; + } + return []; + }; + + beforeEach(() => { + // Clear any existing debug ID maps + delete (globalThis as any)._sentryDebugIds; + delete (globalThis as any)._debugIds; + }); + + it('should return debug images for resources without file:// prefix', () => { + // Setup debug IDs + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'debug-id-123', + }; + + const resources = ['/var/task/index.js']; + const images = getDebugImagesForResources(mockStackParser, resources); + + expect(images).toHaveLength(1); + expect(images[0]).toEqual({ + type: 'sourcemap', + code_file: '/var/task/index.js', + debug_id: 'debug-id-123', + }); + }); + + it('should return debug images for resources with file:// prefix', () => { + // Setup debug IDs - the stack parser strips file:// when parsing + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'debug-id-123', + }; + + // V8 profiler returns resources WITH file:// prefix + const resources = ['file:///var/task/index.js']; + const images = getDebugImagesForResources(mockStackParser, resources); + + expect(images).toHaveLength(1); + expect(images[0]).toEqual({ + type: 'sourcemap', + code_file: 'file:///var/task/index.js', + debug_id: 'debug-id-123', + }); + }); + + it('should handle mixed resources with and without file:// prefix', () => { + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'debug-id-123', + 'at anotherFunction (/var/task/utils.js:10:5)': 'debug-id-456', + }; + + const resources = ['file:///var/task/index.js', '/var/task/utils.js']; + const images = getDebugImagesForResources(mockStackParser, resources); + + expect(images).toHaveLength(2); + expect(images[0]).toEqual({ + type: 'sourcemap', + code_file: 'file:///var/task/index.js', + debug_id: 'debug-id-123', + }); + expect(images[1]).toEqual({ + type: 'sourcemap', + code_file: '/var/task/utils.js', + debug_id: 'debug-id-456', + }); + }); + + it('should return empty array when no debug IDs match', () => { + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'debug-id-123', + }; + + const resources = ['file:///var/task/other.js']; + const images = getDebugImagesForResources(mockStackParser, resources); + + expect(images).toHaveLength(0); + }); + + it('should return empty array when no debug IDs are registered', () => { + const resources = ['file:///var/task/index.js']; + const images = getDebugImagesForResources(mockStackParser, resources); + + expect(images).toHaveLength(0); + }); + + it('should handle empty resource paths array', () => { + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'debug-id-123', + }; + + const resources: string[] = []; + const images = getDebugImagesForResources(mockStackParser, resources); + + expect(images).toHaveLength(0); + }); +}); + +describe('getFilenameToDebugIdMap', () => { + const mockStackParser: StackParser = (stack: string) => { + const match = stack.match(/at .* \((.*?):\d+:\d+\)/); + if (match) { + return [{ filename: match[1], function: 'mockFunction', lineno: 1, colno: 1 }]; + } + return []; + }; + + beforeEach(() => { + delete (globalThis as any)._sentryDebugIds; + delete (globalThis as any)._debugIds; + }); + + it('should return empty object when no debug IDs are registered', () => { + const map = getFilenameToDebugIdMap(mockStackParser); + expect(map).toEqual({}); + }); + + it('should build map from _sentryDebugIds', () => { + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'debug-id-123', + 'at anotherFunction (/var/task/utils.js:10:5)': 'debug-id-456', + }; + + const map = getFilenameToDebugIdMap(mockStackParser); + + expect(map).toEqual({ + '/var/task/index.js': 'debug-id-123', + '/var/task/utils.js': 'debug-id-456', + }); + }); + + it('should build map from native _debugIds', () => { + (globalThis as any)._debugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'native-debug-id-123', + }; + + const map = getFilenameToDebugIdMap(mockStackParser); + + expect(map).toEqual({ + '/var/task/index.js': 'native-debug-id-123', + }); + }); + + it('should prioritize native _debugIds over _sentryDebugIds', () => { + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'sentry-debug-id', + }; + (globalThis as any)._debugIds = { + 'at mockFunction (/var/task/index.js:1:1)': 'native-debug-id', + }; + + const map = getFilenameToDebugIdMap(mockStackParser); + + expect(map['/var/task/index.js']).toBe('native-debug-id'); + }); +}); From 5c08507335754b5f866ea795da2c5ae667868707 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Wed, 14 Jan 2026 16:01:41 +0100 Subject: [PATCH 02/10] Fix for windows and try and reduce bundle impact --- packages/core/src/utils/debug-ids.ts | 16 +++- packages/core/src/utils/node-stack-trace.ts | 10 +-- packages/core/src/utils/stacktrace.ts | 12 +++ .../core/test/lib/utils/debug-ids.test.ts | 80 ++++++++++++------- 4 files changed, 79 insertions(+), 39 deletions(-) diff --git a/packages/core/src/utils/debug-ids.ts b/packages/core/src/utils/debug-ids.ts index 7b11e4ebc280..32396b5bbcac 100644 --- a/packages/core/src/utils/debug-ids.ts +++ b/packages/core/src/utils/debug-ids.ts @@ -1,5 +1,6 @@ import type { DebugImage } from '../types-hoist/debugMeta'; import type { StackParser } from '../types-hoist/stacktrace'; +import { normalizeStackTracePath } from './stacktrace'; import { GLOBAL_OBJ } from './worldwide'; type StackString = string; @@ -10,6 +11,17 @@ let lastSentryKeysCount: number | undefined; let lastNativeKeysCount: number | undefined; let cachedFilenameDebugIds: Record | undefined; +/** + * Clears the cached debug ID mappings. + * Useful for testing or when the global debug ID state changes. + */ +export function clearDebugIdCache(): void { + parsedStackResults = undefined; + lastSentryKeysCount = undefined; + lastNativeKeysCount = undefined; + cachedFilenameDebugIds = undefined; +} + /** * Returns a map of filenames to debug identifiers. * Supports both proprietary _sentryDebugIds and native _debugIds (e.g., from Vercel) formats. @@ -101,8 +113,8 @@ export function getDebugImagesForResources( const images: DebugImage[] = []; for (const path of resource_paths) { - if (path) { - const normalizedPath = path.startsWith('file://') ? path.slice(7) : path; + const normalizedPath = normalizeStackTracePath(path); + if (normalizedPath) { if (filenameDebugIdMap[normalizedPath]) { images.push({ type: 'sourcemap', diff --git a/packages/core/src/utils/node-stack-trace.ts b/packages/core/src/utils/node-stack-trace.ts index 0cecd3dbf1e9..1132471b0e8f 100644 --- a/packages/core/src/utils/node-stack-trace.ts +++ b/packages/core/src/utils/node-stack-trace.ts @@ -22,7 +22,7 @@ // THE SOFTWARE. import type { StackLineParser, StackLineParserFn } from '../types-hoist/stacktrace'; -import { UNKNOWN_FUNCTION } from './stacktrace'; +import { normalizeStackTracePath, UNKNOWN_FUNCTION } from './stacktrace'; export type GetModuleFn = (filename: string | undefined) => string | undefined; @@ -55,7 +55,6 @@ export function node(getModule?: GetModuleFn): StackLineParserFn { const FULL_MATCH = /at (?:async )?(?:(.+?)\s+\()?(?:(.+):(\d+):(\d+)?|([^)]+))\)?/; const DATA_URI_MATCH = /at (?:async )?(.+?) \(data:(.*?),/; - // eslint-disable-next-line complexity return (line: string) => { const dataUriMatch = line.match(DATA_URI_MATCH); if (dataUriMatch) { @@ -109,14 +108,9 @@ export function node(getModule?: GetModuleFn): StackLineParserFn { functionName = typeName ? `${typeName}.${methodName}` : methodName; } - let filename = lineMatch[2]?.startsWith('file://') ? lineMatch[2].slice(7) : lineMatch[2]; + let filename = normalizeStackTracePath(lineMatch[2]); const isNative = lineMatch[5] === 'native'; - // If it's a Windows path, trim the leading slash so that `/C:/foo` becomes `C:/foo` - if (filename?.match(/\/[A-Z]:/)) { - filename = filename.slice(1); - } - if (!filename && lineMatch[5] && !isNative) { filename = lineMatch[5]; } diff --git a/packages/core/src/utils/stacktrace.ts b/packages/core/src/utils/stacktrace.ts index 6b50caf48b30..16a32ede4e58 100644 --- a/packages/core/src/utils/stacktrace.ts +++ b/packages/core/src/utils/stacktrace.ts @@ -177,3 +177,15 @@ export function getVueInternalName(value: VueViewModel | VNode): string { return isVNode ? '[VueVNode]' : '[VueViewModel]'; } + +/** + * Normalizes stack line paths by removing file:// prefix and leading slashes for Windows paths + */ +export function normalizeStackTracePath(path: string | undefined): string | undefined { + let filename = path?.startsWith('file://') ? path.slice(7) : path; + // If it's a Windows path, trim the leading slash so that `/C:/foo` becomes `C:/foo` + if (filename?.match(/\/[A-Z]:/)) { + filename = filename.slice(1); + } + return filename; +} diff --git a/packages/core/test/lib/utils/debug-ids.test.ts b/packages/core/test/lib/utils/debug-ids.test.ts index 6235c37cf628..45ff58c82565 100644 --- a/packages/core/test/lib/utils/debug-ids.test.ts +++ b/packages/core/test/lib/utils/debug-ids.test.ts @@ -1,21 +1,16 @@ import { beforeEach, describe, expect, it } from 'vitest'; -import type { StackParser } from '../../../src/types-hoist/stacktrace'; -import { getDebugImagesForResources, getFilenameToDebugIdMap } from '../../../src/utils/debug-ids'; +import { nodeStackLineParser } from '../../../src'; +import { clearDebugIdCache, getDebugImagesForResources, getFilenameToDebugIdMap } from '../../../src/utils/debug-ids'; +import { createStackParser } from '../../../src/utils/stacktrace'; -describe('getDebugImagesForResources', () => { - const mockStackParser: StackParser = (stack: string) => { - // Simple mock that extracts filename from a stack string - const match = stack.match(/at .* \((.*?):\d+:\d+\)/); - if (match) { - return [{ filename: match[1], function: 'mockFunction', lineno: 1, colno: 1 }]; - } - return []; - }; +const nodeStackParser = createStackParser(nodeStackLineParser()); +describe('getDebugImagesForResources', () => { beforeEach(() => { // Clear any existing debug ID maps delete (globalThis as any)._sentryDebugIds; delete (globalThis as any)._debugIds; + clearDebugIdCache(); }); it('should return debug images for resources without file:// prefix', () => { @@ -25,7 +20,7 @@ describe('getDebugImagesForResources', () => { }; const resources = ['/var/task/index.js']; - const images = getDebugImagesForResources(mockStackParser, resources); + const images = getDebugImagesForResources(nodeStackParser, resources); expect(images).toHaveLength(1); expect(images[0]).toEqual({ @@ -43,7 +38,7 @@ describe('getDebugImagesForResources', () => { // V8 profiler returns resources WITH file:// prefix const resources = ['file:///var/task/index.js']; - const images = getDebugImagesForResources(mockStackParser, resources); + const images = getDebugImagesForResources(nodeStackParser, resources); expect(images).toHaveLength(1); expect(images[0]).toEqual({ @@ -60,7 +55,7 @@ describe('getDebugImagesForResources', () => { }; const resources = ['file:///var/task/index.js', '/var/task/utils.js']; - const images = getDebugImagesForResources(mockStackParser, resources); + const images = getDebugImagesForResources(nodeStackParser, resources); expect(images).toHaveLength(2); expect(images[0]).toEqual({ @@ -81,14 +76,14 @@ describe('getDebugImagesForResources', () => { }; const resources = ['file:///var/task/other.js']; - const images = getDebugImagesForResources(mockStackParser, resources); + const images = getDebugImagesForResources(nodeStackParser, resources); expect(images).toHaveLength(0); }); it('should return empty array when no debug IDs are registered', () => { const resources = ['file:///var/task/index.js']; - const images = getDebugImagesForResources(mockStackParser, resources); + const images = getDebugImagesForResources(nodeStackParser, resources); expect(images).toHaveLength(0); }); @@ -99,28 +94,55 @@ describe('getDebugImagesForResources', () => { }; const resources: string[] = []; - const images = getDebugImagesForResources(mockStackParser, resources); + const images = getDebugImagesForResources(nodeStackParser, resources); expect(images).toHaveLength(0); }); + + it('should handle Windows paths with file:// prefix', () => { + // Stack parser normalizes Windows paths: file:///C:/foo.js -> C:/foo.js + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (C:/Users/dev/project/index.js:1:1)': 'debug-id-win-123', + }; + + // V8 profiler returns Windows paths with file:// prefix + const resources = ['file:///C:/Users/dev/project/index.js']; + const images = getDebugImagesForResources(nodeStackParser, resources); + + expect(images).toHaveLength(1); + expect(images[0]).toEqual({ + type: 'sourcemap', + code_file: 'file:///C:/Users/dev/project/index.js', + debug_id: 'debug-id-win-123', + }); + }); + + it('should handle Windows paths without file:// prefix', () => { + (globalThis as any)._sentryDebugIds = { + 'at mockFunction (C:/Users/dev/project/index.js:1:1)': 'debug-id-win-123', + }; + + const resources = ['C:/Users/dev/project/index.js']; + const images = getDebugImagesForResources(nodeStackParser, resources); + + expect(images).toHaveLength(1); + expect(images[0]).toEqual({ + type: 'sourcemap', + code_file: 'C:/Users/dev/project/index.js', + debug_id: 'debug-id-win-123', + }); + }); }); describe('getFilenameToDebugIdMap', () => { - const mockStackParser: StackParser = (stack: string) => { - const match = stack.match(/at .* \((.*?):\d+:\d+\)/); - if (match) { - return [{ filename: match[1], function: 'mockFunction', lineno: 1, colno: 1 }]; - } - return []; - }; - beforeEach(() => { delete (globalThis as any)._sentryDebugIds; delete (globalThis as any)._debugIds; + clearDebugIdCache(); }); it('should return empty object when no debug IDs are registered', () => { - const map = getFilenameToDebugIdMap(mockStackParser); + const map = getFilenameToDebugIdMap(nodeStackParser); expect(map).toEqual({}); }); @@ -130,7 +152,7 @@ describe('getFilenameToDebugIdMap', () => { 'at anotherFunction (/var/task/utils.js:10:5)': 'debug-id-456', }; - const map = getFilenameToDebugIdMap(mockStackParser); + const map = getFilenameToDebugIdMap(nodeStackParser); expect(map).toEqual({ '/var/task/index.js': 'debug-id-123', @@ -143,7 +165,7 @@ describe('getFilenameToDebugIdMap', () => { 'at mockFunction (/var/task/index.js:1:1)': 'native-debug-id-123', }; - const map = getFilenameToDebugIdMap(mockStackParser); + const map = getFilenameToDebugIdMap(nodeStackParser); expect(map).toEqual({ '/var/task/index.js': 'native-debug-id-123', @@ -158,7 +180,7 @@ describe('getFilenameToDebugIdMap', () => { 'at mockFunction (/var/task/index.js:1:1)': 'native-debug-id', }; - const map = getFilenameToDebugIdMap(mockStackParser); + const map = getFilenameToDebugIdMap(nodeStackParser); expect(map['/var/task/index.js']).toBe('native-debug-id'); }); From 6c9317c1ce22e2173fcf3c8d6f66739212101550 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Tue, 20 Jan 2026 00:21:50 +0200 Subject: [PATCH 03/10] fix(nextjs): Add ALS runner fallbacks for serverless environments (#18889) ### Summary This was introduced by cache components workaround in #18700. When deploying a Next.js app on Cloudflare Workers and I presume other serverless environments, you would get this error ``` NextJS request failed. Error: Cannot call this AsyncLocalStorage bound function outside of the request in which it was created. ``` This happens because the snapshot becomes stale in the next request invocation. ### Solution This is more of a best-effort workaround. I added a retry logic based on some criteria, if the first attempt fails due to ALS error then it will grab a new snapshot and re-run it, if that also fails, then it will run the callback directly. the flow goes like this: ```mermaid flowchart TD A[callback invoked] --> B{Try cached snapshot} B -->|Success| C[Return result] B -->|Error| D{Is AsyncLocalStorage error?} D -->|No| E[Rethrow error] D -->|Yes| F[Get fresh snapshot] F --> G{Fresh snapshot available?} G -->|No| H[Execute callback directly] G -->|Yes| I[Update cached snapshot] I --> J{Try fresh snapshot} J -->|Success| K[Return result] J -->|Error| L{Is AsyncLocalStorage error?} L -->|No| M[Rethrow error] L -->|Yes| N[Execute callback directly] H --> O[Return result] N --> O style C fill:#90EE90 style K fill:#90EE90 style O fill:#90EE90 style E fill:#FFB6C1 style M fill:#FFB6C1 ``` Closes #18842 --- .../server/prepareSafeIdGeneratorContext.ts | 76 +++++++++++++++---- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/packages/nextjs/src/server/prepareSafeIdGeneratorContext.ts b/packages/nextjs/src/server/prepareSafeIdGeneratorContext.ts index bd262eb736e1..b060ae040cfe 100644 --- a/packages/nextjs/src/server/prepareSafeIdGeneratorContext.ts +++ b/packages/nextjs/src/server/prepareSafeIdGeneratorContext.ts @@ -1,8 +1,4 @@ -import { - type _INTERNAL_RandomSafeContextRunner as _INTERNAL_RandomSafeContextRunner, - debug, - GLOBAL_OBJ, -} from '@sentry/core'; +import { type _INTERNAL_RandomSafeContextRunner as RandomSafeContextRunner, debug, GLOBAL_OBJ } from '@sentry/core'; import { DEBUG_BUILD } from '../common/debug-build'; // Inline AsyncLocalStorage interface from current types @@ -15,17 +11,53 @@ type OriginalAsyncLocalStorage = typeof AsyncLocalStorage; */ export function prepareSafeIdGeneratorContext(): void { const sym = Symbol.for('__SENTRY_SAFE_RANDOM_ID_WRAPPER__'); - const globalWithSymbol: typeof GLOBAL_OBJ & { [sym]?: _INTERNAL_RandomSafeContextRunner } = GLOBAL_OBJ; - const als = getAsyncLocalStorage(); - if (!als || typeof als.snapshot !== 'function') { - DEBUG_BUILD && - debug.warn( - '[@sentry/nextjs] No AsyncLocalStorage found in the runtime or AsyncLocalStorage.snapshot() is not available, skipping safe random ID generator context preparation, you may see some errors with cache components.', - ); + const globalWithSymbol: typeof GLOBAL_OBJ & { [sym]?: RandomSafeContextRunner } = GLOBAL_OBJ; + + // Get initial snapshot - if unavailable, don't set up the wrapper at all + const initialSnapshot = getAsyncLocalStorageSnapshot(); + if (!initialSnapshot) { return; } - globalWithSymbol[sym] = als.snapshot(); + // We store a wrapper function instead of the raw snapshot because in serverless + // environments (e.g., Cloudflare Workers), the snapshot is bound to the request + // context it was created in. Once that request ends, the snapshot becomes invalid. + // The wrapper catches this and creates a fresh snapshot for the current request context. + let cachedSnapshot: RandomSafeContextRunner = initialSnapshot; + + globalWithSymbol[sym] = (callback: () => T): T => { + try { + return cachedSnapshot(callback); + } catch (error) { + // Only handle AsyncLocalStorage-related errors, rethrow others + if (!isAsyncLocalStorageError(error)) { + throw error; + } + + // Snapshot likely stale, try to get a fresh one and retry + const freshSnapshot = getAsyncLocalStorageSnapshot(); + // No snapshot available, fall back to direct execution + if (!freshSnapshot) { + return callback(); + } + + // Update the cached snapshot + cachedSnapshot = freshSnapshot; + + // Retry the callback with the fresh snapshot + try { + return cachedSnapshot(callback); + } catch (retryError) { + // Only fall back for AsyncLocalStorage errors, rethrow others + if (!isAsyncLocalStorageError(retryError)) { + throw retryError; + } + // If fresh snapshot also fails with ALS error, fall back to direct execution + return callback(); + } + } + }; + DEBUG_BUILD && debug.log('[@sentry/nextjs] Prepared safe random ID generator context'); } @@ -47,3 +79,21 @@ function getAsyncLocalStorage(): OriginalAsyncLocalStorage | undefined { return undefined; } + +function getAsyncLocalStorageSnapshot(): RandomSafeContextRunner | undefined { + const als = getAsyncLocalStorage(); + + if (!als || typeof als.snapshot !== 'function') { + DEBUG_BUILD && + debug.warn( + '[@sentry/nextjs] No AsyncLocalStorage found in the runtime or AsyncLocalStorage.snapshot() is not available, skipping safe random ID generator context preparation, you may see some errors with cache components.', + ); + return undefined; + } + + return als.snapshot(); +} + +function isAsyncLocalStorageError(error: unknown): boolean { + return error instanceof Error && error.message.includes('AsyncLocalStorage'); +} From 2c041b3271146c6092d8b8b707b35ff461b1d4a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:12:03 +0100 Subject: [PATCH 04/10] chore(deps-dev): bump @remix-run/server-runtime from 2.15.2 to 2.17.3 in /packages/remix (#18750) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@remix-run/server-runtime](https://github.com/remix-run/remix/tree/HEAD/packages/remix-server-runtime) from 2.15.2 to 2.17.3.
Release notes

Sourced from @​remix-run/server-runtime's releases.

v2.17.3

See the changelog for the release notes: https://github.com/remix-run/remix/blob/v2/CHANGELOG.md#v2173

v2.17.2

See the changelog for the release notes: https://github.com/remix-run/remix/blob/v2/CHANGELOG.md#v2172

remix v2.17.1

See the changelog for the release notes: https://github.com/remix-run/remix/blob/v2/CHANGELOG.md#v2171

Commits
Maintainer changes

This version was pushed to npm by [GitHub Actions](https://www.npmjs.com/~GitHub Actions), a new releaser for @​remix-run/server-runtime since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@remix-run/server-runtime&package-manager=npm_and_yarn&previous-version=2.15.2&new-version=2.17.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/getsentry/sentry-javascript/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JPeer264 --- packages/remix/package.json | 6 +-- yarn.lock | 91 +++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/packages/remix/package.json b/packages/remix/package.json index 923ef935e18c..7df5342004bd 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -76,9 +76,9 @@ "yargs": "^17.6.0" }, "devDependencies": { - "@remix-run/node": "^2.15.2", - "@remix-run/react": "^2.15.2", - "@remix-run/server-runtime": "2.15.2", + "@remix-run/node": "^2.17.4", + "@remix-run/react": "^2.17.4", + "@remix-run/server-runtime": "^2.17.4", "@types/express": "^4.17.14", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/yarn.lock b/yarn.lock index 9ad1fe308e75..95d612a0b152 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6609,47 +6609,52 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.5.tgz#a6d70ef7a0e71e083ea09b967df0a0ed742bc6ad" integrity sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg== -"@remix-run/node@^2.15.2": - version "2.15.2" - resolved "https://registry.yarnpkg.com/@remix-run/node/-/node-2.15.2.tgz#7ea460335b66a06d22e554a84edf09e2b8879a8a" - integrity sha512-NS/h5uxje7DYCNgcKqKAiUhf0r2HVnoYUBWLyIIMmCUP1ddWurBP6xTPcWzGhEvV/EvguniYi1wJZ5+X8sonWw== +"@remix-run/node@^2.17.4": + version "2.17.4" + resolved "https://registry.yarnpkg.com/@remix-run/node/-/node-2.17.4.tgz#dfcc43106fc631c1bd6644d215d5698eb4958962" + integrity sha512-9A29JaYiGHDEmaiQuD1IlO/TrQxnnkj98GpytihU+Nz6yTt6RwzzyMMqTAoasRd1dPD4OeSaSqbwkcim/eE76Q== dependencies: - "@remix-run/server-runtime" "2.15.2" + "@remix-run/server-runtime" "2.17.4" "@remix-run/web-fetch" "^4.4.2" "@web3-storage/multipart-parser" "^1.0.0" cookie-signature "^1.1.0" source-map-support "^0.5.21" stream-slice "^0.1.2" - undici "^6.11.1" + undici "^6.21.2" -"@remix-run/react@^2.15.2": - version "2.15.2" - resolved "https://registry.yarnpkg.com/@remix-run/react/-/react-2.15.2.tgz#4f57434c120e0b7885d8b737c417b67f72a3a042" - integrity sha512-NAAMsSgoC/sdOgovUewwRCE/RUm3F+MBxxZKfwu3POCNeHaplY5qGkH/y8PUXvdN1EBG7Z0Ko43dyzCfcEy5PA== +"@remix-run/react@^2.17.4": + version "2.17.4" + resolved "https://registry.yarnpkg.com/@remix-run/react/-/react-2.17.4.tgz#128b6505c118e4bf67d919ee7d3991c0f6c65028" + integrity sha512-MeXHacIBoohr9jzec5j/Rmk57xk34korkPDDb0OPHgkdvh20lO5fJoSAcnZfjTIOH+Vsq1ZRQlmvG5PRQ/64Sw== dependencies: - "@remix-run/router" "1.21.0" - "@remix-run/server-runtime" "2.15.2" - react-router "6.28.1" - react-router-dom "6.28.1" - turbo-stream "2.4.0" + "@remix-run/router" "1.23.2" + "@remix-run/server-runtime" "2.17.4" + react-router "6.30.3" + react-router-dom "6.30.3" + turbo-stream "2.4.1" -"@remix-run/router@1.21.0", "@remix-run/router@1.x": +"@remix-run/router@1.21.0": version "1.21.0" resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.21.0.tgz#c65ae4262bdcfe415dbd4f64ec87676e4a56e2b5" integrity sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA== -"@remix-run/server-runtime@2.15.2": - version "2.15.2" - resolved "https://registry.yarnpkg.com/@remix-run/server-runtime/-/server-runtime-2.15.2.tgz#5be945027612c0891748d1788d39fea1ef0ba33c" - integrity sha512-OqiPcvEnnU88B8b1LIWHHkQ3Tz2GDAmQ1RihFNQsbrFKpDsQLkw0lJlnfgKA/uHd0CEEacpfV7C9qqJT3V6Z2g== +"@remix-run/router@1.23.2", "@remix-run/router@1.x": + version "1.23.2" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.23.2.tgz#156c4b481c0bee22a19f7924728a67120de06971" + integrity sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w== + +"@remix-run/server-runtime@2.17.4", "@remix-run/server-runtime@^2.17.4": + version "2.17.4" + resolved "https://registry.yarnpkg.com/@remix-run/server-runtime/-/server-runtime-2.17.4.tgz#00d52eb69e684b13c152ab9ace70b6c00aaeee5f" + integrity sha512-oCsFbPuISgh8KpPKsfBChzjcntvTz5L+ggq9VNYWX8RX3yA7OgQpKspRHOSxb05bw7m0Hx+L1KRHXjf3juKX8w== dependencies: - "@remix-run/router" "1.21.0" + "@remix-run/router" "1.23.2" "@types/cookie" "^0.6.0" "@web3-storage/multipart-parser" "^1.0.0" - cookie "^0.6.0" + cookie "^0.7.2" set-cookie-parser "^2.4.8" source-map "^0.7.3" - turbo-stream "2.4.0" + turbo-stream "2.4.1" "@remix-run/web-blob@^3.1.0": version "3.1.0" @@ -13582,7 +13587,7 @@ cookie@^0.6.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== -cookie@^0.7.1, cookie@~0.7.2: +cookie@^0.7.1, cookie@^0.7.2, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -26340,20 +26345,20 @@ react-refresh@^0.14.0: dependencies: "@remix-run/router" "1.21.0" -react-router-dom@6.28.1: - version "6.28.1" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.28.1.tgz#b78fe452d2cd31919b80e57047a896bfa1509f8c" - integrity sha512-YraE27C/RdjcZwl5UCqF/ffXnZDxpJdk9Q6jw38SZHjXs7NNdpViq2l2c7fO7+4uWaEfcwfGCv3RSg4e1By/fQ== +react-router-dom@6.30.3: + version "6.30.3" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.30.3.tgz#42ae6dc4c7158bfb0b935f162b9621b29dddf740" + integrity sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag== dependencies: - "@remix-run/router" "1.21.0" - react-router "6.28.1" + "@remix-run/router" "1.23.2" + react-router "6.30.3" -react-router@6.28.1: - version "6.28.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.28.1.tgz#f82317ab24eee67d7beb7b304c0378b2b48fa178" - integrity sha512-2omQTA3rkMljmrvvo6WtewGdVh45SpL9hGiCI9uUrwGGfNFDIvGK4gYJsKlJoNVi6AQZcopSCballL+QGOm7fA== +react-router@6.30.3: + version "6.30.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.30.3.tgz#994b3ccdbe0e81fe84d4f998100f62584dfbf1cf" + integrity sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw== dependencies: - "@remix-run/router" "1.21.0" + "@remix-run/router" "1.23.2" react-router@^7.9.2: version "7.9.2" @@ -29958,10 +29963,10 @@ tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== -turbo-stream@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/turbo-stream/-/turbo-stream-2.4.0.tgz#1e4fca6725e90fa14ac4adb782f2d3759a5695f0" - integrity sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g== +turbo-stream@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/turbo-stream/-/turbo-stream-2.4.1.tgz#c1a64397724084c09b0f6ea4a2c528d3f67931f9" + integrity sha512-v8kOJXpG3WoTN/+at8vK7erSzo6nW6CIaeOvNOkHQVDajfz1ZVeSxCbc6tOH4hrGZW7VUCV0TOXd8CPzYnYkrw== twirp-ts@^2.5.0: version "2.5.0" @@ -30288,10 +30293,10 @@ undici@^5.25.4, undici@^5.28.5: dependencies: "@fastify/busboy" "^2.0.0" -undici@^6.11.1, undici@^6.19.2: - version "6.21.3" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.3.tgz#185752ad92c3d0efe7a7d1f6854a50f83b552d7a" - integrity sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw== +undici@^6.19.2, undici@^6.21.2: + version "6.23.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.23.0.tgz#7953087744d9095a96f115de3140ca3828aff3a4" + integrity sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g== unenv@2.0.0-rc.17: version "2.0.0-rc.17" From 9115e19fcbaff18d6ccdc51ef899585034d77764 Mon Sep 17 00:00:00 2001 From: Andrei <168741329+andreiborza@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:22:19 +0100 Subject: [PATCH 05/10] feat(deps): Bump OpenTelemetry dependencies (#18878) - Bump @opentelemetry/context-async-hooks from 2.2.0 to 2.4.0 - Bump @opentelemetry/core from 2.2.0 to 2.4.0 - Bump @opentelemetry/resources from 2.2.0 to 2.4.0 - Bump @opentelemetry/sdk-trace-base from 2.2.0 to 2.4.0 - Bump @opentelemetry/sdk-trace-node from 2.2.0 to 2.4.0 - Bump @opentelemetry/instrumentation from 0.208.0 to 0.210.0 - Bump @opentelemetry/instrumentation-amqplib from 0.55.0 to 0.57.0 - Bump @opentelemetry/instrumentation-connect from 0.52.0 to 0.53.0 - Bump @opentelemetry/instrumentation-dataloader from 0.26.0 to 0.27.0 - Bump @opentelemetry/instrumentation-express from 0.57.0 to 0.58.0 - Bump @opentelemetry/instrumentation-fs from 0.28.0 to 0.29.0 - Bump @opentelemetry/instrumentation-generic-pool from 0.52.0 to 0.53.0 - Bump @opentelemetry/instrumentation-graphql from 0.56.0 to 0.57.0 - Bump @opentelemetry/instrumentation-hapi from 0.55.0 to 0.56.0 - Bump @opentelemetry/instrumentation-http from 0.208.0 to 0.210.0 - Bump @opentelemetry/instrumentation-ioredis from 0.56.0 to 0.58.0 - Bump @opentelemetry/instrumentation-kafkajs from 0.18.0 to 0.19.0 - Bump @opentelemetry/instrumentation-knex from 0.53.0 to 0.54.0 - Bump @opentelemetry/instrumentation-koa from 0.57.0 to 0.58.0 - Bump @opentelemetry/instrumentation-lru-memoizer from 0.53.0 to 0.54.0 - Bump @opentelemetry/instrumentation-mongodb from 0.61.0 to 0.63.0 - Bump @opentelemetry/instrumentation-mongoose from 0.55.0 to 0.56.0 - Bump @opentelemetry/instrumentation-mysql from 0.54.0 to 0.56.0 - Bump @opentelemetry/instrumentation-mysql2 from 0.55.0 to 0.56.0 - Bump @opentelemetry/instrumentation-nestjs-core from 0.55.0 to 0.56.0 - Bump @opentelemetry/instrumentation-pg from 0.61.0 to 0.62.0 - Bump @opentelemetry/instrumentation-redis from 0.57.0 to 0.58.0 - Bump @opentelemetry/instrumentation-tedious from 0.27.0 to 0.29.0 - Bump @opentelemetry/instrumentation-undici from 0.19.0 to 0.20.0 - Bump @opentelemetry/instrumentation-aws-sdk from 0.64.0 to 0.65.0 - Bump @opentelemetry/sdk-node from 0.208.0 to 0.210.0 - Bump @opentelemetry/exporter-trace-otlp-http from 0.208.0 to 0.210.0 Closes #18874 --- .size-limit.js | 2 +- CHANGELOG.md | 36 ++ .../package.json | 12 +- .../package.json | 16 +- .../node-core-express-otel-v2/package.json | 12 +- .../node-otel-custom-sampler/package.json | 2 +- .../node-otel-sdk-node/package.json | 4 +- .../node-otel-without-tracing/package.json | 10 +- .../test-applications/node-otel/package.json | 4 +- .../node-core-integration-tests/package.json | 12 +- packages/aws-serverless/package.json | 4 +- packages/nestjs/package.json | 6 +- packages/node-core/package.json | 18 +- packages/node/package.json | 54 +-- packages/opentelemetry/package.json | 12 +- packages/react-router/package.json | 4 +- packages/remix/package.json | 2 +- packages/vercel-edge/package.json | 6 +- packages/vercel-edge/rollup.npm.config.mjs | 3 + yarn.lock | 314 +++++++++--------- 20 files changed, 289 insertions(+), 244 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index 207fd6a2b85b..725376ac3776 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -287,7 +287,7 @@ module.exports = [ import: createImport('init'), ignore: [...builtinModules, ...nodePrefixedBuiltinModules], gzip: true, - limit: '163 KB', + limit: '164 KB', }, { name: '@sentry/node - without tracing', diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d67c0238bb2..25bc54e75abc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,42 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +### Other Changes + +- feat(deps): Bump OpenTelemetry dependencies + - Bump @opentelemetry/context-async-hooks from 2.2.0 to 2.4.0 + - Bump @opentelemetry/core from 2.2.0 to 2.4.0 + - Bump @opentelemetry/resources from 2.2.0 to 2.4.0 + - Bump @opentelemetry/sdk-trace-base from 2.2.0 to 2.4.0 + - Bump @opentelemetry/sdk-trace-node from 2.2.0 to 2.4.0 + - Bump @opentelemetry/instrumentation from 0.208.0 to 0.210.0 + - Bump @opentelemetry/instrumentation-amqplib from 0.55.0 to 0.57.0 + - Bump @opentelemetry/instrumentation-connect from 0.52.0 to 0.53.0 + - Bump @opentelemetry/instrumentation-dataloader from 0.26.0 to 0.27.0 + - Bump @opentelemetry/instrumentation-express from 0.57.0 to 0.58.0 + - Bump @opentelemetry/instrumentation-fs from 0.28.0 to 0.29.0 + - Bump @opentelemetry/instrumentation-generic-pool from 0.52.0 to 0.53.0 + - Bump @opentelemetry/instrumentation-graphql from 0.56.0 to 0.57.0 + - Bump @opentelemetry/instrumentation-hapi from 0.55.0 to 0.56.0 + - Bump @opentelemetry/instrumentation-http from 0.208.0 to 0.210.0 + - Bump @opentelemetry/instrumentation-ioredis from 0.56.0 to 0.58.0 + - Bump @opentelemetry/instrumentation-kafkajs from 0.18.0 to 0.19.0 + - Bump @opentelemetry/instrumentation-knex from 0.53.0 to 0.54.0 + - Bump @opentelemetry/instrumentation-koa from 0.57.0 to 0.58.0 + - Bump @opentelemetry/instrumentation-lru-memoizer from 0.53.0 to 0.54.0 + - Bump @opentelemetry/instrumentation-mongodb from 0.61.0 to 0.63.0 + - Bump @opentelemetry/instrumentation-mongoose from 0.55.0 to 0.56.0 + - Bump @opentelemetry/instrumentation-mysql from 0.54.0 to 0.56.0 + - Bump @opentelemetry/instrumentation-mysql2 from 0.55.0 to 0.56.0 + - Bump @opentelemetry/instrumentation-nestjs-core from 0.55.0 to 0.56.0 + - Bump @opentelemetry/instrumentation-pg from 0.61.0 to 0.62.0 + - Bump @opentelemetry/instrumentation-redis from 0.57.0 to 0.58.0 + - Bump @opentelemetry/instrumentation-tedious from 0.27.0 to 0.29.0 + - Bump @opentelemetry/instrumentation-undici from 0.19.0 to 0.20.0 + - Bump @opentelemetry/instrumentation-aws-sdk from 0.64.0 to 0.65.0 + - Bump @opentelemetry/sdk-node from 0.208.0 to 0.210.0 + - Bump @opentelemetry/exporter-trace-otlp-http from 0.208.0 to 0.210.0 + ## 10.35.0 ### Important Changes diff --git a/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-custom-sampler/package.json b/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-custom-sampler/package.json index d7c83c773514..62d5bc10cd1a 100644 --- a/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-custom-sampler/package.json +++ b/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-custom-sampler/package.json @@ -12,12 +12,12 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-http": "^0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-trace-node": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-http": "^0.210.0", + "@opentelemetry/resources": "^2.4.0", + "@opentelemetry/sdk-trace-node": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@sentry/node-core": "latest || *", "@sentry/opentelemetry": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-sdk-node/package.json b/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-sdk-node/package.json index c8987cd84f39..49e9bfe01dc8 100644 --- a/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-sdk-node/package.json +++ b/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2-sdk-node/package.json @@ -12,15 +12,15 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-http": "^0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-trace-node": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-http": "^0.210.0", + "@opentelemetry/resources": "^2.4.0", + "@opentelemetry/sdk-trace-node": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", - "@opentelemetry/sdk-node": "^0.208.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.208.0", + "@opentelemetry/sdk-node": "^0.210.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.210.0", "@sentry/node-core": "latest || *", "@sentry/opentelemetry": "latest || *", "@types/express": "4.17.17", diff --git a/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2/package.json b/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2/package.json index c532f50e5ef9..bda2295cc692 100644 --- a/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2/package.json +++ b/dev-packages/e2e-tests/test-applications/node-core-express-otel-v2/package.json @@ -14,12 +14,12 @@ "@sentry/node-core": "latest || *", "@sentry/opentelemetry": "latest || *", "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-http": "^0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-trace-node": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-http": "^0.210.0", + "@opentelemetry/resources": "^2.4.0", + "@opentelemetry/sdk-trace-node": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@types/express": "^4.17.21", "@types/node": "^18.19.1", diff --git a/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json b/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json index 85fc9b85de85..681a10ccc39d 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/sdk-trace-node": "^2.1.0", + "@opentelemetry/sdk-trace-node": "^2.4.0", "@sentry/node": "latest || *", "@sentry/opentelemetry": "latest || *", "@types/express": "4.17.17", diff --git a/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json b/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json index 709d597b19af..cadd3c29470c 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json @@ -11,8 +11,8 @@ "test:assert": "pnpm test" }, "dependencies": { - "@opentelemetry/sdk-node": "0.208.0", - "@opentelemetry/exporter-trace-otlp-http": "0.208.0", + "@opentelemetry/sdk-node": "0.210.0", + "@opentelemetry/exporter-trace-otlp-http": "0.210.0", "@sentry/node": "latest || *", "@types/express": "4.17.17", "@types/node": "^18.19.1", diff --git a/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json b/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json index a66c60146c65..a445a9ef4aac 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json @@ -12,11 +12,11 @@ }, "dependencies": { "@opentelemetry/api": "1.9.0", - "@opentelemetry/sdk-trace-node": "2.2.0", - "@opentelemetry/exporter-trace-otlp-http": "0.208.0", - "@opentelemetry/instrumentation-undici": "0.13.2", - "@opentelemetry/instrumentation-http": "0.208.0", - "@opentelemetry/instrumentation": "0.208.0", + "@opentelemetry/sdk-trace-node": "2.4.0", + "@opentelemetry/exporter-trace-otlp-http": "0.210.0", + "@opentelemetry/instrumentation-undici": "0.20.0", + "@opentelemetry/instrumentation-http": "0.210.0", + "@opentelemetry/instrumentation": "0.210.0", "@sentry/node": "latest || *", "@types/express": "4.17.17", "@types/node": "^18.19.1", diff --git a/dev-packages/e2e-tests/test-applications/node-otel/package.json b/dev-packages/e2e-tests/test-applications/node-otel/package.json index 0b202bd80556..f13c0cdb896e 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel/package.json @@ -11,8 +11,8 @@ "test:assert": "pnpm test" }, "dependencies": { - "@opentelemetry/sdk-node": "0.208.0", - "@opentelemetry/exporter-trace-otlp-http": "0.208.0", + "@opentelemetry/sdk-node": "0.210.0", + "@opentelemetry/exporter-trace-otlp-http": "0.210.0", "@sentry/node": "latest || *", "@types/express": "4.17.17", "@types/node": "^18.19.1", diff --git a/dev-packages/node-core-integration-tests/package.json b/dev-packages/node-core-integration-tests/package.json index 6157ec378d4f..a6448dd06030 100644 --- a/dev-packages/node-core-integration-tests/package.json +++ b/dev-packages/node-core-integration-tests/package.json @@ -27,12 +27,12 @@ "@nestjs/core": "^11", "@nestjs/platform-express": "^11", "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-http": "0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-trace-base": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-http": "0.210.0", + "@opentelemetry/resources": "^2.4.0", + "@opentelemetry/sdk-trace-base": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@sentry/core": "10.35.0", "@sentry/node-core": "10.35.0", diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index aa93a915f338..56174588929c 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -66,8 +66,8 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-aws-sdk": "0.64.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-aws-sdk": "0.65.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@sentry/core": "10.35.0", "@sentry/node": "10.35.0", diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index 38838303b35c..67a0afa84c2e 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -45,9 +45,9 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-nestjs-core": "0.55.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-nestjs-core": "0.56.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@sentry/core": "10.35.0", "@sentry/node": "10.35.0" diff --git a/packages/node-core/package.json b/packages/node-core/package.json index de16a80e79d7..bc6b4eed4b5e 100644 --- a/packages/node-core/package.json +++ b/packages/node-core/package.json @@ -58,11 +58,11 @@ }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0 || ^2.2.0", - "@opentelemetry/core": "^1.30.1 || ^2.1.0 || ^2.2.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", + "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/instrumentation": ">=0.57.1 <1", - "@opentelemetry/resources": "^1.30.1 || ^2.1.0 || ^2.2.0", - "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0 || ^2.2.0", + "@opentelemetry/resources": "^1.30.1 || ^2.1.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.37.0" }, "dependencies": { @@ -74,11 +74,11 @@ "devDependencies": { "@apm-js-collab/code-transformer": "^0.8.2", "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-trace-base": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/resources": "^2.4.0", + "@opentelemetry/sdk-trace-base": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@types/node": "^18.19.1" }, diff --git a/packages/node/package.json b/packages/node/package.json index c54ee3edc9f9..853d1d48d4d6 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -66,33 +66,33 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", - "@opentelemetry/instrumentation-amqplib": "0.55.0", - "@opentelemetry/instrumentation-connect": "0.52.0", - "@opentelemetry/instrumentation-dataloader": "0.26.0", - "@opentelemetry/instrumentation-express": "0.57.0", - "@opentelemetry/instrumentation-fs": "0.28.0", - "@opentelemetry/instrumentation-generic-pool": "0.52.0", - "@opentelemetry/instrumentation-graphql": "0.56.0", - "@opentelemetry/instrumentation-hapi": "0.55.0", - "@opentelemetry/instrumentation-http": "0.208.0", - "@opentelemetry/instrumentation-ioredis": "0.56.0", - "@opentelemetry/instrumentation-kafkajs": "0.18.0", - "@opentelemetry/instrumentation-knex": "0.53.0", - "@opentelemetry/instrumentation-koa": "0.57.0", - "@opentelemetry/instrumentation-lru-memoizer": "0.53.0", - "@opentelemetry/instrumentation-mongodb": "0.61.0", - "@opentelemetry/instrumentation-mongoose": "0.55.0", - "@opentelemetry/instrumentation-mysql": "0.54.0", - "@opentelemetry/instrumentation-mysql2": "0.55.0", - "@opentelemetry/instrumentation-pg": "0.61.0", - "@opentelemetry/instrumentation-redis": "0.57.0", - "@opentelemetry/instrumentation-tedious": "0.27.0", - "@opentelemetry/instrumentation-undici": "0.19.0", - "@opentelemetry/resources": "^2.2.0", - "@opentelemetry/sdk-trace-base": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", + "@opentelemetry/instrumentation-amqplib": "0.57.0", + "@opentelemetry/instrumentation-connect": "0.53.0", + "@opentelemetry/instrumentation-dataloader": "0.27.0", + "@opentelemetry/instrumentation-express": "0.58.0", + "@opentelemetry/instrumentation-fs": "0.29.0", + "@opentelemetry/instrumentation-generic-pool": "0.53.0", + "@opentelemetry/instrumentation-graphql": "0.57.0", + "@opentelemetry/instrumentation-hapi": "0.56.0", + "@opentelemetry/instrumentation-http": "0.210.0", + "@opentelemetry/instrumentation-ioredis": "0.58.0", + "@opentelemetry/instrumentation-kafkajs": "0.19.0", + "@opentelemetry/instrumentation-knex": "0.54.0", + "@opentelemetry/instrumentation-koa": "0.58.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.54.0", + "@opentelemetry/instrumentation-mongodb": "0.63.0", + "@opentelemetry/instrumentation-mongoose": "0.56.0", + "@opentelemetry/instrumentation-mysql": "0.56.0", + "@opentelemetry/instrumentation-mysql2": "0.56.0", + "@opentelemetry/instrumentation-pg": "0.62.0", + "@opentelemetry/instrumentation-redis": "0.58.0", + "@opentelemetry/instrumentation-tedious": "0.29.0", + "@opentelemetry/instrumentation-undici": "0.20.0", + "@opentelemetry/resources": "^2.4.0", + "@opentelemetry/sdk-trace-base": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@prisma/instrumentation": "6.19.0", "@sentry/core": "10.35.0", diff --git a/packages/opentelemetry/package.json b/packages/opentelemetry/package.json index 28a12de398c6..f8a5e3a391f4 100644 --- a/packages/opentelemetry/package.json +++ b/packages/opentelemetry/package.json @@ -43,16 +43,16 @@ }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0 || ^2.2.0", - "@opentelemetry/core": "^1.30.1 || ^2.1.0 || ^2.2.0", - "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0 || ^2.2.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", + "@opentelemetry/core": "^1.30.1 || ^2.1.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.37.0" }, "devDependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.2.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/sdk-trace-base": "^2.2.0", + "@opentelemetry/context-async-hooks": "^2.4.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/sdk-trace-base": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0" }, "scripts": { diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 307ea8dd48f6..9f8ec57975ea 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -46,8 +46,8 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/instrumentation": "^0.208.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/instrumentation": "^0.210.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@sentry/browser": "10.35.0", "@sentry/cli": "^2.58.4", diff --git a/packages/remix/package.json b/packages/remix/package.json index 7df5342004bd..4cf7f1e83e1f 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -65,7 +65,7 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/instrumentation": "^0.208.0", + "@opentelemetry/instrumentation": "^0.210.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@remix-run/router": "1.x", "@sentry/cli": "^2.58.2", diff --git a/packages/vercel-edge/package.json b/packages/vercel-edge/package.json index 22d49718de4d..af20da5dec82 100644 --- a/packages/vercel-edge/package.json +++ b/packages/vercel-edge/package.json @@ -40,13 +40,13 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/resources": "^2.2.0", + "@opentelemetry/resources": "^2.4.0", "@sentry/core": "10.35.0" }, "devDependencies": { "@edge-runtime/types": "3.0.1", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/sdk-trace-base": "^2.2.0", + "@opentelemetry/core": "^2.4.0", + "@opentelemetry/sdk-trace-base": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@sentry/opentelemetry": "10.35.0" }, diff --git a/packages/vercel-edge/rollup.npm.config.mjs b/packages/vercel-edge/rollup.npm.config.mjs index d8f1704e2f8a..d19ef3a09e2f 100644 --- a/packages/vercel-edge/rollup.npm.config.mjs +++ b/packages/vercel-edge/rollup.npm.config.mjs @@ -43,6 +43,9 @@ const baseConfig = makeBaseNPMConfig({ plugins.makeJsonPlugin(), // Needed because `require-in-the-middle` imports json via require replace({ preventAssignment: true, + // Use negative lookahead/lookbehind instead of word boundaries so `process.argv0` is also replaced in + // `process.argv0.length` (where `.` follows). Default `\b` delimiters don't match before `.`. + delimiters: ['(?=0.52.0 <1", "@opentelemetry/instrumentation@^0.208.0": - version "0.208.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.208.0.tgz#d764f8e4329dad50804e2e98f010170c14c4ce8f" - integrity sha512-Eju0L4qWcQS+oXxi6pgh7zvE2byogAkcsVv0OjHF/97iOz1N/aKE6etSGowYkie+YA1uo6DNwdSxaaNnLvcRlA== +"@opentelemetry/instrumentation@0.210.0", "@opentelemetry/instrumentation@>=0.52.0 <1", "@opentelemetry/instrumentation@^0.210.0": + version "0.210.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.210.0.tgz#3c9cf77072b7c7796fffcb04e19cad2976a4afbf" + integrity sha512-sLMhyHmW9katVaLUOKpfCnxSGhZq2t1ReWgwsu2cSgxmDVMB690H9TanuexanpFI94PJaokrqbp8u9KYZDUT5g== dependencies: - "@opentelemetry/api-logs" "0.208.0" + "@opentelemetry/api-logs" "0.210.0" import-in-the-middle "^2.0.0" require-in-the-middle "^8.0.0" @@ -6203,21 +6209,21 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz#cefa4f3e79db1cd54f19e233b7dfb56621143955" integrity sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA== -"@opentelemetry/resources@2.2.0", "@opentelemetry/resources@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.2.0.tgz#b90a950ad98551295b76ea8a0e7efe45a179badf" - integrity sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A== +"@opentelemetry/resources@2.4.0", "@opentelemetry/resources@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.4.0.tgz#51188708204ba888685de019286a3969508c444d" + integrity sha512-RWvGLj2lMDZd7M/5tjkI/2VHMpXebLgPKvBUd9LRasEWR2xAynDwEYZuLvY9P2NGG73HF07jbbgWX2C9oavcQg== dependencies: - "@opentelemetry/core" "2.2.0" + "@opentelemetry/core" "2.4.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/sdk-trace-base@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz#ddef9a0afd01a623d8625a3529f2137b05e67d0b" - integrity sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw== +"@opentelemetry/sdk-trace-base@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.4.0.tgz#0ab37a996cb574e7efc94e58fc759cb4a8df8401" + integrity sha512-WH0xXkz/OHORDLKqaxcUZS0X+t1s7gGlumr2ebiEgNZQl2b0upK2cdoD0tatf7l8iP74woGJ/Kmxe82jdvcWRw== dependencies: - "@opentelemetry/core" "2.2.0" - "@opentelemetry/resources" "2.2.0" + "@opentelemetry/core" "2.4.0" + "@opentelemetry/resources" "2.4.0" "@opentelemetry/semantic-conventions" "^1.29.0" "@opentelemetry/semantic-conventions@^1.24.0", "@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.30.0", "@opentelemetry/semantic-conventions@^1.33.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0", "@opentelemetry/semantic-conventions@^1.36.0", "@opentelemetry/semantic-conventions@^1.37.0": @@ -8987,10 +8993,10 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb" integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g== -"@types/pg-pool@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.6.tgz#1376d9dc5aec4bb2ec67ce28d7e9858227403c77" - integrity sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ== +"@types/pg-pool@2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.7.tgz#c17945a74472d9a3beaf8e66d5aa6fc938328734" + integrity sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng== dependencies: "@types/pg" "*" From 2f0d9dce1da79a2ae2ce64f2d0141189f9eeaeee Mon Sep 17 00:00:00 2001 From: Andrei <168741329+andreiborza@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:30:07 +0100 Subject: [PATCH 06/10] feat(opentelemetry): Support `db.system.name` attribute for database spans (#18902) Supports the now stable `db.system.name` semantic convention attribute alongside the deprecated `db.system` attribute when identifying database spans. Closes #18903 (added automatically) --- .../src/utils/parseSpanDescription.ts | 3 +- .../test/utils/parseSpanDescription.test.ts | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/opentelemetry/src/utils/parseSpanDescription.ts b/packages/opentelemetry/src/utils/parseSpanDescription.ts index 9328320e404f..bb9c5f59acf7 100644 --- a/packages/opentelemetry/src/utils/parseSpanDescription.ts +++ b/packages/opentelemetry/src/utils/parseSpanDescription.ts @@ -1,6 +1,7 @@ import type { Attributes, AttributeValue } from '@opentelemetry/api'; import { SpanKind } from '@opentelemetry/api'; import { + ATTR_DB_SYSTEM_NAME, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_ROUTE, ATTR_URL_FULL, @@ -47,7 +48,7 @@ export function inferSpanData(spanName: string, attributes: SpanAttributes, kind } // eslint-disable-next-line deprecation/deprecation - const dbSystem = attributes[SEMATTRS_DB_SYSTEM]; + const dbSystem = attributes[ATTR_DB_SYSTEM_NAME] || attributes[SEMATTRS_DB_SYSTEM]; const opIsCache = typeof attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'string' && attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP].startsWith('cache.'); diff --git a/packages/opentelemetry/test/utils/parseSpanDescription.test.ts b/packages/opentelemetry/test/utils/parseSpanDescription.test.ts index 1d717b1d7488..529866b8a2ac 100644 --- a/packages/opentelemetry/test/utils/parseSpanDescription.test.ts +++ b/packages/opentelemetry/test/utils/parseSpanDescription.test.ts @@ -2,6 +2,7 @@ import type { Span } from '@opentelemetry/api'; import { SpanKind } from '@opentelemetry/api'; import { + ATTR_DB_SYSTEM_NAME, ATTR_HTTP_ROUTE, SEMATTRS_DB_STATEMENT, SEMATTRS_DB_SYSTEM, @@ -147,6 +148,48 @@ describe('parseSpanDescription', () => { source: 'task', }, ], + [ + 'works with db.system.name (stable attribute)', + { + [ATTR_DB_SYSTEM_NAME]: 'postgresql', + [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + }, + 'test name', + SpanKind.CLIENT, + { + description: 'SELECT * from users', + op: 'db', + source: 'task', + }, + ], + [ + 'works with db.system.name without statement', + { + [ATTR_DB_SYSTEM_NAME]: 'postgresql', + }, + 'test name', + SpanKind.CLIENT, + { + description: 'test name', + op: 'db', + source: 'task', + }, + ], + [ + 'prefers db.system.name over deprecated db.system', + { + [ATTR_DB_SYSTEM_NAME]: 'postgresql', + [SEMATTRS_DB_SYSTEM]: 'mysql', + [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + }, + 'test name', + SpanKind.CLIENT, + { + description: 'SELECT * from users', + op: 'db', + source: 'task', + }, + ], [ 'works with rpc service', { From 469514804669a46c1b2a9b07ffcbfacc280e95a4 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 21 Jan 2026 11:16:14 +0100 Subject: [PATCH 07/10] fix(core): Sanitize data URLs in `http.client` spans (#18896) Our `http.client` span instrumentations currently treat data URLs (blobs or base64 encoded data) like regular raw URLs. While this is in general fine, the problem is that this leads to incredibly long span names and attribute values, especially because the URL is sent in up to three different attributes per span. This makes Relay reject the the sent events due to exceeding size limits. This patch extracts the already existing stack trace URL sanitization logic for data URLs and apply it to `http.client` spans and attributes --- .size-limit.js | 2 +- .../tracing/request/fetch-data-url/init.js | 10 ++ .../tracing/request/fetch-data-url/subject.js | 6 + .../tracing/request/fetch-data-url/test.ts | 35 ++++++ .../tracing/request/xhr-data-url/init.js | 10 ++ .../tracing/request/xhr-data-url/subject.js | 5 + .../tracing/request/xhr-data-url/test.ts | 30 +++++ .../src/integrations/globalhandlers.ts | 14 +-- packages/browser/src/tracing/request.ts | 9 +- packages/core/src/fetch.ts | 26 +++- packages/core/src/index.ts | 1 + packages/core/src/utils/url.ts | 36 ++++++ packages/core/test/lib/utils/url.test.ts | 117 ++++++++++++++++++ packages/node/src/integrations/http.ts | 17 ++- packages/node/src/integrations/node-fetch.ts | 25 +++- 15 files changed, 324 insertions(+), 19 deletions(-) create mode 100644 dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/init.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/subject.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/test.ts create mode 100644 dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/init.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/subject.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/test.ts diff --git a/.size-limit.js b/.size-limit.js index 725376ac3776..9141676873a1 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -38,7 +38,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'browserTracingIntegration'), gzip: true, - limit: '42 KB', + limit: '43 KB', }, { name: '@sentry/browser (incl. Tracing, Profiling)', diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/init.js b/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/init.js new file mode 100644 index 000000000000..5ab240338c8c --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/init.js @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + integrations: [Sentry.browserTracingIntegration()], + tracesSampleRate: 1, + autoSessionTracking: false, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/subject.js b/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/subject.js new file mode 100644 index 000000000000..63d2d14fbd43 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/subject.js @@ -0,0 +1,6 @@ +// Fetch a data URL to verify that the span name and attributes are sanitized +// Data URLs are used for inline resources, e.g., Web Workers with inline scripts +const dataUrl = 'data:text/plain;base64,SGVsbG8gV29ybGQh'; +fetch(dataUrl).catch(() => { + // Data URL fetch might fail in some browsers, but the span should still be created +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/test.ts b/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/test.ts new file mode 100644 index 000000000000..46995dd6c152 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/request/fetch-data-url/test.ts @@ -0,0 +1,35 @@ +import { expect } from '@playwright/test'; +import { sentryTest } from '../../../../utils/fixtures'; +import { + envelopeRequestParser, + shouldSkipTracingTest, + waitForTransactionRequestOnUrl, +} from '../../../../utils/helpers'; + +sentryTest('sanitizes data URLs in fetch span name and attributes', async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } + + const url = await getLocalTestUrl({ testDir: __dirname }); + + const req = await waitForTransactionRequestOnUrl(page, url); + const transactionEvent = envelopeRequestParser(req); + + const requestSpans = transactionEvent.spans?.filter(({ op }) => op === 'http.client'); + + expect(requestSpans).toHaveLength(1); + + const span = requestSpans?.[0]; + + const sanitizedUrl = 'data:text/plain,base64,SGVsbG8gV2... [truncated]'; + expect(span?.description).toBe(`GET ${sanitizedUrl}`); + + expect(span?.data).toMatchObject({ + 'http.method': 'GET', + url: sanitizedUrl, + type: 'fetch', + }); + + expect(span?.data?.['http.url']).toBe(sanitizedUrl); +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/init.js b/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/init.js new file mode 100644 index 000000000000..5ab240338c8c --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/init.js @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + integrations: [Sentry.browserTracingIntegration()], + tracesSampleRate: 1, + autoSessionTracking: false, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/subject.js b/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/subject.js new file mode 100644 index 000000000000..76656f862519 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/subject.js @@ -0,0 +1,5 @@ +// XHR request to a data URL to verify that the span name and attributes are sanitized +const dataUrl = 'data:text/plain;base64,SGVsbG8gV29ybGQh'; +const xhr = new XMLHttpRequest(); +xhr.open('GET', dataUrl); +xhr.send(); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/test.ts b/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/test.ts new file mode 100644 index 000000000000..88bce31e1753 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/request/xhr-data-url/test.ts @@ -0,0 +1,30 @@ +import { expect } from '@playwright/test'; +import type { Event } from '@sentry/core'; +import { sentryTest } from '../../../../utils/fixtures'; +import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; + +sentryTest('sanitizes data URLs in XHR span name and attributes', async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } + + const url = await getLocalTestUrl({ testDir: __dirname }); + + const eventData = await getFirstSentryEnvelopeRequest(page, url); + const requestSpans = eventData.spans?.filter(({ op }) => op === 'http.client'); + + expect(requestSpans).toHaveLength(1); + + const span = requestSpans?.[0]; + + const sanitizedUrl = 'data:text/plain,base64,SGVsbG8gV2... [truncated]'; + expect(span?.description).toBe(`GET ${sanitizedUrl}`); + + expect(span?.data).toMatchObject({ + 'http.method': 'GET', + url: sanitizedUrl, + type: 'xhr', + }); + + expect(span?.data?.['http.url']).toBe(sanitizedUrl); +}); diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index 6bada802b98e..c8cd806d0062 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -9,6 +9,7 @@ import { getLocationHref, isPrimitive, isString, + stripDataUrlContent, UNKNOWN_FUNCTION, } from '@sentry/core'; import type { BrowserClient } from '../client'; @@ -208,14 +209,13 @@ function getFilenameFromUrl(url: string | undefined): string | undefined { return undefined; } - // stack frame urls can be data urls, for example when initializing a Worker with a base64 encoded script - // in this case we just show the data prefix and mime type to avoid too long raw data urls + // Strip data URL content to avoid long base64 strings in stack frames + // (e.g. when initializing a Worker with a base64 encoded script) + // Don't include data prefix for filenames as it's not useful for stack traces + // Wrap with < > to indicate it's a placeholder if (url.startsWith('data:')) { - const match = url.match(/^data:([^;]+)/); - const mimeType = match ? match[1] : 'text/javascript'; - const isBase64 = url.includes('base64,'); - return ``; + return `<${stripDataUrlContent(url, false)}>`; } - return url; // it's fine to not truncate it as it's not put in a regex (https://codeql.github.com/codeql-query-help/javascript/js-polynomial-redos) + return url; } diff --git a/packages/browser/src/tracing/request.ts b/packages/browser/src/tracing/request.ts index 025b08b12168..0c0e30629436 100644 --- a/packages/browser/src/tracing/request.ts +++ b/packages/browser/src/tracing/request.ts @@ -23,6 +23,7 @@ import { spanToJSON, startInactiveSpan, stringMatchesSomePattern, + stripDataUrlContent, stripUrlQueryAndFragment, } from '@sentry/core'; import type { XhrHint } from '@sentry-internal/browser-utils'; @@ -199,7 +200,7 @@ export function instrumentOutgoingRequests(client: Client, _options?: Partial @@ -317,9 +322,22 @@ function getSpanStartOptions( method: string, spanOrigin: SpanOrigin, ): Parameters[0] { + // Data URLs need special handling because parseStringToURLObject treats them as "relative" + // (no "://"), causing getSanitizedUrlStringFromUrlObject to return just the pathname + // without the "data:" prefix, making later stripDataUrlContent calls ineffective. + // So for data URLs, we strip the content first and use that directly. + if (url.startsWith('data:')) { + const sanitizedUrl = stripDataUrlContent(url); + return { + name: `${method} ${sanitizedUrl}`, + attributes: getFetchSpanAttributes(url, undefined, method, spanOrigin), + }; + } + const parsedUrl = parseStringToURLObject(url); + const sanitizedUrl = parsedUrl ? getSanitizedUrlStringFromUrlObject(parsedUrl) : url; return { - name: parsedUrl ? `${method} ${getSanitizedUrlStringFromUrlObject(parsedUrl)}` : method, + name: `${method} ${sanitizedUrl}`, attributes: getFetchSpanAttributes(url, parsedUrl, method, spanOrigin), }; } @@ -331,7 +349,7 @@ function getFetchSpanAttributes( spanOrigin: SpanOrigin, ): SpanAttributes { const attributes: SpanAttributes = { - url, + url: stripDataUrlContent(url), type: 'fetch', 'http.method': method, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: spanOrigin, @@ -339,7 +357,7 @@ function getFetchSpanAttributes( }; if (parsedUrl) { if (!isURLObjectRelative(parsedUrl)) { - attributes['http.url'] = parsedUrl.href; + attributes['http.url'] = stripDataUrlContent(parsedUrl.href); attributes['server.address'] = parsedUrl.host; } if (parsedUrl.search) { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 0fdd328a42d2..19a83d230155 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -313,6 +313,7 @@ export { getHttpSpanDetailsFromUrlObject, isURLObjectRelative, getSanitizedUrlStringFromUrlObject, + stripDataUrlContent, } from './utils/url'; export { eventFromMessage, diff --git a/packages/core/src/utils/url.ts b/packages/core/src/utils/url.ts index ca09e6e8b5e7..bf0c17dbc278 100644 --- a/packages/core/src/utils/url.ts +++ b/packages/core/src/utils/url.ts @@ -263,3 +263,39 @@ export function getSanitizedUrlString(url: PartialURL): string { return `${protocol ? `${protocol}://` : ''}${filteredHost}${path}`; } + +/** + * Strips the content from a data URL, returning a placeholder with the MIME type. + * + * Data URLs can be very long (e.g. base64 encoded scripts for Web Workers), + * with little valuable information, often leading to envelopes getting dropped due + * to size limit violations. Therefore, we strip data URLs and replace them with a + * placeholder. + * + * @param url - The URL to process + * @param includeDataPrefix - If true, includes the first 10 characters of the data stream + * for debugging (e.g., to identify magic bytes like WASM's AGFzbQ). + * Defaults to true. + * @returns For data URLs, returns a short format like `data:text/javascript;base64,SGVsbG8gV2... [truncated]`. + * For non-data URLs, returns the original URL unchanged. + */ +export function stripDataUrlContent(url: string, includeDataPrefix: boolean = true): string { + if (url.startsWith('data:')) { + // Match the MIME type (everything after 'data:' until the first ';' or ',') + const match = url.match(/^data:([^;,]+)/); + const mimeType = match ? match[1] : 'text/plain'; + const isBase64 = url.includes(';base64,'); + + // Find where the actual data starts (after the comma) + const dataStart = url.indexOf(','); + let dataPrefix = ''; + if (includeDataPrefix && dataStart !== -1) { + const data = url.slice(dataStart + 1); + // Include first 10 chars of data to help identify content (e.g., magic bytes) + dataPrefix = data.length > 10 ? `${data.slice(0, 10)}... [truncated]` : data; + } + + return `data:${mimeType}${isBase64 ? ',base64' : ''}${dataPrefix ? `,${dataPrefix}` : ''}`; + } + return url; +} diff --git a/packages/core/test/lib/utils/url.test.ts b/packages/core/test/lib/utils/url.test.ts index 33364d66daa5..7bdfcfd63804 100644 --- a/packages/core/test/lib/utils/url.test.ts +++ b/packages/core/test/lib/utils/url.test.ts @@ -6,6 +6,7 @@ import { isURLObjectRelative, parseStringToURLObject, parseUrl, + stripDataUrlContent, stripUrlQueryAndFragment, } from '../../../src/utils/url'; @@ -638,3 +639,119 @@ describe('getHttpSpanDetailsFromUrlObject', () => { }); }); }); + +describe('stripDataUrlContent', () => { + it('returns regular URLs unchanged', () => { + expect(stripDataUrlContent('https://example.com/api')).toBe('https://example.com/api'); + expect(stripDataUrlContent('http://localhost:3000/test')).toBe('http://localhost:3000/test'); + expect(stripDataUrlContent('/relative/path')).toBe('/relative/path'); + }); + + it('should be applied BEFORE parseStringToURLObject for data URLs', () => { + // This test documents an important behavior: + // Data URLs are treated as "relative" by parseStringToURLObject because they don't contain "://". + // This means getSanitizedUrlStringFromUrlObject returns just the pathname (without "data:" prefix), + // and stripDataUrlContent won't match since it checks url.startsWith('data:'). + // Therefore, stripDataUrlContent MUST be applied to the original URL before parsing. + const dataUrl = 'data:text/javascript;base64,SGVsbG8gV29ybGQ='; + + // Verify data URLs are treated as relative + const parsedUrl = parseStringToURLObject(dataUrl); + expect(parsedUrl).toBeDefined(); + expect(isURLObjectRelative(parsedUrl!)).toBe(true); + + // getSanitizedUrlStringFromUrlObject returns just the pathname for relative URLs + const sanitizedWithoutStripping = getSanitizedUrlStringFromUrlObject(parsedUrl!); + // The pathname doesn't start with 'data:', so stripDataUrlContent wouldn't work on it + expect(sanitizedWithoutStripping.startsWith('data:')).toBe(false); + // Applying stripDataUrlContent AFTER parsing is ineffective + expect(stripDataUrlContent(sanitizedWithoutStripping)).toBe(sanitizedWithoutStripping); + + // CORRECT approach: strip data URL content FIRST, before any URL parsing + const strippedUrl = stripDataUrlContent(dataUrl); + // Default behavior includes first 10 chars of data for debugging (e.g., magic bytes) + expect(strippedUrl).toBe('data:text/javascript,base64,SGVsbG8gV2... [truncated]'); + // The stripped URL is already sanitized and can be used directly as the span name + }); + + describe('with includeDataPrefix=true (default)', () => { + it('includes first 10 chars of data for base64 data URLs', () => { + // SGVsbG8gV29ybGQ= is "Hello World" in base64 + expect(stripDataUrlContent('data:text/javascript;base64,SGVsbG8gV29ybGQ=')).toBe( + 'data:text/javascript,base64,SGVsbG8gV2... [truncated]', + ); + expect(stripDataUrlContent('data:application/json;base64,eyJrZXkiOiJ2YWx1ZSJ9')).toBe( + 'data:application/json,base64,eyJrZXkiOi... [truncated]', + ); + }); + + it('includes first 10 chars of data for non-base64 data URLs', () => { + expect(stripDataUrlContent('data:text/plain,Hello%20World')).toBe('data:text/plain,Hello%20Wo... [truncated]'); + expect(stripDataUrlContent('data:text/html,

Hello

')).toBe('data:text/html,

Hello<... [truncated]'); + }); + + it('includes all data if less than 10 chars', () => { + expect(stripDataUrlContent('data:text/plain,Hi')).toBe('data:text/plain,Hi'); + expect(stripDataUrlContent('data:text/plain;base64,SGk=')).toBe('data:text/plain,base64,SGk='); + }); + + it('helps identify WASM by magic bytes (AGFzbQ)', () => { + // WASM magic bytes: \0asm -> base64: AGFzbQ + const wasmDataUrl = 'data:application/wasm;base64,AGFzbQEAAAA='; + expect(stripDataUrlContent(wasmDataUrl)).toBe('data:application/wasm,base64,AGFzbQEAAA... [truncated]'); + }); + + it('handles various MIME types', () => { + expect(stripDataUrlContent('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA')).toBe( + 'data:image/png,base64,iVBORw0KGg... [truncated]', + ); + expect(stripDataUrlContent('data:image/svg+xml;base64,PHN2Zz4=')).toBe('data:image/svg+xml,base64,PHN2Zz4='); + }); + + it('defaults to text/plain for data URLs without MIME type', () => { + expect(stripDataUrlContent('data:,Hello')).toBe('data:text/plain,Hello'); + expect(stripDataUrlContent('data:;base64,SGVsbG8=')).toBe('data:text/plain,base64,SGVsbG8='); + }); + + it('handles empty data URLs', () => { + expect(stripDataUrlContent('data:')).toBe('data:text/plain'); + }); + + it('handles very long base64 encoded data URLs', () => { + const longBase64 = 'A'.repeat(10000); + expect(stripDataUrlContent(`data:text/javascript;base64,${longBase64}`)).toBe( + 'data:text/javascript,base64,AAAAAAAAAA... [truncated]', + ); + }); + }); + + describe('with includeDataPrefix=false', () => { + it('strips all content from base64 data URLs', () => { + expect(stripDataUrlContent('data:text/javascript;base64,SGVsbG8gV29ybGQ=', false)).toBe( + 'data:text/javascript,base64', + ); + expect(stripDataUrlContent('data:application/json;base64,eyJrZXkiOiJ2YWx1ZSJ9', false)).toBe( + 'data:application/json,base64', + ); + }); + + it('strips all content from non-base64 data URLs', () => { + expect(stripDataUrlContent('data:text/plain,Hello%20World', false)).toBe('data:text/plain'); + expect(stripDataUrlContent('data:text/html,

Hello

', false)).toBe('data:text/html'); + }); + + it('handles various MIME types', () => { + expect(stripDataUrlContent('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA', false)).toBe( + 'data:image/png,base64', + ); + expect(stripDataUrlContent('data:application/wasm;base64,AGFzbQEAAAA=', false)).toBe( + 'data:application/wasm,base64', + ); + }); + + it('defaults to text/plain for data URLs without MIME type', () => { + expect(stripDataUrlContent('data:,Hello', false)).toBe('data:text/plain'); + expect(stripDataUrlContent('data:;base64,SGVsbG8=', false)).toBe('data:text/plain,base64'); + }); + }); +}); diff --git a/packages/node/src/integrations/http.ts b/packages/node/src/integrations/http.ts index e6c48a6bd550..7c2cadf9eb43 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -3,7 +3,13 @@ import { diag } from '@opentelemetry/api'; import type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'; import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; import type { Span } from '@sentry/core'; -import { defineIntegration, getClient, hasSpansEnabled } from '@sentry/core'; +import { + defineIntegration, + getClient, + hasSpansEnabled, + SEMANTIC_ATTRIBUTE_URL_FULL, + stripDataUrlContent, +} from '@sentry/core'; import type { HTTPModuleRequestIncomingMessage, NodeClient, SentryHttpInstrumentationOptions } from '@sentry/node-core'; import { addOriginToSpan, @@ -282,6 +288,15 @@ function getConfigWithDefaults(options: Partial = {}): HttpInstrume requestHook: (span, req) => { addOriginToSpan(span, 'auto.http.otel.http'); + // Sanitize data URLs to prevent long base64 strings in span attributes + const url = getRequestUrl(req as ClientRequest); + if (url.startsWith('data:')) { + const sanitizedUrl = stripDataUrlContent(url); + span.setAttribute('http.url', sanitizedUrl); + span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl); + span.updateName(`${(req as ClientRequest).method || 'GET'} ${sanitizedUrl}`); + } + options.instrumentation?.requestHook?.(span, req); }, responseHook: (span, res) => { diff --git a/packages/node/src/integrations/node-fetch.ts b/packages/node/src/integrations/node-fetch.ts index 6da9fd628bac..b07c1cce8628 100644 --- a/packages/node/src/integrations/node-fetch.ts +++ b/packages/node/src/integrations/node-fetch.ts @@ -1,7 +1,15 @@ import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici'; import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici'; import type { IntegrationFn } from '@sentry/core'; -import { defineIntegration, getClient, hasSpansEnabled, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; +import { + defineIntegration, + getClient, + hasSpansEnabled, + SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_URL_FULL, + stripDataUrlContent, +} from '@sentry/core'; import type { NodeClient } from '@sentry/node-core'; import { generateInstrumentOnce, SentryNodeFetchInstrumentation } from '@sentry/node-core'; import type { NodeClientOptions } from '../types'; @@ -101,7 +109,20 @@ function getConfigWithDefaults(options: Partial = {}): UndiciI return !!shouldIgnore; }, - startSpanHook: () => { + startSpanHook: request => { + const url = getAbsoluteUrl(request.origin, request.path); + + // Sanitize data URLs to prevent long base64 strings in span attributes + if (url.startsWith('data:')) { + const sanitizedUrl = stripDataUrlContent(url); + return { + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch', + 'http.url': sanitizedUrl, + [SEMANTIC_ATTRIBUTE_URL_FULL]: sanitizedUrl, + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: `${request.method || 'GET'} ${sanitizedUrl}`, + }; + } + return { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch', }; From 65afa6a22f8d58f91cc26e93fd7d00643243342d Mon Sep 17 00:00:00 2001 From: Andrei <168741329+andreiborza@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:35:54 +0100 Subject: [PATCH 08/10] feat(node): Add Prisma v7 support (#18908) Upgrades `@prisma/instrumentation` from `6.19.0` to `7.2.0`. The instrumentation should be backwards compatible with v5 and v6 (we have integration tests for v5 and v6). I also added integration tests for v7. Closes: #18876 --- .size-limit.js | 2 +- .../node-integration-tests/package.json | 1 + .../tracing/prisma-orm-v7/docker-compose.yml | 13 +++ .../tracing/prisma-orm-v7/instrument.mjs | 9 ++ .../tracing/prisma-orm-v7/prisma.config.ts | 9 ++ .../prisma/migrations/migration_lock.toml | 3 + .../migrations/sentry_test/migration.sql | 12 +++ .../prisma-orm-v7/prisma/schema.prisma | 15 +++ .../prisma-orm-v7/prisma/tsconfig.json | 11 +++ .../suites/tracing/prisma-orm-v7/scenario.mjs | 46 +++++++++ .../suites/tracing/prisma-orm-v7/test.ts | 74 ++++++++++++++ .../node-integration-tests/utils/runner.ts | 4 +- packages/node/package.json | 2 +- yarn.lock | 99 ++++++++++++++----- 14 files changed, 275 insertions(+), 25 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/docker-compose.yml create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/instrument.mjs create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma.config.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/migration_lock.toml create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/sentry_test/migration.sql create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/schema.prisma create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/tsconfig.json create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/scenario.mjs create mode 100644 dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/test.ts diff --git a/.size-limit.js b/.size-limit.js index 9141676873a1..e8124a622962 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -287,7 +287,7 @@ module.exports = [ import: createImport('init'), ignore: [...builtinModules, ...nodePrefixedBuiltinModules], gzip: true, - limit: '164 KB', + limit: '166 KB', }, { name: '@sentry/node - without tracing', diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index 0305a70e0029..b503e11b5c51 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -35,6 +35,7 @@ "@nestjs/common": "^11", "@nestjs/core": "^11", "@nestjs/platform-express": "^11", + "@prisma/adapter-pg": "7.2.0", "@prisma/client": "6.15.0", "@sentry/aws-serverless": "10.35.0", "@sentry/core": "10.35.0", diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/docker-compose.yml b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/docker-compose.yml new file mode 100644 index 000000000000..a56fd51cf7d9 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.9' + +services: + db: + image: postgres:13 + restart: always + container_name: integration-tests-prisma-v7 + ports: + - '5435:5432' + environment: + POSTGRES_USER: prisma + POSTGRES_PASSWORD: prisma + POSTGRES_DB: tests diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/instrument.mjs b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/instrument.mjs new file mode 100644 index 000000000000..46a27dd03b74 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/instrument.mjs @@ -0,0 +1,9 @@ +import * as Sentry from '@sentry/node'; +import { loggingTransport } from '@sentry-internal/node-integration-tests'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma.config.ts b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma.config.ts new file mode 100644 index 000000000000..cb67c05a6f37 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'prisma/config'; + +export default defineConfig({ + schema: './prisma/schema.prisma', + migrations: './prisma/migrations', + datasource: { + url: 'postgresql://prisma:prisma@localhost:5435/tests', + }, +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/migration_lock.toml b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/migration_lock.toml new file mode 100644 index 000000000000..99e4f2009079 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/sentry_test/migration.sql b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/sentry_test/migration.sql new file mode 100644 index 000000000000..8619aaceb2b0 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/migrations/sentry_test/migration.sql @@ -0,0 +1,12 @@ +-- CreateTable +CREATE TABLE "User" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "email" TEXT NOT NULL, + "name" TEXT, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/schema.prisma b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/schema.prisma new file mode 100644 index 000000000000..6aa93e968540 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/schema.prisma @@ -0,0 +1,15 @@ +datasource db { + provider = "postgresql" +} + +generator client { + provider = "prisma-client" + output = "./generated/prisma" +} + +model User { + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) + email String @unique + name String? +} diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/tsconfig.json b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/tsconfig.json new file mode 100644 index 000000000000..f95f8e88df1b --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/prisma/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "target": "ES2023", + "declaration": false, + "rewriteRelativeImportExtensions": true, + "skipLibCheck": true + }, + "include": ["./generated/prisma/**/*.ts"] +} diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/scenario.mjs b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/scenario.mjs new file mode 100644 index 000000000000..61a7d3c43984 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/scenario.mjs @@ -0,0 +1,46 @@ +import { PrismaPg } from '@prisma/adapter-pg'; +import * as Sentry from '@sentry/node'; +import { randomBytes } from 'crypto'; +import { PrismaClient } from './prisma/generated/prisma/client.js'; + +// Stop the process from exiting before the transaction is sent +setInterval(() => {}, 1000); + +const connectionString = 'postgresql://prisma:prisma@localhost:5435/tests'; + +async function run() { + await Sentry.startSpan( + { + name: 'Test Transaction', + op: 'transaction', + }, + async span => { + const adapter = new PrismaPg({ connectionString }); + const client = new PrismaClient({ adapter }); + + await client.user.create({ + data: { + name: 'Tilda', + email: `tilda_${randomBytes(4).toString('hex')}@sentry.io`, + }, + }); + + await client.user.findMany(); + + await client.user.deleteMany({ + where: { + email: { + contains: 'sentry.io', + }, + }, + }); + + setTimeout(async () => { + span.end(); + await client.$disconnect(); + }, 500); + }, + ); +} + +run(); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/test.ts b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/test.ts new file mode 100644 index 000000000000..9ae4efd136e7 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v7/test.ts @@ -0,0 +1,74 @@ +import { afterAll, expect } from 'vitest'; +import { conditionalTest } from '../../../utils'; +import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; + +afterAll(() => { + cleanupChildProcesses(); +}); + +// Prisma 7 requires Node.js 20.19+ +conditionalTest({ min: 20 })('Prisma ORM v7 Tests', () => { + createEsmAndCjsTests( + __dirname, + 'scenario.mjs', + 'instrument.mjs', + (createRunner, test, _mode, cwd) => { + test('should instrument PostgreSQL queries from Prisma ORM', { timeout: 75_000 }, async () => { + await createRunner() + .withDockerCompose({ + workingDirectory: [cwd], + readyMatches: ['port 5432'], + setupCommand: `prisma generate --schema ${cwd}/prisma/schema.prisma && tsc -p ${cwd}/prisma/tsconfig.json && prisma migrate dev -n sentry-test --schema ${cwd}/prisma/schema.prisma`, + }) + .expect({ + transaction: transaction => { + expect(transaction.transaction).toBe('Test Transaction'); + + const spans = transaction.spans || []; + expect(spans.length).toBeGreaterThanOrEqual(5); + + // Verify Prisma spans have the correct origin + const prismaSpans = spans.filter( + span => span.data && span.data['sentry.origin'] === 'auto.db.otel.prisma', + ); + expect(prismaSpans.length).toBeGreaterThanOrEqual(5); + + // Check for key Prisma span descriptions + const spanDescriptions = prismaSpans.map(span => span.description); + expect(spanDescriptions).toContain('prisma:client:operation'); + expect(spanDescriptions).toContain('prisma:client:serialize'); + expect(spanDescriptions).toContain('prisma:client:connect'); + expect(spanDescriptions).toContain('prisma:client:db_query'); + + // Verify the create operation has correct metadata + const createSpan = prismaSpans.find( + span => + span.description === 'prisma:client:operation' && + span.data?.['method'] === 'create' && + span.data?.['model'] === 'User', + ); + expect(createSpan).toBeDefined(); + + // Verify db_query span has system info and correct op (v7 uses db.system.name) + const dbQuerySpan = prismaSpans.find(span => span.description === 'prisma:client:db_query'); + expect(dbQuerySpan?.data?.['db.system.name']).toBe('postgresql'); + expect(dbQuerySpan?.data?.['sentry.op']).toBe('db'); + expect(dbQuerySpan?.op).toBe('db'); + }, + }) + .start() + .completed(); + }); + }, + { + additionalDependencies: { + '@prisma/adapter-pg': '7.2.0', + '@prisma/client': '7.2.0', + pg: '^8.11.0', + prisma: '7.2.0', + typescript: '^5.9.0', + }, + copyPaths: ['prisma', 'prisma.config.ts', 'docker-compose.yml'], + }, + ); +}); diff --git a/dev-packages/node-integration-tests/utils/runner.ts b/dev-packages/node-integration-tests/utils/runner.ts index 985db0a80e6c..ee2fae0bc06b 100644 --- a/dev-packages/node-integration-tests/utils/runner.ts +++ b/dev-packages/node-integration-tests/utils/runner.ts @@ -110,7 +110,9 @@ async function runDockerCompose(options: DockerOptions): Promise { clearTimeout(timeout); if (options.setupCommand) { try { - execSync(options.setupCommand, { cwd, stdio: 'inherit' }); + // Prepend local node_modules/.bin to PATH so additionalDependencies binaries take precedence + const env = { ...process.env, PATH: `${cwd}/node_modules/.bin:${process.env.PATH}` }; + execSync(options.setupCommand, { cwd, stdio: 'inherit', env }); } catch (e) { log('Error running docker setup command', e); } diff --git a/packages/node/package.json b/packages/node/package.json index 853d1d48d4d6..a17ab657b6e8 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -94,7 +94,7 @@ "@opentelemetry/resources": "^2.4.0", "@opentelemetry/sdk-trace-base": "^2.4.0", "@opentelemetry/semantic-conventions": "^1.37.0", - "@prisma/instrumentation": "6.19.0", + "@prisma/instrumentation": "7.2.0", "@sentry/core": "10.35.0", "@sentry/node-core": "10.35.0", "@sentry/opentelemetry": "10.35.0", diff --git a/yarn.lock b/yarn.lock index cec96ad88027..a1bddfa00756 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5963,6 +5963,13 @@ dependencies: "@octokit/openapi-types" "^18.0.0" +"@opentelemetry/api-logs@0.207.0": + version "0.207.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.207.0.tgz#ae991c51eedda55af037a3e6fc1ebdb12b289f49" + integrity sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ== + dependencies: + "@opentelemetry/api" "^1.3.0" + "@opentelemetry/api-logs@0.210.0": version "0.210.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.210.0.tgz#569016861175fe79d5a57554b523c68714db3b95" @@ -6195,7 +6202,7 @@ "@opentelemetry/instrumentation" "^0.210.0" "@opentelemetry/semantic-conventions" "^1.24.0" -"@opentelemetry/instrumentation@0.210.0", "@opentelemetry/instrumentation@>=0.52.0 <1", "@opentelemetry/instrumentation@^0.210.0": +"@opentelemetry/instrumentation@0.210.0", "@opentelemetry/instrumentation@^0.210.0": version "0.210.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.210.0.tgz#3c9cf77072b7c7796fffcb04e19cad2976a4afbf" integrity sha512-sLMhyHmW9katVaLUOKpfCnxSGhZq2t1ReWgwsu2cSgxmDVMB690H9TanuexanpFI94PJaokrqbp8u9KYZDUT5g== @@ -6204,6 +6211,15 @@ import-in-the-middle "^2.0.0" require-in-the-middle "^8.0.0" +"@opentelemetry/instrumentation@^0.207.0": + version "0.207.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.207.0.tgz#1a5a921c04f171ff28096fa320af713f3c87ec14" + integrity sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA== + dependencies: + "@opentelemetry/api-logs" "0.207.0" + import-in-the-middle "^2.0.0" + require-in-the-middle "^8.0.0" + "@opentelemetry/redis-common@^0.38.2": version "0.38.2" resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz#cefa4f3e79db1cd54f19e233b7dfb56621143955" @@ -6391,6 +6407,15 @@ resolved "https://registry.yarnpkg.com/@poppinss/exception/-/exception-1.2.2.tgz#8d30d42e126c54fe84e997433e4dcac610090743" integrity sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg== +"@prisma/adapter-pg@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@prisma/adapter-pg/-/adapter-pg-7.2.0.tgz#a956ae4b6b168ed2e1c687a0b45e0d1633959bf0" + integrity sha512-euIdQ13cRB2wZ3jPsnDnFhINquo1PYFPCg6yVL8b2rp3EdinQHsX9EDdCtRr489D5uhphcRk463OdQAFlsCr0w== + dependencies: + "@prisma/driver-adapter-utils" "7.2.0" + pg "^8.16.3" + postgres-array "3.0.4" + "@prisma/client@6.15.0": version "6.15.0" resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.15.0.tgz#c4166aa8492878c842e63c515853d7a4125e6168" @@ -6411,6 +6436,18 @@ resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.15.0.tgz#8595f8ae91eadd20d926398449b8602c74e36bbf" integrity sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g== +"@prisma/debug@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-7.2.0.tgz#569b1cbc10eb3e8cae798b40075fd11d21f6b533" + integrity sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw== + +"@prisma/driver-adapter-utils@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.2.0.tgz#53d6686cdbb695338826e1c8ab5ac97c92efb676" + integrity sha512-gzrUcbI9VmHS24Uf+0+7DNzdIw7keglJsD5m/MHxQOU68OhGVzlphQRobLiDMn8CHNA2XN8uugwKjudVtnfMVQ== + dependencies: + "@prisma/debug" "7.2.0" + "@prisma/engines-version@6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb": version "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb" resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz#718b17890287447360107bef3675487d8cb0ae15" @@ -6442,12 +6479,12 @@ dependencies: "@prisma/debug" "6.15.0" -"@prisma/instrumentation@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-6.19.0.tgz#46d15adc8bc4a5a3167032eea6d0a7aa64fb7d93" - integrity sha512-QcuYy25pkXM8BJ37wVFBO7Zh34nyRV1GOb2n3lPkkbRYfl4hWl3PTcImP41P0KrzVXfa/45p6eVCos27x3exIg== +"@prisma/instrumentation@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-7.2.0.tgz#9409a436d8f98e8950c8659aeeba045c4a07e891" + integrity sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g== dependencies: - "@opentelemetry/instrumentation" ">=0.52.0 <1" + "@opentelemetry/instrumentation" "^0.207.0" "@protobuf-ts/plugin-framework@^2.0.7", "@protobuf-ts/plugin-framework@^2.9.4": version "2.9.4" @@ -24898,35 +24935,35 @@ periscopic@^3.1.0: estree-walker "^3.0.0" is-reference "^3.0.0" -pg-cloudflare@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz#2e3649c38a7a9c74a7e5327c8098a2fd9af595bd" - integrity sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg== +pg-cloudflare@^1.2.5, pg-cloudflare@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz#386035d4bfcf1a7045b026f8b21acf5353f14d65" + integrity sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ== pg-connection-string@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.1.tgz#78c23c21a35dd116f48e12e23c0965e8d9e2cbfb" integrity sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg== -pg-connection-string@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.9.0.tgz#f75e06591fdd42ec7636fe2c6a03febeedbec9bf" - integrity sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ== +pg-connection-string@^2.10.0, pg-connection-string@^2.9.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.10.0.tgz#5570fd4837bd813a2b3938cd1744586c7df4a5f1" + integrity sha512-ur/eoPKzDx2IjPaYyXS6Y8NSblxM7X64deV2ObV57vhjsWiwLvUD6meukAzogiOsu60GO8m/3Cb6FdJsWNjwXg== pg-int8@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.10.0.tgz#134b0213755c5e7135152976488aa7cd7ee1268d" - integrity sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA== +pg-pool@^3.10.0, pg-pool@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.11.0.tgz#adf9a6651a30c839f565a3cc400110949c473d69" + integrity sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w== -pg-protocol@*, pg-protocol@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.10.0.tgz#a473afcbb1c6e5dc3ac24869ba3dd563f8a1ae1b" - integrity sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q== +pg-protocol@*, pg-protocol@^1.10.0, pg-protocol@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.11.0.tgz#2502908893edaa1e8c0feeba262dd7b40b317b53" + integrity sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g== pg-types@2.2.0, pg-types@^2.2.0: version "2.2.0" @@ -24952,6 +24989,19 @@ pg@8.16.0: optionalDependencies: pg-cloudflare "^1.2.5" +pg@^8.16.3: + version "8.17.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.17.1.tgz#cecf0c96d3f5004951ccbafaaa230779ebc89d35" + integrity sha512-EIR+jXdYNSMOrpRp7g6WgQr7SaZNZfS7IzZIO0oTNEeibq956JxeD15t3Jk3zZH0KH8DmOIx38qJfQenoE8bXQ== + dependencies: + pg-connection-string "^2.10.0" + pg-pool "^3.11.0" + pg-protocol "^1.11.0" + pg-types "2.2.0" + pgpass "1.0.5" + optionalDependencies: + pg-cloudflare "^1.3.0" + pgpass@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" @@ -25750,6 +25800,11 @@ postcss@^8.1.10, postcss@^8.2.14, postcss@^8.2.15, postcss@^8.3.7, postcss@^8.4. picocolors "^1.1.1" source-map-js "^1.2.1" +postgres-array@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.4.tgz#4efcaf4d2c688d8bcaa8620ed13f35f299f7528c" + integrity sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ== + postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" From 6d9a7f70e321ec0294e73f55d448de9ad8e3eb2c Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Wed, 21 Jan 2026 13:41:27 +0100 Subject: [PATCH 09/10] PR reivew --- packages/core/src/utils/debug-ids.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/core/src/utils/debug-ids.ts b/packages/core/src/utils/debug-ids.ts index 32396b5bbcac..ea45a8fb2e6c 100644 --- a/packages/core/src/utils/debug-ids.ts +++ b/packages/core/src/utils/debug-ids.ts @@ -114,14 +114,12 @@ export function getDebugImagesForResources( const images: DebugImage[] = []; for (const path of resource_paths) { const normalizedPath = normalizeStackTracePath(path); - if (normalizedPath) { - if (filenameDebugIdMap[normalizedPath]) { - images.push({ - type: 'sourcemap', - code_file: path, - debug_id: filenameDebugIdMap[normalizedPath], - }); - } + if (normalizedPath && filenameDebugIdMap[normalizedPath]) { + images.push({ + type: 'sourcemap', + code_file: path, + debug_id: filenameDebugIdMap[normalizedPath], + }); } } From d185952e4efa26bea07e03e4531702b45f43a415 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 21 Jan 2026 14:04:29 +0100 Subject: [PATCH 10/10] meta(changelog): Update changelog for 10.36.0 --- CHANGELOG.md | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25bc54e75abc..e32b01c44a72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,41 +4,21 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott -### Other Changes +## 10.36.0 + +- feat(node): Add Prisma v7 support ([#18908](https://github.com/getsentry/sentry-javascript/pull/18908)) +- feat(opentelemetry): Support `db.system.name` attribute for database spans ([#18902](https://github.com/getsentry/sentry-javascript/pull/18902)) +- feat(deps): Bump OpenTelemetry dependencies ([#18878](https://github.com/getsentry/sentry-javascript/pull/18878)) +- fix(core): Sanitize data URLs in `http.client` spans ([#18896](https://github.com/getsentry/sentry-javascript/pull/18896)) +- fix(nextjs): Add ALS runner fallbacks for serverless environments ([#18889](https://github.com/getsentry/sentry-javascript/pull/18889)) +- fix(node): Profiling debug ID matching -- feat(deps): Bump OpenTelemetry dependencies - - Bump @opentelemetry/context-async-hooks from 2.2.0 to 2.4.0 - - Bump @opentelemetry/core from 2.2.0 to 2.4.0 - - Bump @opentelemetry/resources from 2.2.0 to 2.4.0 - - Bump @opentelemetry/sdk-trace-base from 2.2.0 to 2.4.0 - - Bump @opentelemetry/sdk-trace-node from 2.2.0 to 2.4.0 - - Bump @opentelemetry/instrumentation from 0.208.0 to 0.210.0 - - Bump @opentelemetry/instrumentation-amqplib from 0.55.0 to 0.57.0 - - Bump @opentelemetry/instrumentation-connect from 0.52.0 to 0.53.0 - - Bump @opentelemetry/instrumentation-dataloader from 0.26.0 to 0.27.0 - - Bump @opentelemetry/instrumentation-express from 0.57.0 to 0.58.0 - - Bump @opentelemetry/instrumentation-fs from 0.28.0 to 0.29.0 - - Bump @opentelemetry/instrumentation-generic-pool from 0.52.0 to 0.53.0 - - Bump @opentelemetry/instrumentation-graphql from 0.56.0 to 0.57.0 - - Bump @opentelemetry/instrumentation-hapi from 0.55.0 to 0.56.0 - - Bump @opentelemetry/instrumentation-http from 0.208.0 to 0.210.0 - - Bump @opentelemetry/instrumentation-ioredis from 0.56.0 to 0.58.0 - - Bump @opentelemetry/instrumentation-kafkajs from 0.18.0 to 0.19.0 - - Bump @opentelemetry/instrumentation-knex from 0.53.0 to 0.54.0 - - Bump @opentelemetry/instrumentation-koa from 0.57.0 to 0.58.0 - - Bump @opentelemetry/instrumentation-lru-memoizer from 0.53.0 to 0.54.0 - - Bump @opentelemetry/instrumentation-mongodb from 0.61.0 to 0.63.0 - - Bump @opentelemetry/instrumentation-mongoose from 0.55.0 to 0.56.0 - - Bump @opentelemetry/instrumentation-mysql from 0.54.0 to 0.56.0 - - Bump @opentelemetry/instrumentation-mysql2 from 0.55.0 to 0.56.0 - - Bump @opentelemetry/instrumentation-nestjs-core from 0.55.0 to 0.56.0 - - Bump @opentelemetry/instrumentation-pg from 0.61.0 to 0.62.0 - - Bump @opentelemetry/instrumentation-redis from 0.57.0 to 0.58.0 - - Bump @opentelemetry/instrumentation-tedious from 0.27.0 to 0.29.0 - - Bump @opentelemetry/instrumentation-undici from 0.19.0 to 0.20.0 - - Bump @opentelemetry/instrumentation-aws-sdk from 0.64.0 to 0.65.0 - - Bump @opentelemetry/sdk-node from 0.208.0 to 0.210.0 - - Bump @opentelemetry/exporter-trace-otlp-http from 0.208.0 to 0.210.0 +
+ Internal Changes + +- chore(deps-dev): bump @remix-run/server-runtime from 2.15.2 to 2.17.3 in /packages/remix ([#18750](https://github.com/getsentry/sentry-javascript/pull/18750)) + +
## 10.35.0