diff --git a/.craft.yml b/.craft.yml index 44d245311312..ec096880c0d6 100644 --- a/.craft.yml +++ b/.craft.yml @@ -142,7 +142,6 @@ targets: id: '@sentry-internal/eslint-config-sdk' includeNames: /^sentry-internal-eslint-config-sdk-\d.*\.tgz$/ - # TODO(v9): Remove this target # NOTE: We publish the v8 layer under its own name so people on v8 can still get patches # whenever we release a new v8 version—otherwise we would overwrite the current major lambda layer. - name: aws-lambda-layer @@ -159,21 +158,6 @@ targets: - nodejs20.x license: MIT - # AWS Lambda Layer target - - name: aws-lambda-layer - includeNames: /^sentry-node-serverless-\d+.\d+.\d+(-(beta|alpha|rc)\.\d+)?\.zip$/ - layerName: SentryNodeServerlessSDK - compatibleRuntimes: - - name: node - versions: - - nodejs10.x - - nodejs12.x - - nodejs14.x - - nodejs16.x - - nodejs18.x - - nodejs20.x - license: MIT - # CDN Bundle Target - name: gcs id: 'browser-cdn-bundles' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf9ba21376bb..31f5cea28bda 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,8 @@ on: branches: - develop - master + - v9 + - v8 - release/** pull_request: merge_group: @@ -105,7 +107,7 @@ jobs: outputs: commit_label: '${{ env.COMMIT_SHA }}: ${{ env.COMMIT_MESSAGE }}' # Note: These next three have to be checked as strings ('true'/'false')! - is_develop: ${{ github.ref == 'refs/heads/develop' }} + is_base_branch: ${{ github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/v9' || github.ref == 'refs/heads/v8'}} is_release: ${{ startsWith(github.ref, 'refs/heads/release/') }} changed_profiling_node: ${{ steps.changed.outputs.profiling_node == 'true' }} changed_ci: ${{ steps.changed.outputs.workflow == 'true' }} @@ -126,7 +128,7 @@ jobs: timeout-minutes: 15 if: | needs.job_get_metadata.outputs.changed_any_code == 'true' || - needs.job_get_metadata.outputs.is_develop == 'true' || + needs.job_get_metadata.outputs.is_base_branch == 'true' || needs.job_get_metadata.outputs.is_release == 'true' || (needs.job_get_metadata.outputs.is_gitflow_sync == 'false' && needs.job_get_metadata.outputs.has_gitflow_label == 'false') steps: @@ -171,7 +173,7 @@ jobs: key: nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT || github.sha }} # On develop branch, we want to _store_ the cache (so it can be used by other branches), but never _restore_ from it restore-keys: - ${{needs.job_get_metadata.outputs.is_develop == 'false' && env.NX_CACHE_RESTORE_KEYS || 'nx-never-restore'}} + ${{needs.job_get_metadata.outputs.is_base_branch == 'false' && env.NX_CACHE_RESTORE_KEYS || 'nx-never-restore'}} - name: Build packages # Set the CODECOV_TOKEN for Bundle Analysis @@ -219,7 +221,7 @@ jobs: timeout-minutes: 15 runs-on: ubuntu-20.04 if: - github.event_name == 'pull_request' || needs.job_get_metadata.outputs.is_develop == 'true' || + github.event_name == 'pull_request' || needs.job_get_metadata.outputs.is_base_branch == 'true' || needs.job_get_metadata.outputs.is_release == 'true' steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) diff --git a/.github/workflows/enforce-license-compliance.yml b/.github/workflows/enforce-license-compliance.yml index 8f63b6ca063b..776f8135178d 100644 --- a/.github/workflows/enforce-license-compliance.yml +++ b/.github/workflows/enforce-license-compliance.yml @@ -2,9 +2,18 @@ name: "CI: Enforce License Compliance" on: push: - branches: [master, develop, release/*] + branches: + - develop + - master + - v9 + - v8 + - release/** pull_request: - branches: [master, develop] + branches: + - develop + - master + - v9 + - v8 jobs: enforce-license-compliance: diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6332f4c125..bf80db840060 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,33 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +Work in this release was contributed by @arturovt. Thank you for your contribution! + +## 8.47.0 + +- feat(v8/core): Add `updateSpanName` helper function (#14736) +- feat(v8/node): Do not overwrite prisma `db.system` in newer Prisma versions (#14772) +- feat(v8/node/deps): Bump @prisma/instrumentation from 5.19.1 to 5.22.0 (#14755) +- feat(v8/replay): Mask srcdoc iframe contents per default (#14779) +- ref(v8/nextjs): Fix typo in source maps deletion warning (#14776) + +Work in this release was contributed by @aloisklink and @benjick. Thank you for your contributions! + +## 8.46.0 + +- feat: Allow capture of more than 1 ANR event [v8] ([#14713](https://github.com/getsentry/sentry-javascript/pull/14713)) +- feat(node): Detect Railway release name [v8] ([#14714](https://github.com/getsentry/sentry-javascript/pull/14714)) +- fix: Normalise ANR debug image file paths if appRoot was supplied [v8] ([#14709](https://github.com/getsentry/sentry-javascript/pull/14709)) +- fix(nuxt): Remove build config from tsconfig ([#14737](https://github.com/getsentry/sentry-javascript/pull/14737)) + +Work in this release was contributed by @conor-ob. Thank you for your contribution! + +## 8.45.1 + +- fix(feedback): Return when the `sendFeedback` promise resolves ([#14683](https://github.com/getsentry/sentry-javascript/pull/14683)) + +Work in this release was contributed by @antonis. Thank you for your contribution! + ## 8.45.0 - feat(core): Add `handled` option to `captureConsoleIntegration` ([#14664](https://github.com/getsentry/sentry-javascript/pull/14664)) diff --git a/dev-packages/browser-integration-tests/package.json b/dev-packages/browser-integration-tests/package.json index 31a7ce76727e..75c47b95f280 100644 --- a/dev-packages/browser-integration-tests/package.json +++ b/dev-packages/browser-integration-tests/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/browser-integration-tests", - "version": "8.45.0", + "version": "8.47.0", "main": "index.js", "license": "MIT", "engines": { @@ -43,7 +43,7 @@ "@babel/preset-typescript": "^7.16.7", "@playwright/test": "^1.44.1", "@sentry-internal/rrweb": "2.31.0", - "@sentry/browser": "8.45.0", + "@sentry/browser": "8.47.0", "axios": "1.7.7", "babel-loader": "^8.2.2", "html-webpack-plugin": "^5.5.0", diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-update-txn-name/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-update-txn-name/test.ts index 6226ff75dbb9..7d2d949898c2 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-update-txn-name/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-update-txn-name/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { Event } from '@sentry/core'; +import { type Event, SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME } from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, @@ -10,27 +10,34 @@ import { import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; -sentryTest('sets the source to custom when updating the transaction name', async ({ getLocalTestUrl, page }) => { - if (shouldSkipTracingTest()) { - sentryTest.skip(); - } +sentryTest( + 'sets the source to custom when updating the transaction name with `span.updateName`', + async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } - const url = await getLocalTestUrl({ testDir: __dirname }); + const url = await getLocalTestUrl({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); - const traceContextData = eventData.contexts?.trace?.data; + const traceContextData = eventData.contexts?.trace?.data; - expect(traceContextData).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser', - [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1, - [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload', - }); + expect(traceContextData).toBeDefined(); - expect(eventData.transaction).toBe('new name'); + expect(eventData.transaction).toBe('new name'); - expect(eventData.contexts?.trace?.op).toBe('pageload'); - expect(eventData.spans?.length).toBeGreaterThan(0); - expect(eventData.transaction_info?.source).toEqual('custom'); -}); + expect(traceContextData).toMatchObject({ + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser', + [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1, + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload', + }); + + expect(traceContextData![SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]).toBeUndefined(); + + expect(eventData.contexts?.trace?.op).toBe('pageload'); + expect(eventData.spans?.length).toBeGreaterThan(0); + expect(eventData.transaction_info?.source).toEqual('custom'); + }, +); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/init.js b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/init.js new file mode 100644 index 000000000000..1f0b64911a75 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/init.js @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; +window._testBaseTimestamp = performance.timeOrigin / 1000; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + integrations: [Sentry.browserTracingIntegration()], + tracesSampleRate: 1, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/subject.js b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/subject.js new file mode 100644 index 000000000000..7f0ad0fea340 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/subject.js @@ -0,0 +1,4 @@ +const activeSpan = Sentry.getActiveSpan(); +const rootSpan = activeSpan && Sentry.getRootSpan(activeSpan); + +Sentry.updateSpanName(rootSpan, 'new name'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/test.ts new file mode 100644 index 000000000000..69094b38e4dd --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-updateSpanName/test.ts @@ -0,0 +1,43 @@ +import { expect } from '@playwright/test'; +import { type Event, SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME } from '@sentry/core'; + +import { + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, +} from '@sentry/browser'; +import { sentryTest } from '../../../../utils/fixtures'; +import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; + +sentryTest( + 'sets the source to custom when updating the transaction name with Sentry.updateSpanName', + async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } + + const url = await getLocalTestUrl({ testDir: __dirname }); + + const eventData = await getFirstSentryEnvelopeRequest(page, url); + + const traceContextData = eventData.contexts?.trace?.data; + + expect(traceContextData).toBeDefined(); + + expect(traceContextData).toMatchObject({ + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser', + [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 1, + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload', + }); + + expect(traceContextData![SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]).toBeUndefined(); + + expect(eventData.transaction).toBe('new name'); + + expect(eventData.contexts?.trace?.op).toBe('pageload'); + expect(eventData.spans?.length).toBeGreaterThan(0); + expect(eventData.transaction_info?.source).toEqual('custom'); + }, +); diff --git a/dev-packages/browser-integration-tests/suites/tracing/dsc-txn-name-update/test.ts b/dev-packages/browser-integration-tests/suites/tracing/dsc-txn-name-update/test.ts index 7ce5f7195a5b..34e15d1be573 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/dsc-txn-name-update/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/dsc-txn-name-update/test.ts @@ -181,5 +181,9 @@ async function captureErrorAndGetEnvelopeTraceHeader(page: Page): Promise=18" diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index 6452d7752eba..041be96fa306 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/e2e-tests", - "version": "8.45.0", + "version": "8.47.0", "license": "MIT", "private": true, "scripts": { diff --git a/dev-packages/e2e-tests/test-applications/angular-17/src/app/component-tracking/component-tracking.components.ts b/dev-packages/e2e-tests/test-applications/angular-17/src/app/component-tracking/component-tracking.components.ts index d437a1d43fdd..1e43d5c6c096 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/src/app/component-tracking/component-tracking.components.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/src/app/component-tracking/component-tracking.components.ts @@ -6,7 +6,10 @@ import { SampleComponent } from '../sample-component/sample-component.components selector: 'app-cancel', standalone: true, imports: [TraceModule, SampleComponent], - template: ``, + template: ` + + + `, }) @TraceClass({ name: 'ComponentTrackingComponent' }) export class ComponentTrackingComponent implements OnInit, AfterViewInit { diff --git a/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts index 29c88a6108e2..03a715ce646c 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts @@ -191,7 +191,7 @@ test.describe('finish routing span', () => { }); test.describe('TraceDirective', () => { - test('creates a child tracingSpan with component name as span name on ngOnInit', async ({ page }) => { + test('creates a child span with the component name as span name on ngOnInit', async ({ page }) => { const navigationTxnPromise = waitForTransaction('angular-17', async transactionEvent => { return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; }); @@ -201,23 +201,36 @@ test.describe('TraceDirective', () => { // immediately navigate to a different route const [_, navigationTxn] = await Promise.all([page.locator('#componentTracking').click(), navigationTxnPromise]); - const traceDirectiveSpan = navigationTxn.spans?.find( + const traceDirectiveSpans = navigationTxn.spans?.filter( span => span?.data && span?.data[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] === 'auto.ui.angular.trace_directive', ); - expect(traceDirectiveSpan).toBeDefined(); - expect(traceDirectiveSpan).toEqual( - expect.objectContaining({ - data: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.angular.init', - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', - }, - description: '', - op: 'ui.angular.init', - origin: 'auto.ui.angular.trace_directive', - start_timestamp: expect.any(Number), - timestamp: expect.any(Number), - }), + expect(traceDirectiveSpans).toHaveLength(2); + expect(traceDirectiveSpans).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + data: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.angular.init', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', + }, + description: '', // custom component name passed to trace directive + op: 'ui.angular.init', + origin: 'auto.ui.angular.trace_directive', + start_timestamp: expect.any(Number), + timestamp: expect.any(Number), + }), + expect.objectContaining({ + data: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.angular.init', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', + }, + description: '', // fallback selector name + op: 'ui.angular.init', + origin: 'auto.ui.angular.trace_directive', + start_timestamp: expect.any(Number), + timestamp: expect.any(Number), + }), + ]), ); }); }); diff --git a/dev-packages/e2e-tests/test-applications/angular-19/.npmrc b/dev-packages/e2e-tests/test-applications/angular-19/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/angular-19/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/angular-19/src/app/component-tracking/component-tracking.components.ts b/dev-packages/e2e-tests/test-applications/angular-19/src/app/component-tracking/component-tracking.components.ts index d437a1d43fdd..a82e5b1acce6 100644 --- a/dev-packages/e2e-tests/test-applications/angular-19/src/app/component-tracking/component-tracking.components.ts +++ b/dev-packages/e2e-tests/test-applications/angular-19/src/app/component-tracking/component-tracking.components.ts @@ -3,10 +3,13 @@ import { TraceClass, TraceMethod, TraceModule } from '@sentry/angular'; import { SampleComponent } from '../sample-component/sample-component.components'; @Component({ - selector: 'app-cancel', + selector: 'app-component-tracking', standalone: true, imports: [TraceModule, SampleComponent], - template: ``, + template: ` + + + `, }) @TraceClass({ name: 'ComponentTrackingComponent' }) export class ComponentTrackingComponent implements OnInit, AfterViewInit { diff --git a/dev-packages/e2e-tests/test-applications/angular-19/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/angular-19/tests/performance.test.ts index af85b8ffc405..c2cb2eca34b6 100644 --- a/dev-packages/e2e-tests/test-applications/angular-19/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-19/tests/performance.test.ts @@ -191,7 +191,7 @@ test.describe('finish routing span', () => { }); test.describe('TraceDirective', () => { - test('creates a child tracingSpan with component name as span name on ngOnInit', async ({ page }) => { + test('creates a child span with the component name as span name on ngOnInit', async ({ page }) => { const navigationTxnPromise = waitForTransaction('angular-18', async transactionEvent => { return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; }); @@ -201,23 +201,36 @@ test.describe('TraceDirective', () => { // immediately navigate to a different route const [_, navigationTxn] = await Promise.all([page.locator('#componentTracking').click(), navigationTxnPromise]); - const traceDirectiveSpan = navigationTxn.spans?.find( + const traceDirectiveSpans = navigationTxn.spans?.filter( span => span?.data && span?.data[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] === 'auto.ui.angular.trace_directive', ); - expect(traceDirectiveSpan).toBeDefined(); - expect(traceDirectiveSpan).toEqual( - expect.objectContaining({ - data: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.angular.init', - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', - }, - description: '', - op: 'ui.angular.init', - origin: 'auto.ui.angular.trace_directive', - start_timestamp: expect.any(Number), - timestamp: expect.any(Number), - }), + expect(traceDirectiveSpans).toHaveLength(2); + expect(traceDirectiveSpans).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + data: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.angular.init', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', + }, + description: '', // custom component name passed to trace directive + op: 'ui.angular.init', + origin: 'auto.ui.angular.trace_directive', + start_timestamp: expect.any(Number), + timestamp: expect.any(Number), + }), + expect.objectContaining({ + data: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.angular.init', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', + }, + description: '', // fallback selector name + op: 'ui.angular.init', + origin: 'auto.ui.angular.trace_directive', + start_timestamp: expect.any(Number), + timestamp: expect.any(Number), + }), + ]), ); }); }); diff --git a/dev-packages/external-contributor-gh-action/package.json b/dev-packages/external-contributor-gh-action/package.json index a4857bd41082..09a0e8206db6 100644 --- a/dev-packages/external-contributor-gh-action/package.json +++ b/dev-packages/external-contributor-gh-action/package.json @@ -1,7 +1,7 @@ { "name": "@sentry-internal/external-contributor-gh-action", "description": "An internal Github Action to add external contributors to the CHANGELOG.md file.", - "version": "8.45.0", + "version": "8.47.0", "license": "MIT", "engines": { "node": ">=18" diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index 24be97583c1c..58d0d4f6d2c9 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/node-integration-tests", - "version": "8.45.0", + "version": "8.47.0", "license": "MIT", "engines": { "node": ">=14.18" @@ -30,10 +30,10 @@ "@nestjs/common": "10.4.6", "@nestjs/core": "10.4.6", "@nestjs/platform-express": "10.4.6", - "@prisma/client": "5.9.1", - "@sentry/aws-serverless": "8.45.0", - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", + "@prisma/client": "5.22.0", + "@sentry/aws-serverless": "8.47.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", "@types/mongodb": "^3.6.20", "@types/mysql": "^2.15.21", "@types/pg": "^8.6.5", diff --git a/dev-packages/node-integration-tests/suites/anr/app-path.mjs b/dev-packages/node-integration-tests/suites/anr/app-path.mjs new file mode 100644 index 000000000000..b7d32e1aa9b2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/anr/app-path.mjs @@ -0,0 +1,36 @@ +import * as assert from 'assert'; +import * as crypto from 'crypto'; +import * as path from 'path'; +import * as url from 'url'; + +import * as Sentry from '@sentry/node'; + +global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; + +const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); + +setTimeout(() => { + process.exit(); +}, 10000); + +Sentry.init({ + dsn: process.env.SENTRY_DSN, + release: '1.0', + autoSessionTracking: false, + integrations: [Sentry.anrIntegration({ captureStackTrace: true, anrThreshold: 100, appRootPath: __dirname })], +}); + +Sentry.setUser({ email: 'person@home.com' }); +Sentry.addBreadcrumb({ message: 'important message!' }); + +function longWork() { + for (let i = 0; i < 20; i++) { + const salt = crypto.randomBytes(128).toString('base64'); + const hash = crypto.pbkdf2Sync('myPassword', salt, 10000, 512, 'sha512'); + assert.ok(hash); + } +} + +setTimeout(() => { + longWork(); +}, 1000); diff --git a/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs b/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs new file mode 100644 index 000000000000..f58eb87f8237 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs @@ -0,0 +1,36 @@ +import * as assert from 'assert'; +import * as crypto from 'crypto'; + +import * as Sentry from '@sentry/node'; + +global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; + +setTimeout(() => { + process.exit(); +}, 10000); + +Sentry.init({ + dsn: process.env.SENTRY_DSN, + release: '1.0', + autoSessionTracking: false, + integrations: [Sentry.anrIntegration({ captureStackTrace: true, anrThreshold: 100, maxAnrEvents: 2 })], +}); + +Sentry.setUser({ email: 'person@home.com' }); +Sentry.addBreadcrumb({ message: 'important message!' }); + +function longWork() { + for (let i = 0; i < 20; i++) { + const salt = crypto.randomBytes(128).toString('base64'); + const hash = crypto.pbkdf2Sync('myPassword', salt, 10000, 512, 'sha512'); + assert.ok(hash); + } +} + +setTimeout(() => { + longWork(); +}, 1000); + +setTimeout(() => { + longWork(); +}, 4000); diff --git a/dev-packages/node-integration-tests/suites/anr/basic.mjs b/dev-packages/node-integration-tests/suites/anr/basic.mjs index 18777e5ecdbd..454a35605925 100644 --- a/dev-packages/node-integration-tests/suites/anr/basic.mjs +++ b/dev-packages/node-integration-tests/suites/anr/basic.mjs @@ -30,3 +30,8 @@ function longWork() { setTimeout(() => { longWork(); }, 1000); + +// Ensure we only send one event even with multiple blocking events +setTimeout(() => { + longWork(); +}, 4000); diff --git a/dev-packages/node-integration-tests/suites/anr/test.ts b/dev-packages/node-integration-tests/suites/anr/test.ts index b1750b308d28..cd7df2a86314 100644 --- a/dev-packages/node-integration-tests/suites/anr/test.ts +++ b/dev-packages/node-integration-tests/suites/anr/test.ts @@ -31,20 +31,20 @@ const ANR_EVENT = { mechanism: { type: 'ANR' }, stacktrace: { frames: expect.arrayContaining([ - { + expect.objectContaining({ colno: expect.any(Number), lineno: expect.any(Number), filename: expect.any(String), function: '?', in_app: true, - }, - { + }), + expect.objectContaining({ colno: expect.any(Number), lineno: expect.any(Number), filename: expect.any(String), function: 'longWork', in_app: true, - }, + }), ]), }, }, @@ -101,7 +101,7 @@ const ANR_EVENT_WITH_DEBUG_META: Event = { { type: 'sourcemap', debug_id: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa', - code_file: expect.stringContaining('basic.'), + code_file: expect.stringContaining('basic'), }, ], }, @@ -123,6 +123,34 @@ conditionalTest({ min: 16 })('should report ANR when event loop blocked', () => .start(done); }); + test('Custom appRootPath', done => { + const ANR_EVENT_WITH_SPECIFIC_DEBUG_META: Event = { + ...ANR_EVENT_WITH_SCOPE, + debug_meta: { + images: [ + { + type: 'sourcemap', + debug_id: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa', + code_file: 'app:///app-path.mjs', + }, + ], + }, + }; + + createRunner(__dirname, 'app-path.mjs') + .withMockSentryServer() + .expect({ event: ANR_EVENT_WITH_SPECIFIC_DEBUG_META }) + .start(done); + }); + + test('multiple events via maxAnrEvents', done => { + createRunner(__dirname, 'basic-multiple.mjs') + .withMockSentryServer() + .expect({ event: ANR_EVENT_WITH_DEBUG_META }) + .expect({ event: ANR_EVENT_WITH_DEBUG_META }) + .start(done); + }); + test('blocked indefinitely', done => { createRunner(__dirname, 'indefinite.mjs').withMockSentryServer().expect({ event: ANR_EVENT }).start(done); }); diff --git a/dev-packages/node-integration-tests/suites/express/tracing/updateName/server.js b/dev-packages/node-integration-tests/suites/express/tracing/updateName/server.js new file mode 100644 index 000000000000..c98e17276d92 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/express/tracing/updateName/server.js @@ -0,0 +1,58 @@ +const { loggingTransport } = require('@sentry-internal/node-integration-tests'); +const Sentry = require('@sentry/node'); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + // disable attaching headers to /test/* endpoints + tracePropagationTargets: [/^(?!.*test).*$/], + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +// express must be required after Sentry is initialized +const express = require('express'); +const cors = require('cors'); +const bodyParser = require('body-parser'); +const { startExpressServerAndSendPortToRunner } = require('@sentry-internal/node-integration-tests'); + +const app = express(); + +app.use(cors()); +app.use(bodyParser.json()); +app.use(bodyParser.text()); +app.use(bodyParser.raw()); + +app.get('/test/:id/span-updateName', (_req, res) => { + const span = Sentry.getActiveSpan(); + const rootSpan = Sentry.getRootSpan(span); + rootSpan.updateName('new-name'); + res.send({ response: 'response 1' }); +}); + +app.get('/test/:id/span-updateName-source', (_req, res) => { + const span = Sentry.getActiveSpan(); + const rootSpan = Sentry.getRootSpan(span); + rootSpan.updateName('new-name'); + rootSpan.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'custom'); + res.send({ response: 'response 2' }); +}); + +app.get('/test/:id/updateSpanName', (_req, res) => { + const span = Sentry.getActiveSpan(); + const rootSpan = Sentry.getRootSpan(span); + Sentry.updateSpanName(rootSpan, 'new-name'); + res.send({ response: 'response 3' }); +}); + +app.get('/test/:id/updateSpanNameAndSource', (_req, res) => { + const span = Sentry.getActiveSpan(); + const rootSpan = Sentry.getRootSpan(span); + Sentry.updateSpanName(rootSpan, 'new-name'); + rootSpan.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'component'); + res.send({ response: 'response 4' }); +}); + +Sentry.setupExpressErrorHandler(app); + +startExpressServerAndSendPortToRunner(app); diff --git a/dev-packages/node-integration-tests/suites/express/tracing/updateName/test.ts b/dev-packages/node-integration-tests/suites/express/tracing/updateName/test.ts new file mode 100644 index 000000000000..c6345713fd7e --- /dev/null +++ b/dev-packages/node-integration-tests/suites/express/tracing/updateName/test.ts @@ -0,0 +1,94 @@ +import { SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME } from '@sentry/core'; +import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/node'; +import { cleanupChildProcesses, createRunner } from '../../../../utils/runner'; + +describe('express tracing', () => { + afterAll(() => { + cleanupChildProcesses(); + }); + + describe('CJS', () => { + // This test documents the unfortunate behaviour of using `span.updateName` on the server-side. + // For http.server root spans (which is the root span on the server 99% of the time), Otel's http instrumentation + // calls `span.updateName` and overwrites whatever the name was set to before (by us or by users). + test("calling just `span.updateName` doesn't update the final name in express (missing source)", done => { + createRunner(__dirname, 'server.js') + .expect({ + transaction: { + transaction: 'GET /test/:id/span-updateName', + transaction_info: { + source: 'route', + }, + }, + }) + .start(done) + .makeRequest('get', '/test/123/span-updateName'); + }); + + // Also calling `updateName` AND setting a source doesn't change anything - Otel has no concept of source, this is sentry-internal. + // Therefore, only the source is updated but the name is still overwritten by Otel. + test("calling `span.updateName` and setting attribute source doesn't update the final name in express but it updates the source", done => { + createRunner(__dirname, 'server.js') + .expect({ + transaction: { + transaction: 'GET /test/:id/span-updateName-source', + transaction_info: { + source: 'custom', + }, + }, + }) + .start(done) + .makeRequest('get', '/test/123/span-updateName-source'); + }); + + // This test documents the correct way to update the span name (and implicitly the source) in Node: + test('calling `Sentry.updateSpanName` updates the final name and source in express', done => { + createRunner(__dirname, 'server.js') + .expect({ + transaction: txnEvent => { + expect(txnEvent).toMatchObject({ + transaction: 'new-name', + transaction_info: { + source: 'custom', + }, + contexts: { + trace: { + op: 'http.server', + data: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom' }, + }, + }, + }); + // ensure we delete the internal attribute once we're done with it + expect(txnEvent.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]).toBeUndefined(); + }, + }) + .start(done) + .makeRequest('get', '/test/123/updateSpanName'); + }); + }); + + // This test documents the correct way to update the span name (and implicitly the source) in Node: + test('calling `Sentry.updateSpanName` and setting source subsequently updates the final name and sets correct source', done => { + createRunner(__dirname, 'server.js') + .expect({ + transaction: txnEvent => { + expect(txnEvent).toMatchObject({ + transaction: 'new-name', + transaction_info: { + source: 'component', + }, + contexts: { + trace: { + op: 'http.server', + data: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component' }, + }, + }, + }); + // ensure we delete the internal attribute once we're done with it + expect(txnEvent.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]).toBeUndefined(); + }, + }) + .start(done) + .makeRequest('get', '/test/123/updateSpanNameAndSource'); + }); +}); diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage/test.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage/test.ts index 86b3bf6d9d22..0370b123cab2 100644 --- a/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/basic-usage/test.ts @@ -1,11 +1,42 @@ +import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/node'; import { cleanupChildProcesses, createRunner } from '../../../../utils/runner'; afterAll(() => { cleanupChildProcesses(); }); -test('should send a manually started root span', done => { +test('sends a manually started root span with source custom', done => { createRunner(__dirname, 'scenario.ts') - .expect({ transaction: { transaction: 'test_span' } }) + .expect({ + transaction: { + transaction: 'test_span', + transaction_info: { source: 'custom' }, + contexts: { + trace: { + span_id: expect.any(String), + trace_id: expect.any(String), + data: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom' }, + }, + }, + }, + }) + .start(done); +}); + +test("doesn't change the name for manually started spans even if attributes triggering inference are set", done => { + createRunner(__dirname, 'scenario.ts') + .expect({ + transaction: { + transaction: 'test_span', + transaction_info: { source: 'custom' }, + contexts: { + trace: { + span_id: expect.any(String), + trace_id: expect.any(String), + data: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom' }, + }, + }, + }, + }) .start(done); }); diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/updateName-method/scenario.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateName-method/scenario.ts new file mode 100644 index 000000000000..ea30608c1c5c --- /dev/null +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateName-method/scenario.ts @@ -0,0 +1,16 @@ +import { loggingTransport } from '@sentry-internal/node-integration-tests'; +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +Sentry.startSpan( + { name: 'test_span', attributes: { [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' } }, + (span: Sentry.Span) => { + span.updateName('new name'); + }, +); diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/updateName-method/test.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateName-method/test.ts new file mode 100644 index 000000000000..676071926b91 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateName-method/test.ts @@ -0,0 +1,24 @@ +import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/node'; +import { cleanupChildProcesses, createRunner } from '../../../../utils/runner'; + +afterAll(() => { + cleanupChildProcesses(); +}); + +test('updates the span name when calling `span.updateName`', done => { + createRunner(__dirname, 'scenario.ts') + .expect({ + transaction: { + transaction: 'new name', + transaction_info: { source: 'url' }, + contexts: { + trace: { + span_id: expect.any(String), + trace_id: expect.any(String), + data: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' }, + }, + }, + }, + }) + .start(done); +}); diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/updateSpanName-function/scenario.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateSpanName-function/scenario.ts new file mode 100644 index 000000000000..ecf7670fa23d --- /dev/null +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateSpanName-function/scenario.ts @@ -0,0 +1,16 @@ +import { loggingTransport } from '@sentry-internal/node-integration-tests'; +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +Sentry.startSpan( + { name: 'test_span', attributes: { [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' } }, + (span: Sentry.Span) => { + Sentry.updateSpanName(span, 'new name'); + }, +); diff --git a/dev-packages/node-integration-tests/suites/public-api/startSpan/updateSpanName-function/test.ts b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateSpanName-function/test.ts new file mode 100644 index 000000000000..c5b325fc0ea2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/public-api/startSpan/updateSpanName-function/test.ts @@ -0,0 +1,24 @@ +import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/node'; +import { cleanupChildProcesses, createRunner } from '../../../../utils/runner'; + +afterAll(() => { + cleanupChildProcesses(); +}); + +test('updates the span name and source when calling `updateSpanName`', done => { + createRunner(__dirname, 'scenario.ts') + .expect({ + transaction: { + transaction: 'new name', + transaction_info: { source: 'custom' }, + contexts: { + trace: { + span_id: expect.any(String), + trace_id: expect.any(String), + data: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom' }, + }, + }, + }, + }) + .start(done); +}); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json index b40c92b4356e..70e2c29be629 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/package.json @@ -16,7 +16,7 @@ "author": "", "license": "ISC", "dependencies": { - "@prisma/client": "5.9.1", - "prisma": "^5.9.1" + "@prisma/client": "5.22.0", + "prisma": "5.22.0" } } diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/test.ts b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/test.ts index dd92de5d0292..4cc1757c0d19 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/test.ts @@ -3,103 +3,137 @@ import { createRunner } from '../../../utils/runner'; conditionalTest({ min: 16 })('Prisma ORM Tests', () => { test('CJS - should instrument PostgreSQL queries from Prisma ORM', done => { - const EXPECTED_TRANSACTION = { - transaction: 'Test Transaction', - spans: expect.arrayContaining([ - expect.objectContaining({ - data: { - method: 'create', - model: 'User', - name: 'User.create', - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:client:operation', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:client:serialize', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:client:connect', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:engine', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'db.type': 'postgres', - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:engine:connection', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'db.statement': expect.stringContaining( - 'INSERT INTO "public"."User" ("createdAt","email","name") VALUES ($1,$2,$3) RETURNING "public"."User"."id", "public"."User"."createdAt", "public"."User"."email", "public"."User"."name" /* traceparent', - ), - 'sentry.origin': 'auto.db.otel.prisma', - 'db.system': 'prisma', - 'sentry.op': 'db', - }, - description: expect.stringContaining( - 'INSERT INTO "public"."User" ("createdAt","email","name") VALUES ($1,$2,$3) RETURNING "public"."User"."id", "public"."User"."createdAt", "public"."User"."email", "public"."User"."name" /* traceparent', - ), - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:engine:serialize', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:engine:response_json_serialization', - status: 'ok', - }), - expect.objectContaining({ - data: { - method: 'findMany', - model: 'User', - name: 'User.findMany', - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:client:operation', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:client:serialize', - status: 'ok', - }), - expect.objectContaining({ - data: { - 'sentry.origin': 'auto.db.otel.prisma', - }, - description: 'prisma:engine', - status: 'ok', - }), - ]), - }; + createRunner(__dirname, 'scenario.js') + .expect({ + transaction: transaction => { + expect(transaction.transaction).toBe('Test Transaction'); - createRunner(__dirname, 'scenario.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done); + const spans = transaction.spans || []; + expect(spans.length).toBeGreaterThanOrEqual(5); + + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + method: 'create', + model: 'User', + name: 'User.create', + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:client:operation', + status: 'ok', + }), + ); + + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:client:serialize', + status: 'ok', + }), + ); + + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:client:connect', + status: 'ok', + }), + ); + + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:engine', + status: 'ok', + }), + ); + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + 'sentry.op': 'db', + 'db.system': 'postgresql', + }, + description: 'prisma:engine:connection', + status: 'ok', + op: 'db', + }), + ); + + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'db.statement': expect.stringContaining( + 'INSERT INTO "public"."User" ("createdAt","email","name") VALUES ($1,$2,$3) RETURNING "public"."User"."id", "public"."User"."createdAt", "public"."User"."email", "public"."User"."name" /* traceparent', + ), + 'sentry.origin': 'auto.db.otel.prisma', + 'sentry.op': 'db', + 'db.system': 'postgresql', + 'otel.kind': 'CLIENT', + }, + description: expect.stringContaining( + 'INSERT INTO "public"."User" ("createdAt","email","name") VALUES ($1,$2,$3) RETURNING "public"."User"."id", "public"."User"."createdAt", "public"."User"."email", "public"."User"."name" /* traceparent', + ), + status: 'ok', + op: 'db', + }), + ); + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:engine:serialize', + status: 'ok', + }), + ); + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:engine:response_json_serialization', + status: 'ok', + }), + ); + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + method: 'findMany', + model: 'User', + name: 'User.findMany', + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:client:operation', + status: 'ok', + }), + ); + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:client:serialize', + status: 'ok', + }), + ); + expect(spans).toContainEqual( + expect.objectContaining({ + data: { + 'sentry.origin': 'auto.db.otel.prisma', + }, + description: 'prisma:engine', + status: 'ok', + }), + ); + }, + }) + .start(done); }); }); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/yarn.lock b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/yarn.lock index 9c0fc47be4be..860aa032d6cc 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/yarn.lock +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/yarn.lock @@ -2,50 +2,57 @@ # yarn lockfile v1 -"@prisma/client@5.9.1": - version "5.9.1" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.9.1.tgz#d92bd2f7f006e0316cb4fda9d73f235965cf2c64" - integrity sha512-caSOnG4kxcSkhqC/2ShV7rEoWwd3XrftokxJqOCMVvia4NYV/TPtJlS9C2os3Igxw/Qyxumj9GBQzcStzECvtQ== - -"@prisma/debug@5.9.1": - version "5.9.1" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.9.1.tgz#906274e73d3267f88b69459199fa3c51cd9511a3" - integrity sha512-yAHFSFCg8KVoL0oRUno3m60GAjsUKYUDkQ+9BA2X2JfVR3kRVSJFc/GpQ2fSORi4pSHZR9orfM4UC9OVXIFFTA== - -"@prisma/engines-version@5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64": - version "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64.tgz#54d2164f28d23e09d41cf9eb0bddbbe7f3aaa660" - integrity sha512-HFl7275yF0FWbdcNvcSRbbu9JCBSLMcurYwvWc8WGDnpu7APxQo2ONtZrUggU3WxLxUJ2uBX+0GOFIcJeVeOOQ== - -"@prisma/engines@5.9.1": - version "5.9.1" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.9.1.tgz#767539afc6f193a182d0495b30b027f61f279073" - integrity sha512-gkdXmjxQ5jktxWNdDA5aZZ6R8rH74JkoKq6LD5mACSvxd2vbqWeWIOV0Py5wFC8vofOYShbt6XUeCIUmrOzOnQ== +"@prisma/client@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.22.0.tgz#da1ca9c133fbefe89e0da781c75e1c59da5f8802" + integrity sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA== + +"@prisma/debug@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.22.0.tgz#58af56ed7f6f313df9fb1042b6224d3174bbf412" + integrity sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ== + +"@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2": + version "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz#d534dd7235c1ba5a23bacd5b92cc0ca3894c28f4" + integrity sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ== + +"@prisma/engines@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.22.0.tgz#28f3f52a2812c990a8b66eb93a0987816a5b6d84" + integrity sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA== dependencies: - "@prisma/debug" "5.9.1" - "@prisma/engines-version" "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64" - "@prisma/fetch-engine" "5.9.1" - "@prisma/get-platform" "5.9.1" - -"@prisma/fetch-engine@5.9.1": - version "5.9.1" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.9.1.tgz#5d3b2c9af54a242e37b3f9561b59ab72f8e92818" - integrity sha512-l0goQOMcNVOJs1kAcwqpKq3ylvkD9F04Ioe1oJoCqmz05mw22bNAKKGWuDd3zTUoUZr97va0c/UfLNru+PDmNA== + "@prisma/debug" "5.22.0" + "@prisma/engines-version" "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" + "@prisma/fetch-engine" "5.22.0" + "@prisma/get-platform" "5.22.0" + +"@prisma/fetch-engine@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz#4fb691b483a450c5548aac2f837b267dd50ef52e" + integrity sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA== dependencies: - "@prisma/debug" "5.9.1" - "@prisma/engines-version" "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64" - "@prisma/get-platform" "5.9.1" - -"@prisma/get-platform@5.9.1": - version "5.9.1" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.9.1.tgz#a66bb46ab4d30db786c84150ef074ab0aad4549e" - integrity sha512-6OQsNxTyhvG+T2Ksr8FPFpuPeL4r9u0JF0OZHUBI/Uy9SS43sPyAIutt4ZEAyqWQt104ERh70EZedkHZKsnNbg== + "@prisma/debug" "5.22.0" + "@prisma/engines-version" "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" + "@prisma/get-platform" "5.22.0" + +"@prisma/get-platform@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.22.0.tgz#fc675bc9d12614ca2dade0506c9c4a77e7dddacd" + integrity sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q== dependencies: - "@prisma/debug" "5.9.1" + "@prisma/debug" "5.22.0" -prisma@^5.9.1: - version "5.9.1" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.9.1.tgz#baa3dd635fbf71504980978f10f55ea11068f6aa" - integrity sha512-Hy/8KJZz0ELtkw4FnG9MS9rNWlXcJhf98Z2QMqi0QiVMoS8PzsBkpla0/Y5hTlob8F3HeECYphBjqmBxrluUrQ== +fsevents@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +prisma@5.22.0: + version "5.22.0" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.22.0.tgz#1f6717ff487cdef5f5799cc1010459920e2e6197" + integrity sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A== dependencies: - "@prisma/engines" "5.9.1" + "@prisma/engines" "5.22.0" + optionalDependencies: + fsevents "2.3.3" diff --git a/dev-packages/rollup-utils/package.json b/dev-packages/rollup-utils/package.json index 763f043da327..fb74a40d5693 100644 --- a/dev-packages/rollup-utils/package.json +++ b/dev-packages/rollup-utils/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/rollup-utils", - "version": "8.45.0", + "version": "8.47.0", "description": "Rollup utilities used at Sentry for the Sentry JavaScript SDK", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/rollup-utils", diff --git a/dev-packages/size-limit-gh-action/package.json b/dev-packages/size-limit-gh-action/package.json index c40c18645d6a..7071201906aa 100644 --- a/dev-packages/size-limit-gh-action/package.json +++ b/dev-packages/size-limit-gh-action/package.json @@ -1,7 +1,7 @@ { "name": "@sentry-internal/size-limit-gh-action", "description": "An internal Github Action to compare the current size of a PR against the one on develop.", - "version": "8.45.0", + "version": "8.47.0", "license": "MIT", "engines": { "node": ">=18" diff --git a/dev-packages/test-utils/package.json b/dev-packages/test-utils/package.json index 09ad4cf5a55d..4248882964e7 100644 --- a/dev-packages/test-utils/package.json +++ b/dev-packages/test-utils/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "8.45.0", + "version": "8.47.0", "name": "@sentry-internal/test-utils", "author": "Sentry", "license": "MIT", @@ -45,7 +45,7 @@ }, "devDependencies": { "@playwright/test": "^1.44.1", - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "volta": { "extends": "../../package.json" diff --git a/docs/assets/run-release-workflow.png b/docs/assets/run-release-workflow.png new file mode 100644 index 000000000000..50af8d111fe8 Binary files /dev/null and b/docs/assets/run-release-workflow.png differ diff --git a/docs/publishing-a-release.md b/docs/publishing-a-release.md index 7b88d6bd41b8..a3fd5b64f0ea 100644 --- a/docs/publishing-a-release.md +++ b/docs/publishing-a-release.md @@ -20,6 +20,21 @@ _These steps are only relevant to Sentry employees when preparing and publishing [@getsentry/releases-approvers](https://github.com/orgs/getsentry/teams/release-approvers) to approve the release. a. Once the release is completed, a sync from `master` ->` develop` will be automatically triggered +## Publishing a release for previous majors + +1. Run `yarn changelog` on the major branch (e.g. `v8`) and determine what version will be released (we use + [semver](https://semver.org)) +2. Create a branch, e.g. `changelog-8.45.1`, off the major branch (e.g. `v8`) +3. Update `CHANGELOG.md` to add an entry for the next release number and a list of changes since the + last release. (See details below.) +4. Open a PR with the title `meta(changelog): Update changelog for VERSION` against the major branch. +5. Once the PR is merged, open the [Prepare Release workflow](https://github.com/getsentry/sentry-javascript/actions/workflows/release.yml) and + fill in ![run-release-workflow.png](./assets/run-release-workflow.png) + 1. The major branch you want to release for, e.g. `v8` + 2. The version you want to release, e.g. `8.45.1` + 3. The major branch to merge into, e.g. `v8` +6. Run the release workflow + ## Updating the Changelog 1. Run `yarn changelog` and copy everything. diff --git a/lerna.json b/lerna.json index febf4090d555..2922aef6d11a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "8.45.0", + "version": "8.47.0", "npmClient": "yarn" } diff --git a/packages/angular/package.json b/packages/angular/package.json index 06bb0492c2f7..e53fcdcc4edf 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/angular", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Angular", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/angular", @@ -21,8 +21,8 @@ "rxjs": "^6.5.5 || ^7.x" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0", + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0", "tslib": "^2.4.1" }, "devDependencies": { diff --git a/packages/angular/src/tracing.ts b/packages/angular/src/tracing.ts index c347a5e19b2e..a5b9391e6ee4 100644 --- a/packages/angular/src/tracing.ts +++ b/packages/angular/src/tracing.ts @@ -1,3 +1,5 @@ +// eslint-disable-next-line @typescript-eslint/consistent-type-imports +import { ElementRef } from '@angular/core'; import type { AfterViewInit, OnDestroy, OnInit } from '@angular/core'; import { Directive, Injectable, Input, NgModule } from '@angular/core'; import type { ActivatedRouteSnapshot, Event, RouterState } from '@angular/router'; @@ -235,10 +237,17 @@ export class TraceService implements OnDestroy { } } -const UNKNOWN_COMPONENT = 'unknown'; - /** - * A directive that can be used to capture initialization lifecycle of the whole component. + * Captures the initialization lifecycle of the component this directive is applied to. + * Specifically, this directive measures the time between `ngOnInit` and `ngAfterViewInit` + * of the component. + * + * Falls back to the component's selector if no name is provided. + * + * @example + * ```html + * + * ``` */ @Directive({ selector: '[trace]' }) export class TraceDirective implements OnInit, AfterViewInit { @@ -246,13 +255,19 @@ export class TraceDirective implements OnInit, AfterViewInit { private _tracingSpan?: Span; + public constructor(private readonly _host: ElementRef) {} + /** * Implementation of OnInit lifecycle method * @inheritdoc */ public ngOnInit(): void { if (!this.componentName) { - this.componentName = UNKNOWN_COMPONENT; + // Technically, the `trace` binding should always be provided. + // However, if it is incorrectly declared on the element without a + // value (e.g., ``), we fall back to using `tagName` + // (which is e.g. `APP-COMPONENT`). + this.componentName = this._host.nativeElement.tagName.toLowerCase(); } if (getActiveSpan()) { diff --git a/packages/astro/package.json b/packages/astro/package.json index 43c374a766cc..32287c849dfa 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/astro", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Astro", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/astro", @@ -56,9 +56,9 @@ "astro": ">=3.x || >=4.0.0-beta || >=5.x" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", "@sentry/vite-plugin": "^2.22.6" }, "devDependencies": { diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index 7eca9de9a41a..ad7481816b4d 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -138,6 +138,7 @@ export { startSpanManual, tediousIntegration, trpcMiddleware, + updateSpanName, withActiveSpan, withIsolationScope, withMonitor, diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 856a7dc4f51f..8ec56890f684 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/aws-serverless", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for AWS Lambda and AWS Serverless Environments", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/serverless", @@ -68,8 +68,8 @@ "@opentelemetry/instrumentation": "^0.56.0", "@opentelemetry/instrumentation-aws-lambda": "0.49.0", "@opentelemetry/instrumentation-aws-sdk": "0.48.0", - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", "@types/aws-lambda": "^8.10.62" }, "devDependencies": { diff --git a/packages/aws-serverless/src/index.ts b/packages/aws-serverless/src/index.ts index 3f167b62a7e3..5146fe423b45 100644 --- a/packages/aws-serverless/src/index.ts +++ b/packages/aws-serverless/src/index.ts @@ -121,6 +121,7 @@ export { spanToTraceHeader, spanToBaggageHeader, trpcMiddleware, + updateSpanName, // eslint-disable-next-line deprecation/deprecation addOpenTelemetryInstrumentation, zodErrorsIntegration, diff --git a/packages/browser-utils/package.json b/packages/browser-utils/package.json index 15d5bde00065..2b5e800e9dda 100644 --- a/packages/browser-utils/package.json +++ b/packages/browser-utils/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/browser-utils", - "version": "8.45.0", + "version": "8.47.0", "description": "Browser Utilities for all Sentry JavaScript SDKs", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/browser-utils", @@ -39,7 +39,7 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "scripts": { "build": "run-p build:transpile build:types", diff --git a/packages/browser/package.json b/packages/browser/package.json index f588f2801eb0..ca91b2388aa9 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/browser", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for browsers", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/browser", @@ -39,14 +39,14 @@ "access": "public" }, "dependencies": { - "@sentry-internal/browser-utils": "8.45.0", - "@sentry-internal/feedback": "8.45.0", - "@sentry-internal/replay": "8.45.0", - "@sentry-internal/replay-canvas": "8.45.0", - "@sentry/core": "8.45.0" + "@sentry-internal/browser-utils": "8.47.0", + "@sentry-internal/feedback": "8.47.0", + "@sentry-internal/replay": "8.47.0", + "@sentry-internal/replay-canvas": "8.47.0", + "@sentry/core": "8.47.0" }, "devDependencies": { - "@sentry-internal/integration-shims": "8.45.0", + "@sentry-internal/integration-shims": "8.47.0", "fake-indexeddb": "^4.0.1" }, "scripts": { diff --git a/packages/browser/src/exports.ts b/packages/browser/src/exports.ts index 492f9da23b38..295e6daa36cc 100644 --- a/packages/browser/src/exports.ts +++ b/packages/browser/src/exports.ts @@ -62,6 +62,7 @@ export { spanToJSON, spanToTraceHeader, spanToBaggageHeader, + updateSpanName, } from '@sentry/core'; export { diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index e6f57c13fe6b..e6e089cbe04c 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -75,3 +75,4 @@ export { } from './integrations/featureFlags'; export { launchDarklyIntegration, buildLaunchDarklyFlagUsedHandler } from './integrations/featureFlags/launchdarkly'; export { openFeatureIntegration, OpenFeatureIntegrationHook } from './integrations/featureFlags/openfeature'; +export { unleashIntegration } from './integrations/featureFlags/unleash'; diff --git a/packages/browser/src/integrations/featureFlags/unleash/index.ts b/packages/browser/src/integrations/featureFlags/unleash/index.ts new file mode 100644 index 000000000000..934ff196ee95 --- /dev/null +++ b/packages/browser/src/integrations/featureFlags/unleash/index.ts @@ -0,0 +1 @@ +export { unleashIntegration } from './integration'; diff --git a/packages/browser/src/integrations/featureFlags/unleash/integration.ts b/packages/browser/src/integrations/featureFlags/unleash/integration.ts new file mode 100644 index 000000000000..c4e3bec09f20 --- /dev/null +++ b/packages/browser/src/integrations/featureFlags/unleash/integration.ts @@ -0,0 +1,36 @@ +import type { Client, Event, EventHint, IntegrationFn } from '@sentry/core'; + +import { defineIntegration } from '@sentry/core'; +import { copyFlagsFromScopeToEvent, insertFlagToScope } from '../../../utils/featureFlags'; +import type { UnleashClient } from './types'; + +/** + * Sentry integration for capturing feature flags from the Unleash SDK. + * + * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information. + * + * @example + * ``` + * import * as Sentry from '@sentry/browser'; + * TODO: + * + * Sentry.init({ + * dsn: '___PUBLIC_DSN___', + * integrations: [TODO:] + * }); + * ``` + */ +export const unleashIntegration = defineIntegration((openFeatureClient: UnleashClient ) => { + return { + name: 'Unleash', + + processEvent(event: Event, _hint: EventHint, _client: Client): Event { + return copyFlagsFromScopeToEvent(event); + }, + + setupOnce() { + openFeatureClient.isEnabled = Proxy(); + openFeatureClient.getVariant = Proxy(); + }, + }; +}) satisfies IntegrationFn; diff --git a/packages/browser/src/integrations/featureFlags/unleash/types.ts b/packages/browser/src/integrations/featureFlags/unleash/types.ts new file mode 100644 index 000000000000..520bfcbdc182 --- /dev/null +++ b/packages/browser/src/integrations/featureFlags/unleash/types.ts @@ -0,0 +1,11 @@ +export type Variant = { + variantName: string; + enabled: boolean; + payload?: object; // TODO: + // TODO: +} + +export interface UnleashClient { + isEnabled(featureName: string): boolean; + getVariant(featureName: string): Variant; +} diff --git a/packages/browser/src/tracing/browserTracingIntegration.ts b/packages/browser/src/tracing/browserTracingIntegration.ts index 17030f2f4a43..78ead340ac12 100644 --- a/packages/browser/src/tracing/browserTracingIntegration.ts +++ b/packages/browser/src/tracing/browserTracingIntegration.ts @@ -465,6 +465,7 @@ export function getMetaContent(metaName: string): string | undefined { // Can't specify generic to `getDomElement` because tracing can be used // in a variety of environments, have to disable `no-unsafe-member-access` // as a result. + // eslint-disable-next-line deprecation/deprecation const metaTag = getDomElement(`meta[name=${metaName}]`); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access return metaTag ? metaTag.getAttribute('content') : undefined; diff --git a/packages/bun/package.json b/packages/bun/package.json index ce1c85cbcd0f..278e143ce4ac 100644 --- a/packages/bun/package.json +++ b/packages/bun/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/bun", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for bun", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/bun", @@ -39,9 +39,9 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", - "@sentry/opentelemetry": "8.45.0" + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", + "@sentry/opentelemetry": "8.47.0" }, "devDependencies": { "bun-types": "latest" diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 1ba5f2de4786..dcae6e98aa8d 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -141,6 +141,7 @@ export { spanToTraceHeader, spanToBaggageHeader, trpcMiddleware, + updateSpanName, // eslint-disable-next-line deprecation/deprecation addOpenTelemetryInstrumentation, zodErrorsIntegration, diff --git a/packages/cloudflare/package.json b/packages/cloudflare/package.json index efec51c5c0f5..97ece632153d 100644 --- a/packages/cloudflare/package.json +++ b/packages/cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/cloudflare", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Cloudflare Workers and Pages", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/cloudflare", @@ -39,7 +39,7 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "optionalDependencies": { "@cloudflare/workers-types": "^4.x" diff --git a/packages/cloudflare/src/index.ts b/packages/cloudflare/src/index.ts index f3c80b8ddf32..fb8c34694282 100644 --- a/packages/cloudflare/src/index.ts +++ b/packages/cloudflare/src/index.ts @@ -89,6 +89,7 @@ export { spanToJSON, spanToTraceHeader, spanToBaggageHeader, + updateSpanName, } from '@sentry/core'; export { withSentry } from './handler'; diff --git a/packages/core/package.json b/packages/core/package.json index ab43b79117b9..5da809ae6de0 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/core", - "version": "8.45.0", + "version": "8.47.0", "description": "Base implementation for all Sentry JavaScript SDKs", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/core", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 77259d2434d4..5baf88f38e1c 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -81,6 +81,7 @@ export { getActiveSpan, addChildSpanToSpan, spanTimeInputToSeconds, + updateSpanName, } from './utils/spanUtils'; export { parseSampleRate } from './utils/parseSampleRate'; export { applySdkMetadata } from './utils/sdkMetadata'; diff --git a/packages/core/src/semanticAttributes.ts b/packages/core/src/semanticAttributes.ts index 2896bd81f93f..b799f5321a0e 100644 --- a/packages/core/src/semanticAttributes.ts +++ b/packages/core/src/semanticAttributes.ts @@ -29,6 +29,15 @@ export const SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT = 'sentry.measurement_un /** The value of a measurement, which may be stored as a TimedEvent. */ export const SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE = 'sentry.measurement_value'; +/** + * A custom span name set by users guaranteed to be taken over any automatically + * inferred name. This attribute is removed before the span is sent. + * + * @internal only meant for internal SDK usage + * @hidden + */ +export const SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME = 'sentry.custom_span_name'; + /** * The id of the profile that this span occurred in. */ diff --git a/packages/core/src/tracing/sentrySpan.ts b/packages/core/src/tracing/sentrySpan.ts index 126702dfad2b..9965261970f2 100644 --- a/packages/core/src/tracing/sentrySpan.ts +++ b/packages/core/src/tracing/sentrySpan.ts @@ -5,6 +5,7 @@ import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary'; import { SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_PROFILE_ID, + SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, @@ -355,6 +356,14 @@ export class SentrySpan implements Span { const source = this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] as TransactionSource | undefined; + // remove internal root span attributes we don't need to send. + /* eslint-disable @typescript-eslint/no-dynamic-delete */ + delete this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]; + spans.forEach(span => { + span.data && delete span.data[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]; + }); + // eslint-enabled-next-line @typescript-eslint/no-dynamic-delete + const transaction: TransactionEvent = { contexts: { trace: spanToTransactionTraceContext(this), diff --git a/packages/core/src/types-hoist/context.ts b/packages/core/src/types-hoist/context.ts index 60aa60b38868..ad6879636086 100644 --- a/packages/core/src/types-hoist/context.ts +++ b/packages/core/src/types-hoist/context.ts @@ -133,6 +133,6 @@ export interface MissingInstrumentationContext extends Record { * directly is not recommended. Use the functions in @sentry/browser * src/utils/featureFlags instead. */ -export interface FeatureFlagContext extends Record { +interface FeatureFlagContext extends Record { values: FeatureFlag[]; } diff --git a/packages/core/src/types-hoist/span.ts b/packages/core/src/types-hoist/span.ts index a2ee74fd7cfa..cf0c3086bf88 100644 --- a/packages/core/src/types-hoist/span.ts +++ b/packages/core/src/types-hoist/span.ts @@ -234,6 +234,16 @@ export interface Span { /** * Update the name of the span. + * + * **Important:** You most likely want to use `Sentry.updateSpanName(span, name)` instead! + * + * This method will update the current span name but cannot guarantee that the new name will be + * the final name of the span. Instrumentation might still overwrite the name with an automatically + * computed name, for example in `http.server` or `db` spans. + * + * You can ensure that your name is kept and not overwritten by calling `Sentry.updateSpanName(span, name)` + * + * @param name the new name of the span */ updateName(name: string): this; diff --git a/packages/core/src/utils-hoist/browser.ts b/packages/core/src/utils-hoist/browser.ts index b3a5220e7c3c..c5d5a91ccb75 100644 --- a/packages/core/src/utils-hoist/browser.ts +++ b/packages/core/src/utils-hoist/browser.ts @@ -155,6 +155,8 @@ export function getLocationHref(): string { * `const element = getDomElement('selector');` * * @param selector the selector string passed on to document.querySelector + * + * @deprecated This method is deprecated and will be removed in the next major version. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function getDomElement(selector: string): E | null { diff --git a/packages/core/src/utils-hoist/index.ts b/packages/core/src/utils-hoist/index.ts index e53cd0edb59b..68a52655fb3a 100644 --- a/packages/core/src/utils-hoist/index.ts +++ b/packages/core/src/utils-hoist/index.ts @@ -2,7 +2,13 @@ export { applyAggregateErrorsToEvent } from './aggregate-errors'; // eslint-disable-next-line deprecation/deprecation export { flatten } from './array'; export { getBreadcrumbLogLevelFromHttpStatusCode } from './breadcrumb-log-level'; -export { getComponentName, getDomElement, getLocationHref, htmlTreeAsString } from './browser'; +export { + getComponentName, + // eslint-disable-next-line deprecation/deprecation + getDomElement, + getLocationHref, + htmlTreeAsString, +} from './browser'; export { dsnFromString, dsnToString, makeDsn } from './dsn'; export { SentryError } from './error'; export { GLOBAL_OBJ, getGlobalSingleton } from './worldwide'; diff --git a/packages/core/src/utils/spanUtils.ts b/packages/core/src/utils/spanUtils.ts index 594a297f9395..09ba9d729449 100644 --- a/packages/core/src/utils/spanUtils.ts +++ b/packages/core/src/utils/spanUtils.ts @@ -3,7 +3,12 @@ import { getMainCarrier } from '../carrier'; import { getCurrentScope } from '../currentScopes'; import { getMetricSummaryJsonForSpan, updateMetricSummaryOnSpan } from '../metrics/metric-summary'; import type { MetricType } from '../metrics/types'; -import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes'; +import { + SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, +} from '../semanticAttributes'; import type { SentrySpan } from '../tracing/sentrySpan'; import { SPAN_STATUS_OK, SPAN_STATUS_UNSET } from '../tracing/spanstatus'; import type { @@ -310,3 +315,27 @@ export function showSpanDropWarning(): void { hasShownSpanDropWarning = true; } } + +/** + * Updates the name of the given span and ensures that the span name is not + * overwritten by the Sentry SDK. + * + * Use this function instead of `span.updateName()` if you want to make sure that + * your name is kept. For some spans, for example root `http.server` spans the + * Sentry SDK would otherwise overwrite the span name with a high-quality name + * it infers when the span ends. + * + * Use this function in server code or when your span is started on the server + * and on the client (browser). If you only update a span name on the client, + * you can also use `span.updateName()` the SDK does not overwrite the name. + * + * @param span - The span to update the name of. + * @param name - The name to set on the span. + */ +export function updateSpanName(span: Span, name: string): void { + span.updateName(name); + span.setAttributes({ + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: name, + }); +} diff --git a/packages/core/test/lib/utils/spanUtils.test.ts b/packages/core/test/lib/utils/spanUtils.test.ts index f7187695a025..aa6d4bf4cb2f 100644 --- a/packages/core/test/lib/utils/spanUtils.test.ts +++ b/packages/core/test/lib/utils/spanUtils.test.ts @@ -1,6 +1,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SPAN_STATUS_ERROR, SPAN_STATUS_OK, SPAN_STATUS_UNSET, @@ -14,8 +15,14 @@ import { } from '../../../src'; import type { Span, SpanAttributes, SpanStatus, SpanTimeInput } from '../../../src/types-hoist'; import type { OpenTelemetrySdkTraceBaseSpan } from '../../../src/utils/spanUtils'; -import { spanToTraceContext } from '../../../src/utils/spanUtils'; -import { getRootSpan, spanIsSampled, spanTimeInputToSeconds, spanToJSON } from '../../../src/utils/spanUtils'; +import { + getRootSpan, + spanIsSampled, + spanTimeInputToSeconds, + spanToJSON, + spanToTraceContext, + updateSpanName, +} from '../../../src/utils/spanUtils'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; function createMockedOtelSpan({ @@ -332,3 +339,13 @@ describe('getRootSpan', () => { }); }); }); + +describe('updateSpanName', () => { + it('updates the span name and source', () => { + const span = new SentrySpan({ name: 'old-name', attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' } }); + updateSpanName(span, 'new-name'); + const spanJSON = spanToJSON(span); + expect(spanJSON.description).toBe('new-name'); + expect(spanJSON.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toBe('custom'); + }); +}); diff --git a/packages/core/test/utils-hoist/browser.test.ts b/packages/core/test/utils-hoist/browser.test.ts index c86570ee7fb0..ac76584908d5 100644 --- a/packages/core/test/utils-hoist/browser.test.ts +++ b/packages/core/test/utils-hoist/browser.test.ts @@ -78,6 +78,7 @@ describe('htmlTreeAsString', () => { describe('getDomElement', () => { it('returns the element for a given query selector', () => { document.head.innerHTML = '
Hello
'; + // eslint-disable-next-line deprecation/deprecation const el = getDomElement('div#mydiv'); expect(el).toBeDefined(); expect(el?.tagName).toEqual('DIV'); diff --git a/packages/deno/package.json b/packages/deno/package.json index b9f7dbdc8ea8..7993decc0b44 100644 --- a/packages/deno/package.json +++ b/packages/deno/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/deno", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Deno", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/deno", @@ -24,7 +24,7 @@ "/build" ], "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.5", diff --git a/packages/deno/src/index.ts b/packages/deno/src/index.ts index 892f6ce681c0..cea4effad4bd 100644 --- a/packages/deno/src/index.ts +++ b/packages/deno/src/index.ts @@ -89,6 +89,7 @@ export { spanToJSON, spanToTraceHeader, spanToBaggageHeader, + updateSpanName, } from '@sentry/core'; export { DenoClient } from './client'; diff --git a/packages/ember/package.json b/packages/ember/package.json index 1547eed88d94..f0f178c477cb 100644 --- a/packages/ember/package.json +++ b/packages/ember/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/ember", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Ember.js", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/ember", @@ -32,8 +32,8 @@ "dependencies": { "@babel/core": "^7.24.4", "@embroider/macros": "^1.16.0", - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0", + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0", "ember-auto-import": "^2.7.2", "ember-cli-babel": "^8.2.0", "ember-cli-htmlbars": "^6.1.1", diff --git a/packages/eslint-config-sdk/package.json b/packages/eslint-config-sdk/package.json index 246f51ed6dcf..62397a6cd160 100644 --- a/packages/eslint-config-sdk/package.json +++ b/packages/eslint-config-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/eslint-config-sdk", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK eslint config", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/eslint-config-sdk", @@ -22,8 +22,8 @@ "access": "public" }, "dependencies": { - "@sentry-internal/eslint-plugin-sdk": "8.45.0", - "@sentry-internal/typescript": "8.45.0", + "@sentry-internal/eslint-plugin-sdk": "8.47.0", + "@sentry-internal/typescript": "8.47.0", "@typescript-eslint/eslint-plugin": "^5.48.0", "@typescript-eslint/parser": "^5.48.0", "eslint-config-prettier": "^6.11.0", diff --git a/packages/eslint-plugin-sdk/package.json b/packages/eslint-plugin-sdk/package.json index 7a6a729fc0cd..0c476b7edb54 100644 --- a/packages/eslint-plugin-sdk/package.json +++ b/packages/eslint-plugin-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/eslint-plugin-sdk", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK eslint plugin", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/eslint-plugin-sdk", diff --git a/packages/feedback/package.json b/packages/feedback/package.json index a5e44856378e..d85ea0f40d74 100644 --- a/packages/feedback/package.json +++ b/packages/feedback/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/feedback", - "version": "8.45.0", + "version": "8.47.0", "description": "Sentry SDK integration for user feedback", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/feedback", @@ -39,7 +39,7 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "devDependencies": { "preact": "^10.19.4" diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 2c03fae30f14..c09ae453f4b4 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/gatsby", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Gatsby.js", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/gatsby", @@ -45,8 +45,8 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/react": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/react": "8.47.0", "@sentry/webpack-plugin": "2.22.7" }, "peerDependencies": { diff --git a/packages/google-cloud-serverless/package.json b/packages/google-cloud-serverless/package.json index 52008df49931..53bf8c4d1e7f 100644 --- a/packages/google-cloud-serverless/package.json +++ b/packages/google-cloud-serverless/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/google-cloud-serverless", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Google Cloud Functions", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/google-cloud-serverless", @@ -48,8 +48,8 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", "@types/express": "^4.17.14" }, "devDependencies": { diff --git a/packages/google-cloud-serverless/src/index.ts b/packages/google-cloud-serverless/src/index.ts index 6f89769c2a37..95d30ec8b072 100644 --- a/packages/google-cloud-serverless/src/index.ts +++ b/packages/google-cloud-serverless/src/index.ts @@ -118,6 +118,7 @@ export { spanToTraceHeader, spanToBaggageHeader, trpcMiddleware, + updateSpanName, // eslint-disable-next-line deprecation/deprecation addOpenTelemetryInstrumentation, zodErrorsIntegration, diff --git a/packages/integration-shims/package.json b/packages/integration-shims/package.json index 322922a945a0..e864d9e18472 100644 --- a/packages/integration-shims/package.json +++ b/packages/integration-shims/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/integration-shims", - "version": "8.45.0", + "version": "8.47.0", "description": "Shims for integrations in Sentry SDK.", "main": "build/cjs/index.js", "module": "build/esm/index.js", @@ -55,7 +55,7 @@ "url": "https://github.com/getsentry/sentry-javascript/issues" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "engines": { "node": ">=14.18" diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index 1bef4cc56c2f..b1efc0df71c9 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/nestjs", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for NestJS", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/nestjs", @@ -14,8 +14,8 @@ "/*.d.ts", "/*.d.ts.map" ], - "main": "build/cjs/nestjs/index.js", - "module": "build/esm/nestjs/index.js", + "main": "build/cjs/index.js", + "module": "build/esm/index.js", "types": "build/types/index.d.ts", "exports": { "./package.json": "./package.json", @@ -44,8 +44,8 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0" + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0" }, "devDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index baafbe149a1d..86f30fefb6fb 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/nextjs", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Next.js", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/nextjs", @@ -79,12 +79,12 @@ "@opentelemetry/api": "^1.9.0", "@opentelemetry/semantic-conventions": "^1.28.0", "@rollup/plugin-commonjs": "28.0.1", - "@sentry-internal/browser-utils": "8.45.0", - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", - "@sentry/opentelemetry": "8.45.0", - "@sentry/react": "8.45.0", - "@sentry/vercel-edge": "8.45.0", + "@sentry-internal/browser-utils": "8.47.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", + "@sentry/opentelemetry": "8.47.0", + "@sentry/react": "8.47.0", + "@sentry/vercel-edge": "8.47.0", "@sentry/webpack-plugin": "2.22.7", "chalk": "3.0.0", "resolve": "1.22.8", diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 9fb3bef49e67..d8a29d7d025c 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -340,7 +340,7 @@ export function constructWebpackConfigFunction( if (!isServer && !userSentryOptions.sourcemaps?.deleteSourcemapsAfterUpload) { // eslint-disable-next-line no-console console.warn( - "[@sentry/nextjs] The Sentry SDK has enabled source map generation for your Next.js app. If you don't want to serve Source Maps to your users, either set the `deleteSourceMapsAfterUpload` option to true, or manually delete the source maps after the build. In future Sentry SDK versions `deleteSourceMapsAfterUpload` will default to `true`. If you do not want to generate and upload sourcemaps, set the `sourcemaps.disable` option in `withSentryConfig()`.", + "[@sentry/nextjs] The Sentry SDK has enabled source map generation for your Next.js app. If you don't want to serve Source Maps to your users, either set the `sourcemaps.deleteSourcemapsAfterUpload` option to true, or manually delete the source maps after the build. In future Sentry SDK versions `sourcemaps.deleteSourcemapsAfterUpload` will default to `true`. If you do not want to generate and upload sourcemaps, set the `sourcemaps.disable` option in `withSentryConfig()`.", ); } diff --git a/packages/nitro-utils/package.json b/packages/nitro-utils/package.json index 06ec390ef87f..12be2c609acf 100644 --- a/packages/nitro-utils/package.json +++ b/packages/nitro-utils/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/nitro-utils", - "version": "8.45.0", + "version": "8.47.0", "description": "Utilities for all Sentry SDKs with Nitro on the server-side", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/nitro-utils", @@ -37,7 +37,7 @@ } }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "devDependencies": { "rollup": "^4.24.4" diff --git a/packages/node/package.json b/packages/node/package.json index 618b9aa89725..c36697b6a6a3 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/node", - "version": "8.45.0", + "version": "8.47.0", "description": "Sentry Node SDK using OpenTelemetry for performance instrumentation", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/node", @@ -96,9 +96,9 @@ "@opentelemetry/resources": "^1.29.0", "@opentelemetry/sdk-trace-base": "^1.29.0", "@opentelemetry/semantic-conventions": "^1.28.0", - "@prisma/instrumentation": "5.19.1", - "@sentry/core": "8.45.0", - "@sentry/opentelemetry": "8.45.0", + "@prisma/instrumentation": "5.22.0", + "@sentry/core": "8.47.0", + "@sentry/opentelemetry": "8.47.0", "import-in-the-middle": "^1.11.2" }, "devDependencies": { diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index fa16ac4e6b3d..215d53bdbde3 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -142,6 +142,7 @@ export { spanToTraceHeader, spanToBaggageHeader, trpcMiddleware, + updateSpanName, zodErrorsIntegration, profiler, } from '@sentry/core'; diff --git a/packages/node/src/integrations/anr/common.ts b/packages/node/src/integrations/anr/common.ts index e2666e3ecd3e..fc1b23e35b1d 100644 --- a/packages/node/src/integrations/anr/common.ts +++ b/packages/node/src/integrations/anr/common.ts @@ -21,6 +21,12 @@ export interface AnrIntegrationOptions { * This uses the node debugger which enables the inspector API and opens the required ports. */ captureStackTrace: boolean; + /** + * Maximum number of ANR events to send. + * + * Defaults to 1. + */ + maxAnrEvents: number; /** * Tags to include with ANR events. */ diff --git a/packages/node/src/integrations/anr/index.ts b/packages/node/src/integrations/anr/index.ts index f0cef4d60831..aa903789ad12 100644 --- a/packages/node/src/integrations/anr/index.ts +++ b/packages/node/src/integrations/anr/index.ts @@ -160,6 +160,7 @@ async function _startWorker( pollInterval: integrationOptions.pollInterval || DEFAULT_INTERVAL, anrThreshold: integrationOptions.anrThreshold || DEFAULT_HANG_THRESHOLD, captureStackTrace: !!integrationOptions.captureStackTrace, + maxAnrEvents: integrationOptions.maxAnrEvents || 1, staticTags: integrationOptions.staticTags || {}, contexts, }; @@ -175,6 +176,7 @@ async function _startWorker( workerData: options, // We don't want any Node args to be passed to the worker execArgv: [], + env: { ...process.env, NODE_OPTIONS: undefined }, }); process.on('exit', () => { diff --git a/packages/node/src/integrations/anr/worker.ts b/packages/node/src/integrations/anr/worker.ts index 354cea514618..117cccfe8904 100644 --- a/packages/node/src/integrations/anr/worker.ts +++ b/packages/node/src/integrations/anr/worker.ts @@ -23,7 +23,7 @@ type VoidFunction = () => void; const options: WorkerStartData = workerData; let session: Session | undefined; -let hasSentAnrEvent = false; +let sentAnrEvents = 0; let mainDebugImages: Record = {}; function log(msg: string): void { @@ -91,24 +91,31 @@ function applyDebugMeta(event: Event): void { return; } + const normalisedDebugImages = options.appRootPath ? {} : mainDebugImages; + if (options.appRootPath) { + for (const [path, debugId] of Object.entries(mainDebugImages)) { + normalisedDebugImages[normalizeUrlToBase(path, options.appRootPath)] = debugId; + } + } + const filenameToDebugId = new Map(); for (const exception of event.exception?.values || []) { for (const frame of exception.stacktrace?.frames || []) { const filename = frame.abs_path || frame.filename; - if (filename && mainDebugImages[filename]) { - filenameToDebugId.set(filename, mainDebugImages[filename] as string); + if (filename && normalisedDebugImages[filename]) { + filenameToDebugId.set(filename, normalisedDebugImages[filename] as string); } } } if (filenameToDebugId.size > 0) { const images: DebugImage[] = []; - for (const [filename, debugId] of filenameToDebugId.entries()) { + for (const [code_file, debug_id] of filenameToDebugId.entries()) { images.push({ type: 'sourcemap', - code_file: filename, - debug_id: debugId, + code_file, + debug_id, }); } event.debug_meta = { images }; @@ -134,11 +141,11 @@ function applyScopeToEvent(event: Event, scope: ScopeData): void { } async function sendAnrEvent(frames?: StackFrame[], scope?: ScopeData): Promise { - if (hasSentAnrEvent) { + if (sentAnrEvents >= options.maxAnrEvents) { return; } - hasSentAnrEvent = true; + sentAnrEvents += 1; await sendAbnormalSession(); @@ -179,11 +186,13 @@ async function sendAnrEvent(frames?: StackFrame[], scope?: ScopeData): Promise { - process.exit(0); - }, 5_000); + if (sentAnrEvents >= options.maxAnrEvents) { + // Delay for 5 seconds so that stdio can flush if the main event loop ever restarts. + // This is mainly for the benefit of logging or debugging. + setTimeout(() => { + process.exit(0); + }, 5_000); + } } let debuggerPause: VoidFunction | undefined; diff --git a/packages/node/src/integrations/local-variables/local-variables-async.ts b/packages/node/src/integrations/local-variables/local-variables-async.ts index e1e0ebadf755..c3dcb1d12450 100644 --- a/packages/node/src/integrations/local-variables/local-variables-async.ts +++ b/packages/node/src/integrations/local-variables/local-variables-async.ts @@ -81,6 +81,7 @@ export const localVariablesAsyncIntegration = defineIntegration((( workerData: options, // We don't want any Node args to be passed to the worker execArgv: [], + env: { ...process.env, NODE_OPTIONS: undefined }, }); process.on('exit', () => { diff --git a/packages/node/src/integrations/tracing/prisma.ts b/packages/node/src/integrations/tracing/prisma.ts index a42d41a6b5ec..a139de3a78fb 100644 --- a/packages/node/src/integrations/tracing/prisma.ts +++ b/packages/node/src/integrations/tracing/prisma.ts @@ -29,7 +29,9 @@ const _prismaIntegration = (() => { span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.prisma'); } - if (spanJSON.description === 'prisma:engine:db_query') { + // In Prisma v5.22+, the `db.system` attribute is automatically set + // On older versions, this is missing, so we add it here + if (spanJSON.description === 'prisma:engine:db_query' && !spanJSON.data?.['db.system']) { span.setAttribute('db.system', 'prisma'); } }); diff --git a/packages/node/src/sdk/api.ts b/packages/node/src/sdk/api.ts index dd7ccc8ca75d..7e4f200d1e06 100644 --- a/packages/node/src/sdk/api.ts +++ b/packages/node/src/sdk/api.ts @@ -68,6 +68,8 @@ export function getSentryRelease(fallback?: string): string | undefined { process.env['HEROKU_TEST_RUN_COMMIT_VERSION'] || // Heroku #2 https://docs.sentry.io/product/integrations/deployment/heroku/#configure-releases process.env['HEROKU_SLUG_COMMIT'] || + // Railway - https://docs.railway.app/reference/variables#git-variables + process.env['RAILWAY_GIT_COMMIT_SHA'] || // Render - https://render.com/docs/environment-variables process.env['RENDER_GIT_COMMIT'] || // Semaphore CI - https://docs.semaphoreci.com/ci-cd-environment/environment-variables diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 86ce75ba76f8..d96bdc3cacf9 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/nuxt", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Nuxt (EXPERIMENTAL)", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/nuxt", @@ -43,13 +43,13 @@ }, "dependencies": { "@nuxt/kit": "^3.13.2", - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", - "@sentry/opentelemetry": "8.45.0", + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", + "@sentry/opentelemetry": "8.47.0", "@sentry/rollup-plugin": "2.22.7", "@sentry/vite-plugin": "2.22.6", - "@sentry/vue": "8.45.0" + "@sentry/vue": "8.47.0" }, "devDependencies": { "@nuxt/module-builder": "^0.8.4", diff --git a/packages/nuxt/tsconfig.types.json b/packages/nuxt/tsconfig.types.json index 65455f66bd75..cab81135cd7a 100644 --- a/packages/nuxt/tsconfig.types.json +++ b/packages/nuxt/tsconfig.types.json @@ -1,6 +1,6 @@ { "extends": "./tsconfig.json", - + "exclude": ["build.config.ts"], "compilerOptions": { "declaration": true, "declarationMap": true, diff --git a/packages/opentelemetry/package.json b/packages/opentelemetry/package.json index e342a8d34be8..db7cbabdce62 100644 --- a/packages/opentelemetry/package.json +++ b/packages/opentelemetry/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/opentelemetry", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry utilities for OpenTelemetry", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/opentelemetry", @@ -39,7 +39,7 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index a8d5affa4646..bff6518eb27d 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -12,6 +12,7 @@ import type { TransactionSource, } from '@sentry/core'; import { + SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, @@ -392,6 +393,7 @@ function removeSentryAttributes(data: Record): Record = {}; @@ -174,12 +198,21 @@ export function descriptionForHttpMethod( const origin = attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] || 'manual'; const isManualSpan = !`${origin}`.startsWith('auto'); - const useInferredDescription = isClientOrServerKind || !isManualSpan; + // If users (or in very rare occasions we) set the source to custom, we don't overwrite the name + const alreadyHasCustomSource = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === 'custom'; + const customSpanName = attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]; + + const useInferredDescription = + !alreadyHasCustomSource && customSpanName == null && (isClientOrServerKind || !isManualSpan); + + const { description, source } = useInferredDescription + ? { description: inferredDescription, source: inferredSource } + : getUserUpdatedNameAndSource(name, attributes); return { op: opParts.join('.'), - description: useInferredDescription ? description : name, - source: useInferredDescription ? source : 'custom', + description, + source, data, }; } @@ -244,3 +277,36 @@ export function getSanitizedUrl( return { urlPath: undefined, url, query, fragment, hasRoute: false }; } + +/** + * Because Otel instrumentation sometimes mutates span names via `span.updateName`, the only way + * to ensure that a user-set span name is preserved is to store it as a tmp attribute on the span. + * We delete this attribute once we're done with it when preparing the event envelope. + * + * This temp attribute always takes precedence over the original name. + * + * We also need to take care of setting the correct source. Users can always update the source + * after updating the name, so we need to respect that. + * + * @internal exported only for testing + */ +export function getUserUpdatedNameAndSource( + originalName: string, + attributes: Attributes, + fallbackSource: TransactionSource = 'custom', +): { + description: string; + source: TransactionSource; +} { + const source = (attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] as TransactionSource) || fallbackSource; + const description = attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]; + + if (description && typeof description === 'string') { + return { + description, + source, + }; + } + + return { description: originalName, source }; +} diff --git a/packages/opentelemetry/test/utils/parseSpanDescription.test.ts b/packages/opentelemetry/test/utils/parseSpanDescription.test.ts index c44645c62888..d43dfcd9f587 100644 --- a/packages/opentelemetry/test/utils/parseSpanDescription.test.ts +++ b/packages/opentelemetry/test/utils/parseSpanDescription.test.ts @@ -15,7 +15,13 @@ import { SEMATTRS_RPC_SERVICE, } from '@opentelemetry/semantic-conventions'; -import { descriptionForHttpMethod, getSanitizedUrl, parseSpanDescription } from '../../src/utils/parseSpanDescription'; +import { SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; +import { + descriptionForHttpMethod, + getSanitizedUrl, + getUserUpdatedNameAndSource, + parseSpanDescription, +} from '../../src/utils/parseSpanDescription'; describe('parseSpanDescription', () => { it.each([ @@ -81,6 +87,53 @@ describe('parseSpanDescription', () => { source: 'task', }, ], + [ + 'works with db system and custom source', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_DB_SYSTEM]: 'mysql', + [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + }, + 'test name', + SpanKind.CLIENT, + { + description: 'test name', + op: 'db', + source: 'custom', + }, + ], + [ + 'works with db system and custom source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_DB_SYSTEM]: 'mysql', + [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + SpanKind.CLIENT, + { + description: 'custom name', + op: 'db', + source: 'custom', + }, + ], + [ + 'works with db system and component source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMATTRS_DB_SYSTEM]: 'mysql', + [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + SpanKind.CLIENT, + { + description: 'custom name', + op: 'db', + source: 'component', + }, + ], [ 'works with db system without statement', { @@ -107,6 +160,50 @@ describe('parseSpanDescription', () => { source: 'route', }, ], + [ + 'works with rpc service and custom source', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_RPC_SERVICE]: 'rpc-test-service', + }, + 'test name', + undefined, + { + description: 'test name', + op: 'rpc', + source: 'custom', + }, + ], + [ + 'works with rpc service and custom source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_RPC_SERVICE]: 'rpc-test-service', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + undefined, + { + description: 'custom name', + op: 'rpc', + source: 'custom', + }, + ], + [ + 'works with rpc service and component source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMATTRS_RPC_SERVICE]: 'rpc-test-service', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + undefined, + { + description: 'custom name', + op: 'rpc', + source: 'component', + }, + ], [ 'works with messaging system', { @@ -120,6 +217,50 @@ describe('parseSpanDescription', () => { source: 'route', }, ], + [ + 'works with messaging system and custom source', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_MESSAGING_SYSTEM]: 'test-messaging-system', + }, + 'test name', + undefined, + { + description: 'test name', + op: 'message', + source: 'custom', + }, + ], + [ + 'works with messaging system and custom source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_MESSAGING_SYSTEM]: 'test-messaging-system', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + undefined, + { + description: 'custom name', + op: 'message', + source: 'custom', + }, + ], + [ + 'works with messaging system and component source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMATTRS_MESSAGING_SYSTEM]: 'test-messaging-system', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + undefined, + { + description: 'custom name', + op: 'message', + source: 'component', + }, + ], [ 'works with faas trigger', { @@ -133,6 +274,50 @@ describe('parseSpanDescription', () => { source: 'route', }, ], + [ + 'works with faas trigger and custom source', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_FAAS_TRIGGER]: 'test-faas-trigger', + }, + 'test name', + undefined, + { + description: 'test name', + op: 'test-faas-trigger', + source: 'custom', + }, + ], + [ + 'works with faas trigger and custom source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMATTRS_FAAS_TRIGGER]: 'test-faas-trigger', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + undefined, + { + description: 'custom name', + op: 'test-faas-trigger', + source: 'custom', + }, + ], + [ + 'works with faas trigger and component source and custom name', + { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMATTRS_FAAS_TRIGGER]: 'test-faas-trigger', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + undefined, + { + description: 'custom name', + op: 'test-faas-trigger', + source: 'component', + }, + ], ])('%s', (_, attributes, name, kind, expected) => { const actual = parseSpanDescription({ attributes, kind, name } as unknown as Span); expect(actual).toEqual(expected); @@ -172,6 +357,26 @@ describe('descriptionForHttpMethod', () => { source: 'url', }, ], + [ + 'works with prefetch request', + 'GET', + { + [SEMATTRS_HTTP_METHOD]: 'GET', + [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path', + [SEMATTRS_HTTP_TARGET]: '/my-path', + 'sentry.http.prefetch': true, + }, + 'test name', + SpanKind.CLIENT, + { + op: 'http.client.prefetch', + description: 'GET https://www.example.com/my-path', + data: { + url: 'https://www.example.com/my-path', + }, + source: 'url', + }, + ], [ 'works with basic server POST', 'POST', @@ -230,6 +435,71 @@ describe('descriptionForHttpMethod', () => { source: 'custom', }, ], + [ + "doesn't overwrite span name with source custom", + 'GET', + { + [SEMATTRS_HTTP_METHOD]: 'GET', + [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path/123', + [SEMATTRS_HTTP_TARGET]: '/my-path/123', + [ATTR_HTTP_ROUTE]: '/my-path/:id', + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + }, + 'test name', + SpanKind.CLIENT, + { + op: 'http.client', + description: 'test name', + data: { + url: 'https://www.example.com/my-path/123', + }, + source: 'custom', + }, + ], + [ + 'takes user-passed span name (with source custom)', + 'GET', + { + [SEMATTRS_HTTP_METHOD]: 'GET', + [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path/123', + [SEMATTRS_HTTP_TARGET]: '/my-path/123', + [ATTR_HTTP_ROUTE]: '/my-path/:id', + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + SpanKind.CLIENT, + { + op: 'http.client', + description: 'custom name', + data: { + url: 'https://www.example.com/my-path/123', + }, + source: 'custom', + }, + ], + [ + 'takes user-passed span name (with source component)', + 'GET', + { + [SEMATTRS_HTTP_METHOD]: 'GET', + [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path/123', + [SEMATTRS_HTTP_TARGET]: '/my-path/123', + [ATTR_HTTP_ROUTE]: '/my-path/:id', + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + }, + 'test name', + SpanKind.CLIENT, + { + op: 'http.client', + description: 'custom name', + data: { + url: 'https://www.example.com/my-path/123', + }, + source: 'component', + }, + ], ])('%s', (_, httpMethod, attributes, name, kind, expected) => { const actual = descriptionForHttpMethod({ attributes, kind, name }, httpMethod); expect(actual).toEqual(expected); @@ -383,3 +653,38 @@ describe('getSanitizedUrl', () => { expect(actual).toEqual(expected); }); }); + +describe('getUserUpdatedNameAndSource', () => { + it('returns param name if `SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME` attribute is not set', () => { + expect(getUserUpdatedNameAndSource('base name', {})).toEqual({ description: 'base name', source: 'custom' }); + }); + + it('returns param name with custom fallback source if `SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME` attribute is not set', () => { + expect(getUserUpdatedNameAndSource('base name', {}, 'route')).toEqual({ + description: 'base name', + source: 'route', + }); + }); + + it('returns param name if `SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME` attribute is not a string', () => { + expect(getUserUpdatedNameAndSource('base name', { [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 123 })).toEqual({ + description: 'base name', + source: 'custom', + }); + }); + + it.each(['custom', 'task', 'url', 'route'])( + 'returns `SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME` attribute if is a string and source is %s', + source => { + expect( + getUserUpdatedNameAndSource('base name', { + [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: 'custom name', + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source, + }), + ).toEqual({ + description: 'custom name', + source, + }); + }, + ); +}); diff --git a/packages/profiling-node/package.json b/packages/profiling-node/package.json index 19ecb062875e..e4659a6b0f38 100644 --- a/packages/profiling-node/package.json +++ b/packages/profiling-node/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/profiling-node", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Node.js Profiling", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/profiling-node", @@ -75,8 +75,8 @@ "test": "cross-env SENTRY_PROFILER_BINARY_DIR=lib jest --config jest.config.js" }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", "detect-libc": "^2.0.2", "node-abi": "^3.61.0" }, diff --git a/packages/react/package.json b/packages/react/package.json index d14ad2f112a8..4ec628a6fc95 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/react", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for React.js", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/react", @@ -39,8 +39,8 @@ "access": "public" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0", + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0", "hoist-non-react-statics": "^3.3.2" }, "peerDependencies": { diff --git a/packages/remix/package.json b/packages/remix/package.json index 9967c77676bc..fb0f7b3181a8 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/remix", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Remix", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/remix", @@ -55,10 +55,10 @@ "@opentelemetry/api": "^1.9.0", "@remix-run/router": "1.x", "@sentry/cli": "^2.39.1", - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", - "@sentry/opentelemetry": "8.45.0", - "@sentry/react": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", + "@sentry/opentelemetry": "8.47.0", + "@sentry/react": "8.47.0", "glob": "^10.3.4", "opentelemetry-instrumentation-remix": "0.8.0", "yargs": "^17.6.0" diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index f6a5f5060dd9..4bb6539dbd33 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -134,6 +134,7 @@ export { startSpanManual, tediousIntegration, trpcMiddleware, + updateSpanName, withActiveSpan, withIsolationScope, withMonitor, diff --git a/packages/replay-canvas/package.json b/packages/replay-canvas/package.json index 4faeb7db1ef7..5f8d3450705b 100644 --- a/packages/replay-canvas/package.json +++ b/packages/replay-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/replay-canvas", - "version": "8.45.0", + "version": "8.47.0", "description": "Replay canvas integration", "main": "build/npm/cjs/index.js", "module": "build/npm/esm/index.js", @@ -68,8 +68,8 @@ "@sentry-internal/rrweb": "2.31.0" }, "dependencies": { - "@sentry-internal/replay": "8.45.0", - "@sentry/core": "8.45.0" + "@sentry-internal/replay": "8.47.0", + "@sentry/core": "8.47.0" }, "engines": { "node": ">=14.18" diff --git a/packages/replay-internal/package.json b/packages/replay-internal/package.json index 4267723b8b67..80ebd01c3ca0 100644 --- a/packages/replay-internal/package.json +++ b/packages/replay-internal/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/replay", - "version": "8.45.0", + "version": "8.47.0", "description": "User replays for Sentry", "main": "build/npm/cjs/index.js", "module": "build/npm/esm/index.js", @@ -68,7 +68,7 @@ "homepage": "https://docs.sentry.io/platforms/javascript/session-replay/", "devDependencies": { "@babel/core": "^7.17.5", - "@sentry-internal/replay-worker": "8.45.0", + "@sentry-internal/replay-worker": "8.47.0", "@sentry-internal/rrweb": "2.31.0", "@sentry-internal/rrweb-snapshot": "2.31.0", "fflate": "^0.8.1", @@ -76,8 +76,8 @@ "jsdom-worker": "^0.2.1" }, "dependencies": { - "@sentry-internal/browser-utils": "8.45.0", - "@sentry/core": "8.45.0" + "@sentry-internal/browser-utils": "8.47.0", + "@sentry/core": "8.47.0" }, "engines": { "node": ">=14.18" diff --git a/packages/replay-internal/src/util/getPrivacyOptions.ts b/packages/replay-internal/src/util/getPrivacyOptions.ts index ba35ec21476d..a5aa3d392632 100644 --- a/packages/replay-internal/src/util/getPrivacyOptions.ts +++ b/packages/replay-internal/src/util/getPrivacyOptions.ts @@ -25,7 +25,7 @@ function getOption(selectors: string[], defaultSelectors: string[]): string { * Returns privacy related configuration for use in rrweb */ export function getPrivacyOptions({ mask, unmask, block, unblock, ignore }: GetPrivacyOptions): GetPrivacyReturn { - const defaultBlockedElements = ['base[href="/"]']; + const defaultBlockedElements = ['base', 'iframe[srcdoc]:not([src])']; const maskSelector = getOption(mask, ['.sentry-mask', '[data-sentry-mask]']); const unmaskSelector = getOption(unmask, []); diff --git a/packages/replay-internal/test/integration/integrationSettings.test.ts b/packages/replay-internal/test/integration/integrationSettings.test.ts index 62dc2a4a6588..8f7f39fdcf1a 100644 --- a/packages/replay-internal/test/integration/integrationSettings.test.ts +++ b/packages/replay-internal/test/integration/integrationSettings.test.ts @@ -17,7 +17,9 @@ describe('Integration | integrationSettings', () => { it('sets the correct configuration when `blockAllMedia` is disabled', async () => { const { replay } = await mockSdk({ replayOptions: { blockAllMedia: false } }); - expect(replay['_recordingOptions'].blockSelector).toBe('.sentry-block,[data-sentry-block],base[href="/"]'); + expect(replay['_recordingOptions'].blockSelector).toBe( + '.sentry-block,[data-sentry-block],base,iframe[srcdoc]:not([src])', + ); }); }); diff --git a/packages/replay-internal/test/integration/rrweb.test.ts b/packages/replay-internal/test/integration/rrweb.test.ts index 4327ddb21de1..cd3fbcd095be 100644 --- a/packages/replay-internal/test/integration/rrweb.test.ts +++ b/packages/replay-internal/test/integration/rrweb.test.ts @@ -23,7 +23,7 @@ describe('Integration | rrweb', () => { }); expect(mockRecord.mock.calls[0]?.[0]).toMatchInlineSnapshot(` { - "blockSelector": ".sentry-block,[data-sentry-block],base[href="/"],img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]", + "blockSelector": ".sentry-block,[data-sentry-block],base,iframe[srcdoc]:not([src]),img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]", "collectFonts": true, "emit": [Function], "errorHandler": [Function], @@ -62,7 +62,7 @@ describe('Integration | rrweb', () => { expect(mockRecord.mock.calls[0]?.[0]).toMatchInlineSnapshot(` { - "blockSelector": ".sentry-block,[data-sentry-block],base[href="/"],img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]", + "blockSelector": ".sentry-block,[data-sentry-block],base,iframe[srcdoc]:not([src]),img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]", "checkoutEveryNms": 360000, "collectFonts": true, "emit": [Function], diff --git a/packages/replay-internal/test/unit/util/getPrivacyOptions.test.ts b/packages/replay-internal/test/unit/util/getPrivacyOptions.test.ts index 8595ca6aa1c4..3123e3efaa7c 100644 --- a/packages/replay-internal/test/unit/util/getPrivacyOptions.test.ts +++ b/packages/replay-internal/test/unit/util/getPrivacyOptions.test.ts @@ -21,7 +21,7 @@ describe('Unit | util | getPrivacyOptions', () => { }), ).toMatchInlineSnapshot(` { - "blockSelector": ".custom-block,.sentry-block,[data-sentry-block],base[href="/"]", + "blockSelector": ".custom-block,.sentry-block,[data-sentry-block],base,iframe[srcdoc]:not([src])", "ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore],input[type="file"]", "maskTextSelector": ".custom-mask,.sentry-mask,[data-sentry-mask]", "unblockSelector": ".custom-unblock", diff --git a/packages/replay-worker/package.json b/packages/replay-worker/package.json index 7a1596319e4f..d3c3a2f9e8f8 100644 --- a/packages/replay-worker/package.json +++ b/packages/replay-worker/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/replay-worker", - "version": "8.45.0", + "version": "8.47.0", "description": "Worker for @sentry-internal/replay", "main": "build/esm/index.js", "module": "build/esm/index.js", diff --git a/packages/solid/package.json b/packages/solid/package.json index f718a1374a11..bfe49a8b0179 100644 --- a/packages/solid/package.json +++ b/packages/solid/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/solid", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Solid", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/solid", @@ -44,8 +44,8 @@ "access": "public" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0" + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0" }, "peerDependencies": { "@solidjs/router": "^0.13.4", diff --git a/packages/solidstart/package.json b/packages/solidstart/package.json index dba27d321153..574b0691c35c 100644 --- a/packages/solidstart/package.json +++ b/packages/solidstart/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/solidstart", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Solid Start", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/solidstart", @@ -66,10 +66,10 @@ } }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", - "@sentry/opentelemetry": "8.45.0", - "@sentry/solid": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", + "@sentry/opentelemetry": "8.47.0", + "@sentry/solid": "8.47.0", "@sentry/vite-plugin": "2.22.6" }, "devDependencies": { diff --git a/packages/solidstart/src/server/index.ts b/packages/solidstart/src/server/index.ts index 450420a2b586..4c1f192b0c36 100644 --- a/packages/solidstart/src/server/index.ts +++ b/packages/solidstart/src/server/index.ts @@ -126,6 +126,7 @@ export { startSpanManual, tediousIntegration, trpcMiddleware, + updateSpanName, withActiveSpan, withIsolationScope, withMonitor, diff --git a/packages/svelte/package.json b/packages/svelte/package.json index fb95251cf35b..ff1a40be18d0 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/svelte", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Svelte", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/svelte", @@ -39,8 +39,8 @@ "access": "public" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0", + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0", "magic-string": "^0.30.0" }, "peerDependencies": { diff --git a/packages/svelte/src/sdk.ts b/packages/svelte/src/sdk.ts index 1d21b72ef59d..a1d78195b50f 100644 --- a/packages/svelte/src/sdk.ts +++ b/packages/svelte/src/sdk.ts @@ -55,5 +55,6 @@ export function detectAndReportSvelteKit(): void { * @see https://github.com/sveltejs/kit/issues/307 for more information */ export function isSvelteKitApp(): boolean { + // eslint-disable-next-line deprecation/deprecation return getDomElement('div#svelte-announcer') !== null; } diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json index 7ae146015a74..7e841d73e078 100644 --- a/packages/sveltekit/package.json +++ b/packages/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/sveltekit", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for SvelteKit", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/sveltekit", @@ -40,10 +40,10 @@ } }, "dependencies": { - "@sentry/core": "8.45.0", - "@sentry/node": "8.45.0", - "@sentry/opentelemetry": "8.45.0", - "@sentry/svelte": "8.45.0", + "@sentry/core": "8.47.0", + "@sentry/node": "8.47.0", + "@sentry/opentelemetry": "8.47.0", + "@sentry/svelte": "8.47.0", "@sentry/vite-plugin": "2.22.6", "magic-string": "0.30.7", "magicast": "0.2.8", diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index bb88e121244f..4996dcc0e7ca 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -128,6 +128,7 @@ export { startSpanManual, tediousIntegration, trpcMiddleware, + updateSpanName, withActiveSpan, withIsolationScope, withMonitor, diff --git a/packages/types/package.json b/packages/types/package.json index 26927c6882b9..37278e7fd5b3 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/types", - "version": "8.45.0", + "version": "8.47.0", "description": "Types for all Sentry JavaScript SDKs", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/types", @@ -56,7 +56,7 @@ "yalc:publish": "yalc publish --push --sig" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "volta": { "extends": "../../package.json" diff --git a/packages/typescript/package.json b/packages/typescript/package.json index 9d11789736f3..4f169fab4be0 100644 --- a/packages/typescript/package.json +++ b/packages/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@sentry-internal/typescript", - "version": "8.45.0", + "version": "8.47.0", "description": "Typescript configuration used at Sentry", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/typescript", diff --git a/packages/utils/package.json b/packages/utils/package.json index b35f0087434b..e1216050ed25 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/utils", - "version": "8.45.0", + "version": "8.47.0", "description": "Utilities for all Sentry JavaScript SDKs", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/utils", @@ -39,7 +39,7 @@ "access": "public" }, "dependencies": { - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "scripts": { "build": "run-p build:transpile build:types", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 1d8d712e5b0f..8c67c23a1299 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -560,6 +560,7 @@ export const resolve = resolve_imported; export const getComponentName = getComponentName_imported; /** @deprecated Import from `@sentry/core` instead. */ +// eslint-disable-next-line deprecation/deprecation export const getDomElement = getDomElement_imported; /** @deprecated Import from `@sentry/core` instead. */ diff --git a/packages/vercel-edge/package.json b/packages/vercel-edge/package.json index 4e7f81e055af..f88cf6fa44da 100644 --- a/packages/vercel-edge/package.json +++ b/packages/vercel-edge/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/vercel-edge", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for the Vercel Edge Runtime", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/vercel-edge", @@ -40,7 +40,7 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.0", - "@sentry/core": "8.45.0" + "@sentry/core": "8.47.0" }, "devDependencies": { "@edge-runtime/types": "3.0.1", @@ -48,7 +48,7 @@ "@opentelemetry/resources": "^1.29.0", "@opentelemetry/sdk-trace-base": "^1.29.0", "@opentelemetry/semantic-conventions": "^1.28.0", - "@sentry/opentelemetry": "8.45.0" + "@sentry/opentelemetry": "8.47.0" }, "scripts": { "build": "run-p build:transpile build:types", diff --git a/packages/vercel-edge/src/sdk.ts b/packages/vercel-edge/src/sdk.ts index 78f1f49ba092..c29e9f693ba2 100644 --- a/packages/vercel-edge/src/sdk.ts +++ b/packages/vercel-edge/src/sdk.ts @@ -268,6 +268,8 @@ export function getSentryRelease(fallback?: string): string | undefined { process.env['HEROKU_TEST_RUN_COMMIT_VERSION'] || // Heroku #2 https://docs.sentry.io/product/integrations/deployment/heroku/#configure-releases process.env['HEROKU_SLUG_COMMIT'] || + // Railway - https://docs.railway.app/reference/variables#git-variables + process.env['RAILWAY_GIT_COMMIT_SHA'] || // Render - https://render.com/docs/environment-variables process.env['RENDER_GIT_COMMIT'] || // Semaphore CI - https://docs.semaphoreci.com/ci-cd-environment/environment-variables diff --git a/packages/vue/package.json b/packages/vue/package.json index 167352a6289b..a4f399729b45 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/vue", - "version": "8.45.0", + "version": "8.47.0", "description": "Official Sentry SDK for Vue.js", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/vue", @@ -39,8 +39,8 @@ "access": "public" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0" + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0" }, "peerDependencies": { "pinia": "2.x", diff --git a/packages/wasm/package.json b/packages/wasm/package.json index a45a87130c7c..e0fac4e61da9 100644 --- a/packages/wasm/package.json +++ b/packages/wasm/package.json @@ -1,6 +1,6 @@ { "name": "@sentry/wasm", - "version": "8.45.0", + "version": "8.47.0", "description": "Support for WASM.", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/wasm", @@ -39,8 +39,8 @@ "access": "public" }, "dependencies": { - "@sentry/browser": "8.45.0", - "@sentry/core": "8.45.0" + "@sentry/browser": "8.47.0", + "@sentry/core": "8.47.0" }, "scripts": { "build": "run-p build:transpile build:bundle build:types", diff --git a/yarn.lock b/yarn.lock index e2f483ec6322..9a549f168710 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7554,6 +7554,13 @@ dependencies: "@opentelemetry/api" "^1.0.0" +"@opentelemetry/api-logs@0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz#c478cbd8120ec2547b64edfa03a552cfe42170be" + integrity sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw== + dependencies: + "@opentelemetry/api" "^1.0.0" + "@opentelemetry/api-logs@0.56.0": version "0.56.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.56.0.tgz#68f8c51ca905c260b610c8a3c67d3f9fa3d59a45" @@ -7838,7 +7845,19 @@ semver "^7.5.2" shimmer "^1.2.1" -"@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0", "@opentelemetry/instrumentation@^0.52.1": +"@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz#e6369e4015eb5112468a4d45d38dcada7dad892d" + integrity sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A== + dependencies: + "@opentelemetry/api-logs" "0.53.0" + "@types/shimmer" "^1.2.0" + import-in-the-middle "^1.8.1" + require-in-the-middle "^7.1.1" + semver "^7.5.2" + shimmer "^1.2.1" + +"@opentelemetry/instrumentation@^0.52.1": version "0.52.1" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz#2e7e46a38bd7afbf03cf688c862b0b43418b7f48" integrity sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw== @@ -8046,13 +8065,13 @@ resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.9.1.tgz#d92bd2f7f006e0316cb4fda9d73f235965cf2c64" integrity sha512-caSOnG4kxcSkhqC/2ShV7rEoWwd3XrftokxJqOCMVvia4NYV/TPtJlS9C2os3Igxw/Qyxumj9GBQzcStzECvtQ== -"@prisma/instrumentation@5.19.1": - version "5.19.1" - resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.19.1.tgz#146319cf85f22b7a43296f0f40cfeac55516e66e" - integrity sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w== +"@prisma/instrumentation@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.22.0.tgz#c39941046e9886e17bdb47dbac45946c24d579aa" + integrity sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q== dependencies: "@opentelemetry/api" "^1.8" - "@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51 || ^0.52.0" + "@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0" "@opentelemetry/sdk-trace-base" "^1.22" "@protobuf-ts/plugin-framework@^2.0.7", "@protobuf-ts/plugin-framework@^2.9.4":