From 456690f40e8e87e3e2f5c83653041fa84e7302db Mon Sep 17 00:00:00 2001 From: Andrei <168741329+andreiborza@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:41:24 +0100 Subject: [PATCH 1/8] feat(nestjs): Remove `SentryService` (#14759) Closes: #13590 --- docs/migration/v8-to-v9.md | 6 +++ packages/nestjs/src/setup.ts | 72 +----------------------------------- 2 files changed, 7 insertions(+), 71 deletions(-) diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 783698c7ac76..59b42ca7161e 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -106,6 +106,12 @@ It will be removed in a future major version. - The `getNumberOfUrlSegments` method has been removed. There are no replacements. +### `@sentry/nestjs` + +- Removed `SentryService`. + If you are using `@sentry/nestjs` you can safely remove any references to the `SentryService`. + If you are using another package migrate to `@sentry/nestjs` and remove the `SentryService` afterwards. + ## 5. Build Changes Previously the CJS versions of the SDK code (wrongfully) contained compatibility statements for default exports in ESM: diff --git a/packages/nestjs/src/setup.ts b/packages/nestjs/src/setup.ts index e2fa65205b9a..a5d670402d68 100644 --- a/packages/nestjs/src/setup.ts +++ b/packages/nestjs/src/setup.ts @@ -5,21 +5,10 @@ import type { ExecutionContext, HttpServer, NestInterceptor, - OnModuleInit, } from '@nestjs/common'; import { Catch, Global, HttpException, Injectable, Logger, Module } from '@nestjs/common'; import { APP_INTERCEPTOR, BaseExceptionFilter } from '@nestjs/core'; -import type { Span } from '@sentry/core'; -import { - SEMANTIC_ATTRIBUTE_SENTRY_OP, - SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, - captureException, - getClient, - getDefaultIsolationScope, - getIsolationScope, - logger, - spanToJSON, -} from '@sentry/core'; +import { captureException, getDefaultIsolationScope, getIsolationScope, logger } from '@sentry/core'; import type { Observable } from 'rxjs'; import { isExpectedError } from './helpers'; @@ -177,40 +166,6 @@ export { SentryGlobalGraphQLFilter }; */ export const SentryGlobalGenericFilter = SentryGlobalFilter; -/** - * Service to set up Sentry performance tracing for Nest.js applications. - * - * @deprecated `SentryService` is deprecated. - * If you are using `@sentry/nestjs` you can safely remove any references to the `SentryService`. - * If you are using another package migrate to `@sentry/nestjs` and remove the `SentryService` afterwards. - */ -class SentryService implements OnModuleInit { - public readonly __SENTRY_INTERNAL__: boolean; - - public constructor() { - this.__SENTRY_INTERNAL__ = true; - } - - /** - * Initializes the Sentry service and registers span attributes. - */ - public onModuleInit(): void { - // Sadly, NestInstrumentation has no requestHook, so we need to add the attributes here - // We register this hook in this method, because if we register it in the integration `setup`, - // it would always run even for users that are not even using Nest.js - const client = getClient(); - if (client) { - client.on('spanStart', span => { - addNestSpanAttributes(span); - }); - } - } -} -// eslint-disable-next-line deprecation/deprecation -Injectable()(SentryService); -// eslint-disable-next-line deprecation/deprecation -export { SentryService }; - /** * Set up a root module that can be injected in nest applications. */ @@ -222,48 +177,23 @@ class SentryModule { return { module: SentryModule, providers: [ - // eslint-disable-next-line deprecation/deprecation - SentryService, { provide: APP_INTERCEPTOR, // eslint-disable-next-line deprecation/deprecation useClass: SentryTracingInterceptor, }, ], - // eslint-disable-next-line deprecation/deprecation - exports: [SentryService], }; } } Global()(SentryModule); Module({ providers: [ - // eslint-disable-next-line deprecation/deprecation - SentryService, { provide: APP_INTERCEPTOR, // eslint-disable-next-line deprecation/deprecation useClass: SentryTracingInterceptor, }, ], - // eslint-disable-next-line deprecation/deprecation - exports: [SentryService], })(SentryModule); export { SentryModule }; - -function addNestSpanAttributes(span: Span): void { - const attributes = spanToJSON(span).data; - - // this is one of: app_creation, request_context, handler - const type = attributes['nestjs.type']; - - // If this is already set, or we have no nest.js span, no need to process again... - if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || !type) { - return; - } - - span.setAttributes({ - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.nestjs', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.nestjs`, - }); -} From a921440f2065311d4f12f108329aaa2720ec7bc7 Mon Sep 17 00:00:00 2001 From: Andrei <168741329+andreiborza@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:48:21 +0100 Subject: [PATCH 2/8] feat(nestjs): Remove `SentryTracingInterceptor`, `SentryGlobalGraphQLFilter`, `SentryGlobalGenericFilter` (#14761) **Note**: we keep `SentryTracingInterceptor` to maintain parameterized transaction names but remove the public export. Closes: #14295 --- .../nestjs-basic-with-graphql/src/main.ts | 4 +- .../nestjs-graphql/src/app.module.ts | 4 +- docs/migration/v8-to-v9.md | 9 ++++ packages/nestjs/package.json | 2 +- packages/nestjs/src/setup.ts | 53 ------------------- 5 files changed, 14 insertions(+), 58 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/main.ts b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/main.ts index 947539414ddf..1456fd17b9e1 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/main.ts @@ -3,7 +3,7 @@ import './instrument'; // Import other modules import { HttpAdapterHost, NestFactory } from '@nestjs/core'; -import { SentryGlobalGenericFilter } from '@sentry/nestjs/setup'; +import { SentryGlobalFilter } from '@sentry/nestjs/setup'; import { AppModule } from './app.module'; const PORT = 3030; @@ -12,7 +12,7 @@ async function bootstrap() { const app = await NestFactory.create(AppModule); const { httpAdapter } = app.get(HttpAdapterHost); - app.useGlobalFilters(new SentryGlobalGenericFilter(httpAdapter as any)); + app.useGlobalFilters(new SentryGlobalFilter(httpAdapter as any)); await app.listen(PORT); } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/app.module.ts b/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/app.module.ts index 4cfc2ebd33e4..6eba5ad74cbe 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/app.module.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/app.module.ts @@ -2,7 +2,7 @@ import { ApolloDriver } from '@nestjs/apollo'; import { Logger, Module } from '@nestjs/common'; import { APP_FILTER } from '@nestjs/core'; import { GraphQLModule } from '@nestjs/graphql'; -import { SentryGlobalGraphQLFilter, SentryModule } from '@sentry/nestjs/setup'; +import { SentryGlobalFilter, SentryModule } from '@sentry/nestjs/setup'; import { AppResolver } from './app.resolver'; @Module({ @@ -19,7 +19,7 @@ import { AppResolver } from './app.resolver'; AppResolver, { provide: APP_FILTER, - useClass: SentryGlobalGraphQLFilter, + useClass: SentryGlobalFilter, }, { provide: Logger, diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 59b42ca7161e..ff1adc85dfd4 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -111,6 +111,15 @@ It will be removed in a future major version. - Removed `SentryService`. If you are using `@sentry/nestjs` you can safely remove any references to the `SentryService`. If you are using another package migrate to `@sentry/nestjs` and remove the `SentryService` afterwards. +- Removed `SentryTracingInterceptor`. + If you are using `@sentry/nestjs` you can safely remove any references to the `SentryTracingInterceptor`. + If you are using another package migrate to `@sentry/nestjs` and remove the `SentryTracingInterceptor` afterwards. +- Removed `SentryGlobalGenericFilter`. + Use the `SentryGlobalFilter` instead. + The `SentryGlobalFilter` is a drop-in replacement. +- Removed `SentryGlobalGraphQLFilter`. + Use the `SentryGlobalFilter` instead. + The `SentryGlobalFilter` is a drop-in replacement. ## 5. Build Changes diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index 56ab66b31cd5..a11de76a0c31 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -71,7 +71,7 @@ "build:types:watch": "tsc -p tsconfig.types.json --watch", "build:tarball": "npm pack", "circularDepCheck": "madge --circular src/index.ts && madge --circular src/setup.ts", - "clean": "rimraf build coverage sentry-node-*.tgz", + "clean": "rimraf build coverage sentry-nestjs-*.tgz ./*.d.ts ./*.d.ts.map", "fix": "eslint . --format stylish --fix", "lint": "eslint . --format stylish", "test": "vitest run", diff --git a/packages/nestjs/src/setup.ts b/packages/nestjs/src/setup.ts index a5d670402d68..d45d2d7d4900 100644 --- a/packages/nestjs/src/setup.ts +++ b/packages/nestjs/src/setup.ts @@ -35,10 +35,6 @@ interface ExpressRequest { /** * Interceptor to add Sentry tracing capabilities to Nest.js applications. - * - * @deprecated `SentryTracingInterceptor` is deprecated. - * If you are using `@sentry/nestjs` you can safely remove any references to the `SentryTracingInterceptor`. - * If you are using another package migrate to `@sentry/nestjs` and remove the `SentryTracingInterceptor` afterwards. */ class SentryTracingInterceptor implements NestInterceptor { // used to exclude this class from being auto-instrumented @@ -73,10 +69,7 @@ class SentryTracingInterceptor implements NestInterceptor { return next.handle(); } } -// eslint-disable-next-line deprecation/deprecation Injectable()(SentryTracingInterceptor); -// eslint-disable-next-line deprecation/deprecation -export { SentryTracingInterceptor }; /** * Global filter to handle exceptions and report them to Sentry. @@ -122,50 +115,6 @@ class SentryGlobalFilter extends BaseExceptionFilter { Catch()(SentryGlobalFilter); export { SentryGlobalFilter }; -/** - * Global filter to handle exceptions in NestJS + GraphQL applications and report them to Sentry. - * - * @deprecated `SentryGlobalGraphQLFilter` is deprecated. Use the `SentryGlobalFilter` instead. The `SentryGlobalFilter` is a drop-in replacement. - */ -class SentryGlobalGraphQLFilter { - private static readonly _logger = new Logger('ExceptionsHandler'); - public readonly __SENTRY_INTERNAL__: boolean; - - public constructor() { - this.__SENTRY_INTERNAL__ = true; - } - - /** - * Catches exceptions and reports them to Sentry unless they are HttpExceptions. - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - public catch(exception: unknown, host: ArgumentsHost): void { - // neither report nor log HttpExceptions - if (exception instanceof HttpException) { - throw exception; - } - if (exception instanceof Error) { - // eslint-disable-next-line deprecation/deprecation - SentryGlobalGraphQLFilter._logger.error(exception.message, exception.stack); - } - captureException(exception); - throw exception; - } -} -// eslint-disable-next-line deprecation/deprecation -Catch()(SentryGlobalGraphQLFilter); -// eslint-disable-next-line deprecation/deprecation -export { SentryGlobalGraphQLFilter }; - -/** - * Global filter to handle exceptions and report them to Sentry. - * - * This filter is a generic filter that can handle both HTTP and GraphQL exceptions. - * - * @deprecated `SentryGlobalGenericFilter` is deprecated. Use the `SentryGlobalFilter` instead. The `SentryGlobalFilter` is a drop-in replacement. - */ -export const SentryGlobalGenericFilter = SentryGlobalFilter; - /** * Set up a root module that can be injected in nest applications. */ @@ -179,7 +128,6 @@ class SentryModule { providers: [ { provide: APP_INTERCEPTOR, - // eslint-disable-next-line deprecation/deprecation useClass: SentryTracingInterceptor, }, ], @@ -191,7 +139,6 @@ Module({ providers: [ { provide: APP_INTERCEPTOR, - // eslint-disable-next-line deprecation/deprecation useClass: SentryTracingInterceptor, }, ], From d773cb7324480ed3cffc14504f0e41951e344d19 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 17 Dec 2024 13:19:48 -0500 Subject: [PATCH 3/8] feat!: Remove metrics API from the JS SDK (#14745) 1. Removes `metrics` export and all it's usages 2. Removes all usages of `_metrics_summary` from the SDK 3. Removes `metricsShim` usage in the browser SDK CDN bundles 4. Removes all metrics related types from the SDK --- .../suites/metrics/metricsEvent/init.js | 34 ---- .../suites/metrics/metricsEvent/test.ts | 34 ---- .../suites/metrics/metricsShim/init.js | 13 -- .../suites/metrics/metricsShim/test.ts | 36 ---- .../suites/metrics/timing/init.js | 39 ---- .../suites/metrics/timing/test.ts | 159 --------------- .../utils/helpers.ts | 12 -- .../suites/metrics/should-exit-forced.js | 19 -- .../suites/metrics/should-exit.js | 18 -- .../suites/metrics/test.ts | 21 -- .../tracing/metric-summaries/scenario.js | 50 ----- .../suites/tracing/metric-summaries/test.ts | 91 --------- .../rollup-utils/plugins/bundlePlugins.mjs | 2 - docs/migration/v8-to-v9.md | 4 + packages/astro/src/index.server.ts | 2 - packages/astro/src/index.types.ts | 3 - packages/aws-serverless/src/index.ts | 2 - packages/browser/src/index.bundle.feedback.ts | 3 +- packages/browser/src/index.bundle.replay.ts | 7 +- .../index.bundle.tracing.replay.feedback.ts | 2 - .../src/index.bundle.tracing.replay.ts | 2 - packages/browser/src/index.bundle.tracing.ts | 2 - packages/browser/src/index.bundle.ts | 2 - packages/browser/src/index.ts | 2 - packages/browser/src/metrics.ts | 76 ------- packages/bun/src/index.ts | 2 - packages/cloudflare/src/index.ts | 2 - packages/core/src/carrier.ts | 2 - packages/core/src/index.ts | 6 - packages/core/src/metrics/aggregator.ts | 174 ---------------- .../core/src/metrics/browser-aggregator.ts | 96 --------- packages/core/src/metrics/constants.ts | 21 -- packages/core/src/metrics/envelope.ts | 58 ------ packages/core/src/metrics/exports-default.ts | 97 --------- packages/core/src/metrics/exports.ts | 186 ------------------ packages/core/src/metrics/instance.ts | 128 ------------ packages/core/src/metrics/metric-summary.ts | 82 -------- packages/core/src/metrics/types.ts | 12 -- packages/core/src/metrics/utils.ts | 125 ------------ packages/core/src/tracing/sentrySpan.ts | 3 - packages/core/src/types-hoist/datacategory.ts | 2 - packages/core/src/types-hoist/envelope.ts | 6 - packages/core/src/types-hoist/event.ts | 3 +- packages/core/src/types-hoist/index.ts | 10 - packages/core/src/types-hoist/metrics.ts | 114 ----------- packages/core/src/types-hoist/span.ts | 10 - packages/core/src/utils-hoist/envelope.ts | 1 - packages/core/src/utils/spanUtils.ts | 22 --- .../core/test/lib/metrics/aggregator.test.ts | 138 ------------- .../lib/metrics/browser-aggregator.test.ts | 86 -------- packages/core/test/lib/metrics/timing.test.ts | 125 ------------ packages/core/test/lib/metrics/utils.test.ts | 43 ---- .../core/test/lib/tracing/sentrySpan.test.ts | 1 - packages/deno/src/index.ts | 2 - packages/google-cloud-serverless/src/index.ts | 2 - packages/integration-shims/src/index.ts | 1 - packages/integration-shims/src/metrics.ts | 22 --- packages/nextjs/src/index.types.ts | 3 - packages/node/src/index.ts | 2 - packages/nuxt/src/index.types.ts | 2 - packages/opentelemetry/src/spanExporter.ts | 3 - packages/remix/src/index.server.ts | 2 - packages/remix/src/index.types.ts | 3 - packages/solidstart/src/index.types.ts | 3 - packages/solidstart/src/server/index.ts | 2 - packages/sveltekit/src/index.types.ts | 3 - packages/sveltekit/src/server/index.ts | 2 - packages/types/src/index.ts | 24 --- packages/vercel-edge/src/index.ts | 2 - 69 files changed, 7 insertions(+), 2261 deletions(-) delete mode 100644 dev-packages/browser-integration-tests/suites/metrics/metricsEvent/init.js delete mode 100644 dev-packages/browser-integration-tests/suites/metrics/metricsEvent/test.ts delete mode 100644 dev-packages/browser-integration-tests/suites/metrics/metricsShim/init.js delete mode 100644 dev-packages/browser-integration-tests/suites/metrics/metricsShim/test.ts delete mode 100644 dev-packages/browser-integration-tests/suites/metrics/timing/init.js delete mode 100644 dev-packages/browser-integration-tests/suites/metrics/timing/test.ts delete mode 100644 dev-packages/node-integration-tests/suites/metrics/should-exit-forced.js delete mode 100644 dev-packages/node-integration-tests/suites/metrics/should-exit.js delete mode 100644 dev-packages/node-integration-tests/suites/metrics/test.ts delete mode 100644 dev-packages/node-integration-tests/suites/tracing/metric-summaries/scenario.js delete mode 100644 dev-packages/node-integration-tests/suites/tracing/metric-summaries/test.ts delete mode 100644 packages/browser/src/metrics.ts delete mode 100644 packages/core/src/metrics/aggregator.ts delete mode 100644 packages/core/src/metrics/browser-aggregator.ts delete mode 100644 packages/core/src/metrics/constants.ts delete mode 100644 packages/core/src/metrics/envelope.ts delete mode 100644 packages/core/src/metrics/exports-default.ts delete mode 100644 packages/core/src/metrics/exports.ts delete mode 100644 packages/core/src/metrics/instance.ts delete mode 100644 packages/core/src/metrics/metric-summary.ts delete mode 100644 packages/core/src/metrics/types.ts delete mode 100644 packages/core/src/metrics/utils.ts delete mode 100644 packages/core/src/types-hoist/metrics.ts delete mode 100644 packages/core/test/lib/metrics/aggregator.test.ts delete mode 100644 packages/core/test/lib/metrics/browser-aggregator.test.ts delete mode 100644 packages/core/test/lib/metrics/timing.test.ts delete mode 100644 packages/core/test/lib/metrics/utils.test.ts delete mode 100644 packages/integration-shims/src/metrics.ts diff --git a/dev-packages/browser-integration-tests/suites/metrics/metricsEvent/init.js b/dev-packages/browser-integration-tests/suites/metrics/metricsEvent/init.js deleted file mode 100644 index 878444f52a0a..000000000000 --- a/dev-packages/browser-integration-tests/suites/metrics/metricsEvent/init.js +++ /dev/null @@ -1,34 +0,0 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', -}); - -Sentry.metrics.increment('increment'); -Sentry.metrics.increment('increment', 2); -Sentry.metrics.increment('increment', '3'); -Sentry.metrics.distribution('distribution', 42); -Sentry.metrics.distribution('distribution', '45'); -Sentry.metrics.gauge('gauge', 5); -Sentry.metrics.gauge('gauge', '15'); -Sentry.metrics.set('set', 'nope'); -Sentry.metrics.set('set', 'another'); - -Sentry.metrics.timing('timing', 99, 'hour'); -Sentry.metrics.timing('timingSync', () => { - sleepSync(200); -}); -Sentry.metrics.timing('timingAsync', async () => { - await new Promise(resolve => setTimeout(resolve, 200)); -}); - -function sleepSync(milliseconds) { - var start = new Date().getTime(); - for (var i = 0; i < 1e7; i++) { - if (new Date().getTime() - start > milliseconds) { - break; - } - } -} diff --git a/dev-packages/browser-integration-tests/suites/metrics/metricsEvent/test.ts b/dev-packages/browser-integration-tests/suites/metrics/metricsEvent/test.ts deleted file mode 100644 index 38b0139edad3..000000000000 --- a/dev-packages/browser-integration-tests/suites/metrics/metricsEvent/test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { expect } from '@playwright/test'; - -import { sentryTest } from '../../../utils/fixtures'; -import { - getFirstSentryEnvelopeRequest, - properEnvelopeRequestParser, - shouldSkipMetricsTest, -} from '../../../utils/helpers'; - -sentryTest('collects metrics', async ({ getLocalTestUrl, page }) => { - if (shouldSkipMetricsTest()) { - sentryTest.skip(); - } - - const url = await getLocalTestUrl({ testDir: __dirname }); - - const statsdBuffer = await getFirstSentryEnvelopeRequest(page, url, properEnvelopeRequestParser); - const statsdString = new TextDecoder().decode(statsdBuffer); - // Replace all the Txxxxxx to remove the timestamps - const normalisedStatsdString = statsdString.replace(/T\d+\n?/g, 'T000000').trim(); - - const parts = normalisedStatsdString.split('T000000'); - - expect(parts).toEqual([ - 'increment@none:6|c|', - 'distribution@none:42:45|d|', - 'gauge@none:15:5:15:20:2|g|', - 'set@none:3387254:3443787523|s|', - 'timing@hour:99|d|', - expect.stringMatching(/timingSync@second:0.(\d+)\|d\|/), - expect.stringMatching(/timingAsync@second:0.(\d+)\|d\|/), - '', // trailing element - ]); -}); diff --git a/dev-packages/browser-integration-tests/suites/metrics/metricsShim/init.js b/dev-packages/browser-integration-tests/suites/metrics/metricsShim/init.js deleted file mode 100644 index 93c639cbdff9..000000000000 --- a/dev-packages/browser-integration-tests/suites/metrics/metricsShim/init.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', -}); - -// This should not fail -Sentry.metrics.increment('increment'); -Sentry.metrics.distribution('distribution', 42); -Sentry.metrics.gauge('gauge', 5); -Sentry.metrics.set('set', 'nope'); diff --git a/dev-packages/browser-integration-tests/suites/metrics/metricsShim/test.ts b/dev-packages/browser-integration-tests/suites/metrics/metricsShim/test.ts deleted file mode 100644 index e8d0dbcfb274..000000000000 --- a/dev-packages/browser-integration-tests/suites/metrics/metricsShim/test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { expect } from '@playwright/test'; - -import { sentryTest } from '../../../utils/fixtures'; -import { shouldSkipMetricsTest } from '../../../utils/helpers'; - -sentryTest('exports shim metrics integration for non-tracing bundles', async ({ getLocalTestUrl, page }) => { - // Skip in tracing tests - if (!shouldSkipMetricsTest()) { - sentryTest.skip(); - } - - const consoleMessages: string[] = []; - page.on('console', msg => consoleMessages.push(msg.text())); - - let requestCount = 0; - await page.route('https://dsn.ingest.sentry.io/**/*', route => { - requestCount++; - return route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify({ id: 'test-id' }), - }); - }); - - const url = await getLocalTestUrl({ testDir: __dirname, skipDsnRouteHandler: true }); - - await page.goto(url); - - expect(requestCount).toBe(0); - expect(consoleMessages).toEqual([ - 'You are using metrics even though this bundle does not include tracing.', - 'You are using metrics even though this bundle does not include tracing.', - 'You are using metrics even though this bundle does not include tracing.', - 'You are using metrics even though this bundle does not include tracing.', - ]); -}); diff --git a/dev-packages/browser-integration-tests/suites/metrics/timing/init.js b/dev-packages/browser-integration-tests/suites/metrics/timing/init.js deleted file mode 100644 index 87f087b04ecf..000000000000 --- a/dev-packages/browser-integration-tests/suites/metrics/timing/init.js +++ /dev/null @@ -1,39 +0,0 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - tracesSampleRate: 1.0, - release: '1.0.0', - autoSessionTracking: false, -}); - -window.timingSync = () => { - // Ensure we always have a wrapping span - return Sentry.startSpan({ name: 'manual span' }, () => { - return Sentry.metrics.timing('timingSync', () => { - sleepSync(200); - return 'sync done'; - }); - }); -}; - -window.timingAsync = () => { - // Ensure we always have a wrapping span - return Sentry.startSpan({ name: 'manual span' }, () => { - return Sentry.metrics.timing('timingAsync', async () => { - await new Promise(resolve => setTimeout(resolve, 200)); - return 'async done'; - }); - }); -}; - -function sleepSync(milliseconds) { - var start = new Date().getTime(); - for (var i = 0; i < 1e7; i++) { - if (new Date().getTime() - start > milliseconds) { - break; - } - } -} diff --git a/dev-packages/browser-integration-tests/suites/metrics/timing/test.ts b/dev-packages/browser-integration-tests/suites/metrics/timing/test.ts deleted file mode 100644 index 215f042dcdf7..000000000000 --- a/dev-packages/browser-integration-tests/suites/metrics/timing/test.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { expect } from '@playwright/test'; - -import { sentryTest } from '../../../utils/fixtures'; -import { - envelopeRequestParser, - properEnvelopeRequestParser, - shouldSkipTracingTest, - waitForTransactionRequest, -} from '../../../utils/helpers'; - -sentryTest('allows to wrap sync methods with a timing metric', async ({ getLocalTestUrl, page }) => { - if (shouldSkipTracingTest()) { - sentryTest.skip(); - } - - const url = await getLocalTestUrl({ testDir: __dirname }); - - const beforeTime = Math.floor(Date.now() / 1000); - - const metricsPromiseReq = page.waitForRequest(req => { - const postData = req.postData(); - if (!postData) { - return false; - } - - try { - // this implies this is a metrics envelope - return typeof envelopeRequestParser(req) === 'string'; - } catch { - return false; - } - }); - - const transactionPromise = waitForTransactionRequest(page); - - await page.goto(url); - await page.waitForFunction('typeof window.timingSync === "function"'); - const response = await page.evaluate('window.timingSync()'); - - expect(response).toBe('sync done'); - - const statsdString = envelopeRequestParser(await metricsPromiseReq); - const transactionEvent = properEnvelopeRequestParser(await transactionPromise); - - expect(typeof statsdString).toEqual('string'); - - const parsedStatsd = /timingSync@second:(0\.\d+)\|d\|#(.+)\|T(\d+)/.exec(statsdString); - - expect(parsedStatsd).toBeTruthy(); - - const duration = parseFloat(parsedStatsd![1]); - const tags = parsedStatsd![2]; - const timestamp = parseInt(parsedStatsd![3], 10); - - expect(timestamp).toBeGreaterThanOrEqual(beforeTime); - expect(tags).toEqual('release:1.0.0,transaction:manual span'); - expect(duration).toBeGreaterThan(0.2); - expect(duration).toBeLessThan(1); - - expect(transactionEvent).toBeDefined(); - expect(transactionEvent.transaction).toEqual('manual span'); - - const spans = transactionEvent.spans || []; - - expect(spans.length).toBe(1); - const span = spans[0]; - expect(span.op).toEqual('metrics.timing'); - expect(span.description).toEqual('timingSync'); - expect(span.timestamp! - span.start_timestamp).toEqual(duration); - expect(span._metrics_summary).toEqual({ - 'd:timingSync@second': [ - { - count: 1, - max: duration, - min: duration, - sum: duration, - tags: { - release: '1.0.0', - transaction: 'manual span', - }, - }, - ], - }); -}); - -sentryTest('allows to wrap async methods with a timing metric', async ({ getLocalTestUrl, page }) => { - if (shouldSkipTracingTest()) { - sentryTest.skip(); - } - - const url = await getLocalTestUrl({ testDir: __dirname }); - - const beforeTime = Math.floor(Date.now() / 1000); - - const metricsPromiseReq = page.waitForRequest(req => { - const postData = req.postData(); - if (!postData) { - return false; - } - - try { - // this implies this is a metrics envelope - return typeof envelopeRequestParser(req) === 'string'; - } catch { - return false; - } - }); - - const transactionPromise = waitForTransactionRequest(page); - - await page.goto(url); - await page.waitForFunction('typeof window.timingAsync === "function"'); - const response = await page.evaluate('window.timingAsync()'); - - expect(response).toBe('async done'); - - const statsdString = envelopeRequestParser(await metricsPromiseReq); - const transactionEvent = properEnvelopeRequestParser(await transactionPromise); - - expect(typeof statsdString).toEqual('string'); - - const parsedStatsd = /timingAsync@second:(0\.\d+)\|d\|#(.+)\|T(\d+)/.exec(statsdString); - - expect(parsedStatsd).toBeTruthy(); - - const duration = parseFloat(parsedStatsd![1]); - const tags = parsedStatsd![2]; - const timestamp = parseInt(parsedStatsd![3], 10); - - expect(timestamp).toBeGreaterThanOrEqual(beforeTime); - expect(tags).toEqual('release:1.0.0,transaction:manual span'); - expect(duration).toBeGreaterThan(0.2); - expect(duration).toBeLessThan(1); - - expect(transactionEvent).toBeDefined(); - expect(transactionEvent.transaction).toEqual('manual span'); - - const spans = transactionEvent.spans || []; - - expect(spans.length).toBe(1); - const span = spans[0]; - expect(span.op).toEqual('metrics.timing'); - expect(span.description).toEqual('timingAsync'); - expect(span.timestamp! - span.start_timestamp).toEqual(duration); - expect(span._metrics_summary).toEqual({ - 'd:timingAsync@second': [ - { - count: 1, - max: duration, - min: duration, - sum: duration, - tags: { - release: '1.0.0', - transaction: 'manual span', - }, - }, - ], - }); -}); diff --git a/dev-packages/browser-integration-tests/utils/helpers.ts b/dev-packages/browser-integration-tests/utils/helpers.ts index 03c654c22eb1..e02365302331 100644 --- a/dev-packages/browser-integration-tests/utils/helpers.ts +++ b/dev-packages/browser-integration-tests/utils/helpers.ts @@ -270,18 +270,6 @@ export function shouldSkipFeedbackTest(): boolean { return false; } -/** - * We can only test metrics tests in certain bundles/packages: - * - NPM (ESM, CJS) - * - CDN bundles that include tracing - * - * @returns `true` if we should skip the metrics test - */ -export function shouldSkipMetricsTest(): boolean { - const bundle = process.env.PW_BUNDLE as string | undefined; - return bundle != null && !bundle.includes('tracing') && !bundle.includes('esm') && !bundle.includes('cjs'); -} - /** * We only test feature flags integrations in certain bundles/packages: * - NPM (ESM, CJS) diff --git a/dev-packages/node-integration-tests/suites/metrics/should-exit-forced.js b/dev-packages/node-integration-tests/suites/metrics/should-exit-forced.js deleted file mode 100644 index 2621828973ab..000000000000 --- a/dev-packages/node-integration-tests/suites/metrics/should-exit-forced.js +++ /dev/null @@ -1,19 +0,0 @@ -const Sentry = require('@sentry/node'); - -function configureSentry() { - Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - release: '1.0', - autoSessionTracking: false, - }); - - Sentry.metrics.increment('test'); -} - -async function main() { - configureSentry(); - await new Promise(resolve => setTimeout(resolve, 1000)); - process.exit(0); -} - -main(); diff --git a/dev-packages/node-integration-tests/suites/metrics/should-exit.js b/dev-packages/node-integration-tests/suites/metrics/should-exit.js deleted file mode 100644 index 01a6f0194507..000000000000 --- a/dev-packages/node-integration-tests/suites/metrics/should-exit.js +++ /dev/null @@ -1,18 +0,0 @@ -const Sentry = require('@sentry/node'); - -function configureSentry() { - Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - release: '1.0', - autoSessionTracking: false, - }); - - Sentry.metrics.increment('test'); -} - -async function main() { - configureSentry(); - await new Promise(resolve => setTimeout(resolve, 1000)); -} - -main(); diff --git a/dev-packages/node-integration-tests/suites/metrics/test.ts b/dev-packages/node-integration-tests/suites/metrics/test.ts deleted file mode 100644 index 2c3cc350eeba..000000000000 --- a/dev-packages/node-integration-tests/suites/metrics/test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createRunner } from '../../utils/runner'; - -describe('metrics', () => { - test('should exit', done => { - const runner = createRunner(__dirname, 'should-exit.js').start(); - - setTimeout(() => { - expect(runner.childHasExited()).toBe(true); - done(); - }, 5_000); - }); - - test('should exit forced', done => { - const runner = createRunner(__dirname, 'should-exit-forced.js').start(); - - setTimeout(() => { - expect(runner.childHasExited()).toBe(true); - done(); - }, 5_000); - }); -}); diff --git a/dev-packages/node-integration-tests/suites/tracing/metric-summaries/scenario.js b/dev-packages/node-integration-tests/suites/tracing/metric-summaries/scenario.js deleted file mode 100644 index 422fa4c504a5..000000000000 --- a/dev-packages/node-integration-tests/suites/tracing/metric-summaries/scenario.js +++ /dev/null @@ -1,50 +0,0 @@ -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', - tracesSampleRate: 1.0, - transport: loggingTransport, -}); - -Sentry.startSpan( - { - name: 'Test Transaction', - op: 'transaction', - }, - () => { - Sentry.metrics.increment('root-counter', 1, { - tags: { - email: 'jon.doe@example.com', - }, - }); - Sentry.metrics.increment('root-counter', 1, { - tags: { - email: 'jane.doe@example.com', - }, - }); - - Sentry.startSpan( - { - name: 'Some other span', - op: 'transaction', - }, - () => { - Sentry.metrics.increment('root-counter'); - Sentry.metrics.increment('root-counter'); - Sentry.metrics.increment('root-counter', 2); - - Sentry.metrics.set('root-set', 'some-value'); - Sentry.metrics.set('root-set', 'another-value'); - Sentry.metrics.set('root-set', 'another-value'); - - Sentry.metrics.gauge('root-gauge', 42); - Sentry.metrics.gauge('root-gauge', 20); - - Sentry.metrics.distribution('root-distribution', 42); - Sentry.metrics.distribution('root-distribution', 20); - }, - ); - }, -); diff --git a/dev-packages/node-integration-tests/suites/tracing/metric-summaries/test.ts b/dev-packages/node-integration-tests/suites/tracing/metric-summaries/test.ts deleted file mode 100644 index 94f5fdc30c70..000000000000 --- a/dev-packages/node-integration-tests/suites/tracing/metric-summaries/test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { createRunner } from '../../../utils/runner'; - -const EXPECTED_TRANSACTION = { - transaction: 'Test Transaction', - _metrics_summary: { - 'c:root-counter@none': [ - { - min: 1, - max: 1, - count: 1, - sum: 1, - tags: { - release: '1.0', - transaction: 'Test Transaction', - email: 'jon.doe@example.com', - }, - }, - { - min: 1, - max: 1, - count: 1, - sum: 1, - tags: { - release: '1.0', - transaction: 'Test Transaction', - email: 'jane.doe@example.com', - }, - }, - ], - }, - spans: expect.arrayContaining([ - expect.objectContaining({ - description: 'Some other span', - op: 'transaction', - _metrics_summary: { - 'c:root-counter@none': [ - { - min: 1, - max: 2, - count: 3, - sum: 4, - tags: { - release: '1.0', - transaction: 'Test Transaction', - }, - }, - ], - 's:root-set@none': [ - { - min: 0, - max: 1, - count: 3, - sum: 2, - tags: { - release: '1.0', - transaction: 'Test Transaction', - }, - }, - ], - 'g:root-gauge@none': [ - { - min: 20, - max: 42, - count: 2, - sum: 62, - tags: { - release: '1.0', - transaction: 'Test Transaction', - }, - }, - ], - 'd:root-distribution@none': [ - { - min: 20, - max: 42, - count: 2, - sum: 62, - tags: { - release: '1.0', - transaction: 'Test Transaction', - }, - }, - ], - }, - }), - ]), -}; - -test('Should add metric summaries to spans', done => { - createRunner(__dirname, 'scenario.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done); -}); diff --git a/dev-packages/rollup-utils/plugins/bundlePlugins.mjs b/dev-packages/rollup-utils/plugins/bundlePlugins.mjs index dce0ca15bf35..9d6edd3157c0 100644 --- a/dev-packages/rollup-utils/plugins/bundlePlugins.mjs +++ b/dev-packages/rollup-utils/plugins/bundlePlugins.mjs @@ -126,8 +126,6 @@ export function makeTerserPlugin() { '_sentryId', // Keeps the frozen DSC on a Sentry Span '_frozenDsc', - // This keeps metrics summary on spans - '_metrics_summary', // These are used to keep span & scope relationships '_sentryRootSpan', '_sentryChildSpans', diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index ff1adc85dfd4..d6d49a0e72aa 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -175,6 +175,10 @@ The following outlines deprecations that were introduced in version 8 of the SDK To enable session tracking, it is recommended to unset `autoSessionTracking` and ensure that either, in browser environments the `browserSessionIntegration` is added, or in server environments the `httpIntegration` is added. To disable session tracking, it is recommended unset `autoSessionTracking` and to remove the `browserSessionIntegration` in browser environments, or in server environments configure the `httpIntegration` with the `trackIncomingRequestsAsSessions` option set to `false`. +- **The metrics API has been removed from the SDK.** + +The Sentry metrics beta has ended and the metrics API has been removed from the SDK. Learn more in [help center docs](https://sentry.zendesk.com/hc/en-us/articles/26369339769883-Metrics-Beta-Ended-on-October-7th). + ## `@sentry/utils` - **The `@sentry/utils` package has been deprecated. Import everything from `@sentry/core` instead.** diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index 3fe0c0001715..c5f3f74699d6 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -78,8 +78,6 @@ export { localVariablesIntegration, lruMemoizerIntegration, makeNodeTransport, - // eslint-disable-next-line deprecation/deprecation - metrics, modulesIntegration, mongoIntegration, mongooseIntegration, diff --git a/packages/astro/src/index.types.ts b/packages/astro/src/index.types.ts index ce87a51c3af7..01be44660cb9 100644 --- a/packages/astro/src/index.types.ts +++ b/packages/astro/src/index.types.ts @@ -10,7 +10,6 @@ import type { NodeOptions } from '@sentry/node'; import type { Client, Integration, Options, StackParser } from '@sentry/core'; import type * as clientSdk from './index.client'; -import type * as serverSdk from './index.server'; import sentryAstro from './index.server'; /** Initializes Sentry Astro SDK */ @@ -32,6 +31,4 @@ export declare const continueTrace: typeof clientSdk.continueTrace; export declare const Span: clientSdk.Span; -// eslint-disable-next-line deprecation/deprecation -export declare const metrics: typeof clientSdk.metrics & typeof serverSdk; export default sentryAstro; diff --git a/packages/aws-serverless/src/index.ts b/packages/aws-serverless/src/index.ts index d486ba9f68a7..c50d796415e9 100644 --- a/packages/aws-serverless/src/index.ts +++ b/packages/aws-serverless/src/index.ts @@ -76,8 +76,6 @@ export { continueTrace, getAutoPerformanceIntegrations, cron, - // eslint-disable-next-line deprecation/deprecation - metrics, parameterize, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, diff --git a/packages/browser/src/index.bundle.feedback.ts b/packages/browser/src/index.bundle.feedback.ts index c6f75c03d9d1..957583d79eeb 100644 --- a/packages/browser/src/index.bundle.feedback.ts +++ b/packages/browser/src/index.bundle.feedback.ts @@ -1,4 +1,4 @@ -import { browserTracingIntegrationShim, metricsShim, replayIntegrationShim } from '@sentry-internal/integration-shims'; +import { browserTracingIntegrationShim, replayIntegrationShim } from '@sentry-internal/integration-shims'; import { feedbackAsyncIntegration } from './feedbackAsync'; export * from './index.bundle.base'; @@ -10,7 +10,6 @@ export { feedbackAsyncIntegration as feedbackAsyncIntegration, feedbackAsyncIntegration as feedbackIntegration, replayIntegrationShim as replayIntegration, - metricsShim as metrics, }; export { captureFeedback } from '@sentry/core'; diff --git a/packages/browser/src/index.bundle.replay.ts b/packages/browser/src/index.bundle.replay.ts index 2c1c8f0de424..86dc0fba7d25 100644 --- a/packages/browser/src/index.bundle.replay.ts +++ b/packages/browser/src/index.bundle.replay.ts @@ -1,8 +1,4 @@ -import { - browserTracingIntegrationShim, - feedbackIntegrationShim, - metricsShim, -} from '@sentry-internal/integration-shims'; +import { browserTracingIntegrationShim, feedbackIntegrationShim } from '@sentry-internal/integration-shims'; export * from './index.bundle.base'; @@ -12,5 +8,4 @@ export { browserTracingIntegrationShim as browserTracingIntegration, feedbackIntegrationShim as feedbackAsyncIntegration, feedbackIntegrationShim as feedbackIntegration, - metricsShim as metrics, }; diff --git a/packages/browser/src/index.bundle.tracing.replay.feedback.ts b/packages/browser/src/index.bundle.tracing.replay.feedback.ts index 6d86f90e01cc..a16f07bafaf2 100644 --- a/packages/browser/src/index.bundle.tracing.replay.feedback.ts +++ b/packages/browser/src/index.bundle.tracing.replay.feedback.ts @@ -4,8 +4,6 @@ registerSpanErrorInstrumentation(); export * from './index.bundle.base'; -export * from './metrics'; - export { getActiveSpan, getRootSpan, diff --git a/packages/browser/src/index.bundle.tracing.replay.ts b/packages/browser/src/index.bundle.tracing.replay.ts index a0fa6660b227..37f0da34ae25 100644 --- a/packages/browser/src/index.bundle.tracing.replay.ts +++ b/packages/browser/src/index.bundle.tracing.replay.ts @@ -4,8 +4,6 @@ registerSpanErrorInstrumentation(); export * from './index.bundle.base'; -export * from './metrics'; - export { getActiveSpan, getRootSpan, diff --git a/packages/browser/src/index.bundle.tracing.ts b/packages/browser/src/index.bundle.tracing.ts index 8115e628aa89..d540ff0bd6f9 100644 --- a/packages/browser/src/index.bundle.tracing.ts +++ b/packages/browser/src/index.bundle.tracing.ts @@ -5,8 +5,6 @@ registerSpanErrorInstrumentation(); export * from './index.bundle.base'; -export * from './metrics'; - export { getActiveSpan, getRootSpan, diff --git a/packages/browser/src/index.bundle.ts b/packages/browser/src/index.bundle.ts index 38787264f9b0..5004b376cd46 100644 --- a/packages/browser/src/index.bundle.ts +++ b/packages/browser/src/index.bundle.ts @@ -1,7 +1,6 @@ import { browserTracingIntegrationShim, feedbackIntegrationShim, - metricsShim, replayIntegrationShim, } from '@sentry-internal/integration-shims'; @@ -12,5 +11,4 @@ export { feedbackIntegrationShim as feedbackAsyncIntegration, feedbackIntegrationShim as feedbackIntegration, replayIntegrationShim as replayIntegration, - metricsShim as metrics, }; diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 94e090692a4e..56c7dd449602 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -31,8 +31,6 @@ import { feedbackSyncIntegration } from './feedbackSync'; export { feedbackAsyncIntegration, feedbackSyncIntegration, feedbackSyncIntegration as feedbackIntegration }; export { getFeedback, sendFeedback } from '@sentry-internal/feedback'; -export * from './metrics'; - export { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './tracing/request'; export { browserTracingIntegration, diff --git a/packages/browser/src/metrics.ts b/packages/browser/src/metrics.ts deleted file mode 100644 index 96f56988c485..000000000000 --- a/packages/browser/src/metrics.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { BrowserMetricsAggregator, metrics as metricsCore } from '@sentry/core'; -import type { DurationUnit, MetricData, Metrics } from '@sentry/core'; - -/** - * Adds a value to a counter metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function increment(name: string, value: number = 1, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.increment(BrowserMetricsAggregator, name, value, data); -} - -/** - * Adds a value to a distribution metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function distribution(name: string, value: number, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.distribution(BrowserMetricsAggregator, name, value, data); -} - -/** - * Adds a value to a set metric. Value must be a string or integer. - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function set(name: string, value: number | string, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.set(BrowserMetricsAggregator, name, value, data); -} - -/** - * Adds a value to a gauge metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function gauge(name: string, value: number, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.gauge(BrowserMetricsAggregator, name, value, data); -} - -/** - * Adds a timing metric. - * The metric is added as a distribution metric. - * - * You can either directly capture a numeric `value`, or wrap a callback function in `timing`. - * In the latter case, the duration of the callback execution will be captured as a span & a metric. - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function timing(name: string, value: number, unit?: DurationUnit, data?: Omit): void; -function timing(name: string, callback: () => T, unit?: DurationUnit, data?: Omit): T; -function timing( - name: string, - value: number | (() => T), - unit: DurationUnit = 'second', - data?: Omit, -): T | void { - // eslint-disable-next-line deprecation/deprecation - return metricsCore.timing(BrowserMetricsAggregator, name, value, unit, data); -} - -/** - * The metrics API is used to capture custom metrics in Sentry. - * - * @deprecated The Sentry metrics beta has ended. This export will be removed in a future release. - */ -export const metrics: Metrics = { - increment, - distribution, - set, - gauge, - timing, -}; diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 94c40505ff41..6b172c998d64 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -99,8 +99,6 @@ export { continueTrace, getAutoPerformanceIntegrations, cron, - // eslint-disable-next-line deprecation/deprecation - metrics, parameterize, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, diff --git a/packages/cloudflare/src/index.ts b/packages/cloudflare/src/index.ts index 38f0565e61c3..8dd5ba50a623 100644 --- a/packages/cloudflare/src/index.ts +++ b/packages/cloudflare/src/index.ts @@ -67,8 +67,6 @@ export { withActiveSpan, getSpanDescendants, continueTrace, - // eslint-disable-next-line deprecation/deprecation - metrics, functionToStringIntegration, inboundFiltersIntegration, linkedErrorsIntegration, diff --git a/packages/core/src/carrier.ts b/packages/core/src/carrier.ts index e8bffa63b660..5136121cb8ae 100644 --- a/packages/core/src/carrier.ts +++ b/packages/core/src/carrier.ts @@ -1,7 +1,6 @@ import type { AsyncContextStack } from './asyncContext/stackStrategy'; import type { AsyncContextStrategy } from './asyncContext/types'; import type { Scope } from './scope'; -import type { Client, MetricsAggregator } from './types-hoist'; import type { Logger } from './utils-hoist/logger'; import { SDK_VERSION } from './utils-hoist/version'; import { GLOBAL_OBJ } from './utils-hoist/worldwide'; @@ -25,7 +24,6 @@ export interface SentryCarrier { globalScope?: Scope; defaultIsolationScope?: Scope; defaultCurrentScope?: Scope; - globalMetricsAggregators?: WeakMap | undefined; logger?: Logger; /** Overwrites TextEncoder used in `@sentry/core`, need for `react-native@0.73` and older */ diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index d7c4785cc3e2..98cb1bda04e9 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -101,13 +101,7 @@ export { extraErrorDataIntegration } from './integrations/extraerrordata'; export { rewriteFramesIntegration } from './integrations/rewriteframes'; export { zodErrorsIntegration } from './integrations/zoderrors'; export { thirdPartyErrorFilterIntegration } from './integrations/third-party-errors-filter'; -// eslint-disable-next-line deprecation/deprecation -export { metrics } from './metrics/exports'; export { profiler } from './profiling'; -// eslint-disable-next-line deprecation/deprecation -export { metricsDefault } from './metrics/exports-default'; -export { BrowserMetricsAggregator } from './metrics/browser-aggregator'; -export { getMetricSummaryJsonForSpan } from './metrics/metric-summary'; export { // eslint-disable-next-line deprecation/deprecation addTracingHeadersToFetchRequest, diff --git a/packages/core/src/metrics/aggregator.ts b/packages/core/src/metrics/aggregator.ts deleted file mode 100644 index 972c6b3336ad..000000000000 --- a/packages/core/src/metrics/aggregator.ts +++ /dev/null @@ -1,174 +0,0 @@ -import type { Client, MeasurementUnit, MetricsAggregator as MetricsAggregatorBase, Primitive } from '../types-hoist'; -import { timestampInSeconds } from '../utils-hoist/time'; -import { updateMetricSummaryOnActiveSpan } from '../utils/spanUtils'; -import { DEFAULT_FLUSH_INTERVAL, MAX_WEIGHT, SET_METRIC_TYPE } from './constants'; -import { captureAggregateMetrics } from './envelope'; -import { METRIC_MAP } from './instance'; -import type { MetricBucket, MetricType } from './types'; -import { getBucketKey, sanitizeMetricKey, sanitizeTags, sanitizeUnit } from './utils'; - -/** - * A metrics aggregator that aggregates metrics in memory and flushes them periodically. - */ -export class MetricsAggregator implements MetricsAggregatorBase { - // TODO(@anonrig): Use FinalizationRegistry to have a proper way of flushing the buckets - // when the aggregator is garbage collected. - // Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry - private _buckets: MetricBucket; - - // Different metrics have different weights. We use this to limit the number of metrics - // that we store in memory. - private _bucketsTotalWeight; - - // We adjust the type here to add the `unref()` part, as setInterval can technically return a number or a NodeJS.Timer - private readonly _interval: ReturnType & { unref?: () => void }; - - // SDKs are required to shift the flush interval by random() * rollup_in_seconds. - // That shift is determined once per startup to create jittering. - private readonly _flushShift: number; - - // An SDK is required to perform force flushing ahead of scheduled time if the memory - // pressure is too high. There is no rule for this other than that SDKs should be tracking - // abstract aggregation complexity (eg: a counter only carries a single float, whereas a - // distribution is a float per emission). - // - // Force flush is used on either shutdown, flush() or when we exceed the max weight. - private _forceFlush: boolean; - - public constructor(private readonly _client: Client) { - this._buckets = new Map(); - this._bucketsTotalWeight = 0; - - this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL); - if (this._interval.unref) { - this._interval.unref(); - } - - this._flushShift = Math.floor((Math.random() * DEFAULT_FLUSH_INTERVAL) / 1000); - this._forceFlush = false; - } - - /** - * @inheritDoc - */ - public add( - metricType: MetricType, - unsanitizedName: string, - value: number | string, - unsanitizedUnit: MeasurementUnit = 'none', - unsanitizedTags: Record = {}, - maybeFloatTimestamp = timestampInSeconds(), - ): void { - const timestamp = Math.floor(maybeFloatTimestamp); - const name = sanitizeMetricKey(unsanitizedName); - const tags = sanitizeTags(unsanitizedTags); - const unit = sanitizeUnit(unsanitizedUnit as string); - - const bucketKey = getBucketKey(metricType, name, unit, tags); - - let bucketItem = this._buckets.get(bucketKey); - // If this is a set metric, we need to calculate the delta from the previous weight. - const previousWeight = bucketItem && metricType === SET_METRIC_TYPE ? bucketItem.metric.weight : 0; - - if (bucketItem) { - bucketItem.metric.add(value); - // TODO(abhi): Do we need this check? - if (bucketItem.timestamp < timestamp) { - bucketItem.timestamp = timestamp; - } - } else { - bucketItem = { - // @ts-expect-error we don't need to narrow down the type of value here, saves bundle size. - metric: new METRIC_MAP[metricType](value), - timestamp, - metricType, - name, - unit, - tags, - }; - this._buckets.set(bucketKey, bucketItem); - } - - // If value is a string, it's a set metric so calculate the delta from the previous weight. - const val = typeof value === 'string' ? bucketItem.metric.weight - previousWeight : value; - updateMetricSummaryOnActiveSpan(metricType, name, val, unit, unsanitizedTags, bucketKey); - - // We need to keep track of the total weight of the buckets so that we can - // flush them when we exceed the max weight. - this._bucketsTotalWeight += bucketItem.metric.weight; - - if (this._bucketsTotalWeight >= MAX_WEIGHT) { - this.flush(); - } - } - - /** - * Flushes the current metrics to the transport via the transport. - */ - public flush(): void { - this._forceFlush = true; - this._flush(); - } - - /** - * Shuts down metrics aggregator and clears all metrics. - */ - public close(): void { - this._forceFlush = true; - clearInterval(this._interval); - this._flush(); - } - - /** - * Flushes the buckets according to the internal state of the aggregator. - * If it is a force flush, which happens on shutdown, it will flush all buckets. - * Otherwise, it will only flush buckets that are older than the flush interval, - * and according to the flush shift. - * - * This function mutates `_forceFlush` and `_bucketsTotalWeight` properties. - */ - private _flush(): void { - // TODO(@anonrig): Add Atomics for locking to avoid having force flush and regular flush - // running at the same time. - // Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics - - // This path eliminates the need for checking for timestamps since we're forcing a flush. - // Remember to reset the flag, or it will always flush all metrics. - if (this._forceFlush) { - this._forceFlush = false; - this._bucketsTotalWeight = 0; - this._captureMetrics(this._buckets); - this._buckets.clear(); - return; - } - const cutoffSeconds = Math.floor(timestampInSeconds()) - DEFAULT_FLUSH_INTERVAL / 1000 - this._flushShift; - // TODO(@anonrig): Optimization opportunity. - // Convert this map to an array and store key in the bucketItem. - const flushedBuckets: MetricBucket = new Map(); - for (const [key, bucket] of this._buckets) { - if (bucket.timestamp <= cutoffSeconds) { - flushedBuckets.set(key, bucket); - this._bucketsTotalWeight -= bucket.metric.weight; - } - } - - for (const [key] of flushedBuckets) { - this._buckets.delete(key); - } - - this._captureMetrics(flushedBuckets); - } - - /** - * Only captures a subset of the buckets passed to this function. - * @param flushedBuckets - */ - private _captureMetrics(flushedBuckets: MetricBucket): void { - if (flushedBuckets.size > 0) { - // TODO(@anonrig): Optimization opportunity. - // This copy operation can be avoided if we store the key in the bucketItem. - const buckets = Array.from(flushedBuckets).map(([, bucketItem]) => bucketItem); - captureAggregateMetrics(this._client, buckets); - } - } -} diff --git a/packages/core/src/metrics/browser-aggregator.ts b/packages/core/src/metrics/browser-aggregator.ts deleted file mode 100644 index fca72f48f40f..000000000000 --- a/packages/core/src/metrics/browser-aggregator.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { Client, MeasurementUnit, MetricsAggregator, Primitive } from '../types-hoist'; -import { timestampInSeconds } from '../utils-hoist/time'; -import { updateMetricSummaryOnActiveSpan } from '../utils/spanUtils'; -import { DEFAULT_BROWSER_FLUSH_INTERVAL, SET_METRIC_TYPE } from './constants'; -import { captureAggregateMetrics } from './envelope'; -import { METRIC_MAP } from './instance'; -import type { MetricBucket, MetricType } from './types'; -import { getBucketKey, sanitizeMetricKey, sanitizeTags, sanitizeUnit } from './utils'; - -/** - * A simple metrics aggregator that aggregates metrics in memory and flushes them periodically. - * Default flush interval is 5 seconds. - * - * @experimental This API is experimental and might change in the future. - */ -export class BrowserMetricsAggregator implements MetricsAggregator { - // TODO(@anonrig): Use FinalizationRegistry to have a proper way of flushing the buckets - // when the aggregator is garbage collected. - // Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry - private _buckets: MetricBucket; - private readonly _interval: ReturnType; - - public constructor(private readonly _client: Client) { - this._buckets = new Map(); - this._interval = setInterval(() => this.flush(), DEFAULT_BROWSER_FLUSH_INTERVAL); - } - - /** - * @inheritDoc - */ - public add( - metricType: MetricType, - unsanitizedName: string, - value: number | string, - unsanitizedUnit: MeasurementUnit | undefined = 'none', - unsanitizedTags: Record | undefined = {}, - maybeFloatTimestamp: number | undefined = timestampInSeconds(), - ): void { - const timestamp = Math.floor(maybeFloatTimestamp); - const name = sanitizeMetricKey(unsanitizedName); - const tags = sanitizeTags(unsanitizedTags); - const unit = sanitizeUnit(unsanitizedUnit as string); - - const bucketKey = getBucketKey(metricType, name, unit, tags); - - let bucketItem = this._buckets.get(bucketKey); - // If this is a set metric, we need to calculate the delta from the previous weight. - const previousWeight = bucketItem && metricType === SET_METRIC_TYPE ? bucketItem.metric.weight : 0; - - if (bucketItem) { - bucketItem.metric.add(value); - // TODO(abhi): Do we need this check? - if (bucketItem.timestamp < timestamp) { - bucketItem.timestamp = timestamp; - } - } else { - bucketItem = { - // @ts-expect-error we don't need to narrow down the type of value here, saves bundle size. - metric: new METRIC_MAP[metricType](value), - timestamp, - metricType, - name, - unit, - tags, - }; - this._buckets.set(bucketKey, bucketItem); - } - - // If value is a string, it's a set metric so calculate the delta from the previous weight. - const val = typeof value === 'string' ? bucketItem.metric.weight - previousWeight : value; - updateMetricSummaryOnActiveSpan(metricType, name, val, unit, unsanitizedTags, bucketKey); - } - - /** - * @inheritDoc - */ - public flush(): void { - // short circuit if buckets are empty. - if (this._buckets.size === 0) { - return; - } - - const metricBuckets = Array.from(this._buckets.values()); - captureAggregateMetrics(this._client, metricBuckets); - - this._buckets.clear(); - } - - /** - * @inheritDoc - */ - public close(): void { - clearInterval(this._interval); - this.flush(); - } -} diff --git a/packages/core/src/metrics/constants.ts b/packages/core/src/metrics/constants.ts deleted file mode 100644 index ae1cd968723c..000000000000 --- a/packages/core/src/metrics/constants.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const COUNTER_METRIC_TYPE = 'c' as const; -export const GAUGE_METRIC_TYPE = 'g' as const; -export const SET_METRIC_TYPE = 's' as const; -export const DISTRIBUTION_METRIC_TYPE = 'd' as const; - -/** - * This does not match spec in https://develop.sentry.dev/sdk/metrics - * but was chosen to optimize for the most common case in browser environments. - */ -export const DEFAULT_BROWSER_FLUSH_INTERVAL = 5000; - -/** - * SDKs are required to bucket into 10 second intervals (rollup in seconds) - * which is the current lower bound of metric accuracy. - */ -export const DEFAULT_FLUSH_INTERVAL = 10000; - -/** - * The maximum number of metrics that should be stored in memory. - */ -export const MAX_WEIGHT = 10000; diff --git a/packages/core/src/metrics/envelope.ts b/packages/core/src/metrics/envelope.ts deleted file mode 100644 index 7c1a4d612577..000000000000 --- a/packages/core/src/metrics/envelope.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { Client, DsnComponents, MetricBucketItem, SdkMetadata, StatsdEnvelope, StatsdItem } from '../types-hoist'; -import { dsnToString } from '../utils-hoist/dsn'; -import { createEnvelope } from '../utils-hoist/envelope'; -import { logger } from '../utils-hoist/logger'; -import { serializeMetricBuckets } from './utils'; - -/** - * Captures aggregated metrics to the supplied client. - */ -export function captureAggregateMetrics(client: Client, metricBucketItems: Array): void { - logger.log(`Flushing aggregated metrics, number of metrics: ${metricBucketItems.length}`); - const dsn = client.getDsn(); - const metadata = client.getSdkMetadata(); - const tunnel = client.getOptions().tunnel; - - const metricsEnvelope = createMetricEnvelope(metricBucketItems, dsn, metadata, tunnel); - - // sendEnvelope should not throw - // eslint-disable-next-line @typescript-eslint/no-floating-promises - client.sendEnvelope(metricsEnvelope); -} - -/** - * Create envelope from a metric aggregate. - */ -export function createMetricEnvelope( - metricBucketItems: Array, - dsn?: DsnComponents, - metadata?: SdkMetadata, - tunnel?: string, -): StatsdEnvelope { - const headers: StatsdEnvelope[0] = { - sent_at: new Date().toISOString(), - }; - - if (metadata && metadata.sdk) { - headers.sdk = { - name: metadata.sdk.name, - version: metadata.sdk.version, - }; - } - - if (!!tunnel && dsn) { - headers.dsn = dsnToString(dsn); - } - - const item = createMetricEnvelopeItem(metricBucketItems); - return createEnvelope(headers, [item]); -} - -function createMetricEnvelopeItem(metricBucketItems: MetricBucketItem[]): StatsdItem { - const payload = serializeMetricBuckets(metricBucketItems); - const metricHeaders: StatsdItem[0] = { - type: 'statsd', - length: payload.length, - }; - return [metricHeaders, payload]; -} diff --git a/packages/core/src/metrics/exports-default.ts b/packages/core/src/metrics/exports-default.ts deleted file mode 100644 index e071015b73f1..000000000000 --- a/packages/core/src/metrics/exports-default.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { - Client, - DurationUnit, - MetricData, - Metrics, - MetricsAggregator as MetricsAggregatorInterface, -} from '../types-hoist'; -import { MetricsAggregator } from './aggregator'; -import { metrics as metricsCore } from './exports'; - -/** - * Adds a value to a counter metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function increment(name: string, value: number = 1, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.increment(MetricsAggregator, name, value, data); -} - -/** - * Adds a value to a distribution metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function distribution(name: string, value: number, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.distribution(MetricsAggregator, name, value, data); -} - -/** - * Adds a value to a set metric. Value must be a string or integer. - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function set(name: string, value: number | string, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.set(MetricsAggregator, name, value, data); -} - -/** - * Adds a value to a gauge metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function gauge(name: string, value: number, data?: MetricData): void { - // eslint-disable-next-line deprecation/deprecation - metricsCore.gauge(MetricsAggregator, name, value, data); -} - -/** - * Adds a timing metric. - * The metric is added as a distribution metric. - * - * You can either directly capture a numeric `value`, or wrap a callback function in `timing`. - * In the latter case, the duration of the callback execution will be captured as a span & a metric. - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function timing(name: string, value: number, unit?: DurationUnit, data?: Omit): void; -function timing(name: string, callback: () => T, unit?: DurationUnit, data?: Omit): T; -function timing( - name: string, - value: number | (() => T), - unit: DurationUnit = 'second', - data?: Omit, -): T | void { - // eslint-disable-next-line deprecation/deprecation - return metricsCore.timing(MetricsAggregator, name, value, unit, data); -} - -/** - * Returns the metrics aggregator for a given client. - */ -function getMetricsAggregatorForClient(client: Client): MetricsAggregatorInterface { - // eslint-disable-next-line deprecation/deprecation - return metricsCore.getMetricsAggregatorForClient(client, MetricsAggregator); -} - -/** - * The metrics API is used to capture custom metrics in Sentry. - * - * @deprecated The Sentry metrics beta has ended. This export will be removed in a future release. - */ -export const metricsDefault: Metrics & { - getMetricsAggregatorForClient: typeof getMetricsAggregatorForClient; -} = { - increment, - distribution, - set, - gauge, - timing, - /** - * @ignore This is for internal use only. - */ - getMetricsAggregatorForClient, -}; diff --git a/packages/core/src/metrics/exports.ts b/packages/core/src/metrics/exports.ts deleted file mode 100644 index 03d2ef90efe8..000000000000 --- a/packages/core/src/metrics/exports.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { getGlobalSingleton } from '../carrier'; -import { getClient } from '../currentScopes'; -import { DEBUG_BUILD } from '../debug-build'; -import { startSpanManual } from '../tracing'; -import type { Client, DurationUnit, MetricData, MetricsAggregator as MetricsAggregatorInterface } from '../types-hoist'; -import { logger } from '../utils-hoist/logger'; -import { timestampInSeconds } from '../utils-hoist/time'; -import { handleCallbackErrors } from '../utils/handleCallbackErrors'; -import { getActiveSpan, getRootSpan, spanToJSON } from '../utils/spanUtils'; -import { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, GAUGE_METRIC_TYPE, SET_METRIC_TYPE } from './constants'; -import type { MetricType } from './types'; - -type MetricsAggregatorConstructor = { - new (client: Client): MetricsAggregatorInterface; -}; - -/** - * Gets the metrics aggregator for a given client. - * @param client The client for which to get the metrics aggregator. - * @param Aggregator Optional metrics aggregator class to use to create an aggregator if one does not exist. - */ -function getMetricsAggregatorForClient( - client: Client, - Aggregator: MetricsAggregatorConstructor, -): MetricsAggregatorInterface { - const globalMetricsAggregators = getGlobalSingleton( - 'globalMetricsAggregators', - () => new WeakMap(), - ); - - const aggregator = globalMetricsAggregators.get(client); - if (aggregator) { - return aggregator; - } - - const newAggregator = new Aggregator(client); - client.on('flush', () => newAggregator.flush()); - client.on('close', () => newAggregator.close()); - globalMetricsAggregators.set(client, newAggregator); - - return newAggregator; -} - -function addToMetricsAggregator( - Aggregator: MetricsAggregatorConstructor, - metricType: MetricType, - name: string, - value: number | string, - data: MetricData | undefined = {}, -): void { - const client = data.client || getClient(); - - if (!client) { - return; - } - - const span = getActiveSpan(); - const rootSpan = span ? getRootSpan(span) : undefined; - const transactionName = rootSpan && spanToJSON(rootSpan).description; - - const { unit, tags, timestamp } = data; - const { release, environment } = client.getOptions(); - const metricTags: Record = {}; - if (release) { - metricTags.release = release; - } - if (environment) { - metricTags.environment = environment; - } - if (transactionName) { - metricTags.transaction = transactionName; - } - - DEBUG_BUILD && logger.log(`Adding value of ${value} to ${metricType} metric ${name}`); - - const aggregator = getMetricsAggregatorForClient(client, Aggregator); - aggregator.add(metricType, name, value, unit, { ...metricTags, ...tags }, timestamp); -} - -/** - * Adds a value to a counter metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function increment(aggregator: MetricsAggregatorConstructor, name: string, value: number = 1, data?: MetricData): void { - addToMetricsAggregator(aggregator, COUNTER_METRIC_TYPE, name, ensureNumber(value), data); -} - -/** - * Adds a value to a distribution metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function distribution(aggregator: MetricsAggregatorConstructor, name: string, value: number, data?: MetricData): void { - addToMetricsAggregator(aggregator, DISTRIBUTION_METRIC_TYPE, name, ensureNumber(value), data); -} - -/** - * Adds a timing metric. - * The metric is added as a distribution metric. - * - * You can either directly capture a numeric `value`, or wrap a callback function in `timing`. - * In the latter case, the duration of the callback execution will be captured as a span & a metric. - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function timing( - aggregator: MetricsAggregatorConstructor, - name: string, - value: number | (() => T), - unit: DurationUnit = 'second', - data?: Omit, -): T | void { - // callback form - if (typeof value === 'function') { - const startTime = timestampInSeconds(); - - return startSpanManual( - { - op: 'metrics.timing', - name, - startTime, - onlyIfParent: true, - }, - span => { - return handleCallbackErrors( - () => value(), - () => { - // no special error handling necessary - }, - () => { - const endTime = timestampInSeconds(); - const timeDiff = endTime - startTime; - // eslint-disable-next-line deprecation/deprecation - distribution(aggregator, name, timeDiff, { ...data, unit: 'second' }); - span.end(endTime); - }, - ); - }, - ); - } - - // value form - // eslint-disable-next-line deprecation/deprecation - distribution(aggregator, name, value, { ...data, unit }); -} - -/** - * Adds a value to a set metric. Value must be a string or integer. - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function set(aggregator: MetricsAggregatorConstructor, name: string, value: number | string, data?: MetricData): void { - addToMetricsAggregator(aggregator, SET_METRIC_TYPE, name, value, data); -} - -/** - * Adds a value to a gauge metric - * - * @deprecated The Sentry metrics beta has ended. This method will be removed in a future release. - */ -function gauge(aggregator: MetricsAggregatorConstructor, name: string, value: number, data?: MetricData): void { - addToMetricsAggregator(aggregator, GAUGE_METRIC_TYPE, name, ensureNumber(value), data); -} - -/** - * The metrics API is used to capture custom metrics in Sentry. - * - * @deprecated The Sentry metrics beta has ended. This export will be removed in a future release. - */ -export const metrics = { - increment, - distribution, - set, - gauge, - timing, - /** - * @ignore This is for internal use only. - */ - getMetricsAggregatorForClient, -}; - -// Although this is typed to be a number, we try to handle strings as well here -function ensureNumber(number: number | string): number { - return typeof number === 'string' ? parseInt(number) : number; -} diff --git a/packages/core/src/metrics/instance.ts b/packages/core/src/metrics/instance.ts deleted file mode 100644 index 28b57ae7f75c..000000000000 --- a/packages/core/src/metrics/instance.ts +++ /dev/null @@ -1,128 +0,0 @@ -import type { MetricInstance } from '../types-hoist'; -import { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, GAUGE_METRIC_TYPE, SET_METRIC_TYPE } from './constants'; -import { simpleHash } from './utils'; - -/** - * A metric instance representing a counter. - */ -export class CounterMetric implements MetricInstance { - public constructor(private _value: number) {} - - /** @inheritDoc */ - public get weight(): number { - return 1; - } - - /** @inheritdoc */ - public add(value: number): void { - this._value += value; - } - - /** @inheritdoc */ - public toString(): string { - return `${this._value}`; - } -} - -/** - * A metric instance representing a gauge. - */ -export class GaugeMetric implements MetricInstance { - private _last: number; - private _min: number; - private _max: number; - private _sum: number; - private _count: number; - - public constructor(value: number) { - this._last = value; - this._min = value; - this._max = value; - this._sum = value; - this._count = 1; - } - - /** @inheritDoc */ - public get weight(): number { - return 5; - } - - /** @inheritdoc */ - public add(value: number): void { - this._last = value; - if (value < this._min) { - this._min = value; - } - if (value > this._max) { - this._max = value; - } - this._sum += value; - this._count++; - } - - /** @inheritdoc */ - public toString(): string { - return `${this._last}:${this._min}:${this._max}:${this._sum}:${this._count}`; - } -} - -/** - * A metric instance representing a distribution. - */ -export class DistributionMetric implements MetricInstance { - private _value: number[]; - - public constructor(first: number) { - this._value = [first]; - } - - /** @inheritDoc */ - public get weight(): number { - return this._value.length; - } - - /** @inheritdoc */ - public add(value: number): void { - this._value.push(value); - } - - /** @inheritdoc */ - public toString(): string { - return this._value.join(':'); - } -} - -/** - * A metric instance representing a set. - */ -export class SetMetric implements MetricInstance { - private _value: Set; - - public constructor(public first: number | string) { - this._value = new Set([first]); - } - - /** @inheritDoc */ - public get weight(): number { - return this._value.size; - } - - /** @inheritdoc */ - public add(value: number | string): void { - this._value.add(value); - } - - /** @inheritdoc */ - public toString(): string { - return Array.from(this._value) - .map(val => (typeof val === 'string' ? simpleHash(val) : val)) - .join(':'); - } -} - -export const METRIC_MAP = { - [COUNTER_METRIC_TYPE]: CounterMetric, - [GAUGE_METRIC_TYPE]: GaugeMetric, - [DISTRIBUTION_METRIC_TYPE]: DistributionMetric, - [SET_METRIC_TYPE]: SetMetric, -}; diff --git a/packages/core/src/metrics/metric-summary.ts b/packages/core/src/metrics/metric-summary.ts deleted file mode 100644 index e7a8a00c289a..000000000000 --- a/packages/core/src/metrics/metric-summary.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { MeasurementUnit, Span } from '../types-hoist'; -import type { MetricSummary } from '../types-hoist'; -import type { Primitive } from '../types-hoist'; -import { dropUndefinedKeys } from '../utils-hoist/object'; -import type { MetricType } from './types'; - -/** - * key: bucketKey - * value: [exportKey, MetricSummary] - */ -type MetricSummaryStorage = Map; - -const METRICS_SPAN_FIELD = '_sentryMetrics'; - -type SpanWithPotentialMetrics = Span & { - [METRICS_SPAN_FIELD]?: MetricSummaryStorage; -}; - -/** - * Fetches the metric summary if it exists for the passed span - */ -export function getMetricSummaryJsonForSpan(span: Span): Record> | undefined { - const storage = (span as SpanWithPotentialMetrics)[METRICS_SPAN_FIELD]; - - if (!storage) { - return undefined; - } - const output: Record> = {}; - - for (const [, [exportKey, summary]] of storage) { - const arr = output[exportKey] || (output[exportKey] = []); - arr.push(dropUndefinedKeys(summary)); - } - - return output; -} - -/** - * Updates the metric summary on a span. - */ -export function updateMetricSummaryOnSpan( - span: Span, - metricType: MetricType, - sanitizedName: string, - value: number, - unit: MeasurementUnit, - tags: Record, - bucketKey: string, -): void { - const existingStorage = (span as SpanWithPotentialMetrics)[METRICS_SPAN_FIELD]; - const storage = - existingStorage || - ((span as SpanWithPotentialMetrics)[METRICS_SPAN_FIELD] = new Map()); - - const exportKey = `${metricType}:${sanitizedName}@${unit}`; - const bucketItem = storage.get(bucketKey); - - if (bucketItem) { - const [, summary] = bucketItem; - storage.set(bucketKey, [ - exportKey, - { - min: Math.min(summary.min, value), - max: Math.max(summary.max, value), - count: (summary.count += 1), - sum: (summary.sum += value), - tags: summary.tags, - }, - ]); - } else { - storage.set(bucketKey, [ - exportKey, - { - min: value, - max: value, - count: 1, - sum: value, - tags, - }, - ]); - } -} diff --git a/packages/core/src/metrics/types.ts b/packages/core/src/metrics/types.ts deleted file mode 100644 index d1d01cd1abab..000000000000 --- a/packages/core/src/metrics/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { MetricBucketItem } from '../types-hoist'; -import type { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, GAUGE_METRIC_TYPE, SET_METRIC_TYPE } from './constants'; - -export type MetricType = - | typeof COUNTER_METRIC_TYPE - | typeof GAUGE_METRIC_TYPE - | typeof SET_METRIC_TYPE - | typeof DISTRIBUTION_METRIC_TYPE; - -// TODO(@anonrig): Convert this to WeakMap when we support ES6 and -// use FinalizationRegistry to flush the buckets when the aggregator is garbage collected. -export type MetricBucket = Map; diff --git a/packages/core/src/metrics/utils.ts b/packages/core/src/metrics/utils.ts deleted file mode 100644 index 903a185e27f3..000000000000 --- a/packages/core/src/metrics/utils.ts +++ /dev/null @@ -1,125 +0,0 @@ -import type { MeasurementUnit, MetricBucketItem, Primitive } from '../types-hoist'; -import { dropUndefinedKeys } from '../utils-hoist/object'; -import type { MetricType } from './types'; - -/** - * Generate bucket key from metric properties. - */ -export function getBucketKey( - metricType: MetricType, - name: string, - unit: MeasurementUnit, - tags: Record, -): string { - const stringifiedTags = Object.entries(dropUndefinedKeys(tags)).sort((a, b) => a[0].localeCompare(b[0])); - return `${metricType}${name}${unit}${stringifiedTags}`; -} - -/* eslint-disable no-bitwise */ -/** - * Simple hash function for strings. - */ -export function simpleHash(s: string): number { - let rv = 0; - for (let i = 0; i < s.length; i++) { - const c = s.charCodeAt(i); - rv = (rv << 5) - rv + c; - rv &= rv; - } - return rv >>> 0; -} -/* eslint-enable no-bitwise */ - -/** - * Serialize metrics buckets into a string based on statsd format. - * - * Example of format: - * metric.name@second:1:1.2|d|#a:value,b:anothervalue|T12345677 - * Segments: - * name: metric.name - * unit: second - * value: [1, 1.2] - * type of metric: d (distribution) - * tags: { a: value, b: anothervalue } - * timestamp: 12345677 - */ -export function serializeMetricBuckets(metricBucketItems: MetricBucketItem[]): string { - let out = ''; - for (const item of metricBucketItems) { - const tagEntries = Object.entries(item.tags); - const maybeTags = tagEntries.length > 0 ? `|#${tagEntries.map(([key, value]) => `${key}:${value}`).join(',')}` : ''; - out += `${item.name}@${item.unit}:${item.metric}|${item.metricType}${maybeTags}|T${item.timestamp}\n`; - } - return out; -} - -/** - * Sanitizes units - * - * These Regex's are straight from the normalisation docs: - * https://develop.sentry.dev/sdk/metrics/#normalization - */ -export function sanitizeUnit(unit: string): string { - return unit.replace(/[^\w]+/gi, '_'); -} - -/** - * Sanitizes metric keys - * - * These Regex's are straight from the normalisation docs: - * https://develop.sentry.dev/sdk/metrics/#normalization - */ -export function sanitizeMetricKey(key: string): string { - return key.replace(/[^\w\-.]+/gi, '_'); -} - -/** - * Sanitizes metric keys - * - * These Regex's are straight from the normalisation docs: - * https://develop.sentry.dev/sdk/metrics/#normalization - */ -function sanitizeTagKey(key: string): string { - return key.replace(/[^\w\-./]+/gi, ''); -} - -/** - * These Regex's are straight from the normalisation docs: - * https://develop.sentry.dev/sdk/metrics/#normalization - */ -const tagValueReplacements: [string, string][] = [ - ['\n', '\\n'], - ['\r', '\\r'], - ['\t', '\\t'], - ['\\', '\\\\'], - ['|', '\\u{7c}'], - [',', '\\u{2c}'], -]; - -function getCharOrReplacement(input: string): string { - for (const [search, replacement] of tagValueReplacements) { - if (input === search) { - return replacement; - } - } - - return input; -} - -function sanitizeTagValue(value: string): string { - return [...value].reduce((acc, char) => acc + getCharOrReplacement(char), ''); -} - -/** - * Sanitizes tags. - */ -export function sanitizeTags(unsanitizedTags: Record): Record { - const tags: Record = {}; - for (const key in unsanitizedTags) { - if (Object.prototype.hasOwnProperty.call(unsanitizedTags, key)) { - const sanitizedKey = sanitizeTagKey(key); - tags[sanitizedKey] = sanitizeTagValue(String(unsanitizedTags[key])); - } - } - return tags; -} diff --git a/packages/core/src/tracing/sentrySpan.ts b/packages/core/src/tracing/sentrySpan.ts index 9965261970f2..309f46ff874c 100644 --- a/packages/core/src/tracing/sentrySpan.ts +++ b/packages/core/src/tracing/sentrySpan.ts @@ -1,7 +1,6 @@ import { getClient, getCurrentScope } from '../currentScopes'; import { DEBUG_BUILD } from '../debug-build'; import { createSpanEnvelope } from '../envelope'; -import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary'; import { SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_PROFILE_ID, @@ -233,7 +232,6 @@ export class SentrySpan implements Span { timestamp: this._endTime, trace_id: this._traceId, origin: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] as SpanOrigin | undefined, - _metrics_summary: getMetricSummaryJsonForSpan(this), profile_id: this._attributes[SEMANTIC_ATTRIBUTE_PROFILE_ID] as string | undefined, exclusive_time: this._attributes[SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME] as number | undefined, measurements: timedEventsToMeasurements(this._events), @@ -385,7 +383,6 @@ export class SentrySpan implements Span { dynamicSamplingContext: getDynamicSamplingContextFromSpan(this), }), }, - _metrics_summary: getMetricSummaryJsonForSpan(this), ...(source && { transaction_info: { source, diff --git a/packages/core/src/types-hoist/datacategory.ts b/packages/core/src/types-hoist/datacategory.ts index bd1c0b693e4d..da90cc0ca90b 100644 --- a/packages/core/src/types-hoist/datacategory.ts +++ b/packages/core/src/types-hoist/datacategory.ts @@ -26,8 +26,6 @@ export type DataCategory = | 'monitor' // Feedback type event (v2) | 'feedback' - // Metrics sent via the statsd or metrics envelope items - | 'metric_bucket' // Span | 'span' // Unknown data category diff --git a/packages/core/src/types-hoist/envelope.ts b/packages/core/src/types-hoist/envelope.ts index b5e2599942d4..ab7af66f3a01 100644 --- a/packages/core/src/types-hoist/envelope.ts +++ b/packages/core/src/types-hoist/envelope.ts @@ -41,7 +41,6 @@ export type EnvelopeItemType = | 'replay_event' | 'replay_recording' | 'check_in' - | 'statsd' | 'span' | 'raw_security'; @@ -84,7 +83,6 @@ type ReplayRecordingItemHeaders = { type: 'replay_recording'; length: number }; type CheckInItemHeaders = { type: 'check_in' }; type ProfileItemHeaders = { type: 'profile' }; type ProfileChunkItemHeaders = { type: 'profile_chunk' }; -type StatsdItemHeaders = { type: 'statsd'; length: number }; type SpanItemHeaders = { type: 'span' }; type RawSecurityHeaders = { type: 'raw_security'; sentry_release?: string; sentry_environment?: string }; @@ -98,7 +96,6 @@ export type ClientReportItem = BaseEnvelopeItem; type ReplayEventItem = BaseEnvelopeItem; type ReplayRecordingItem = BaseEnvelopeItem; -export type StatsdItem = BaseEnvelopeItem; export type FeedbackItem = BaseEnvelopeItem; export type ProfileItem = BaseEnvelopeItem; export type ProfileChunkItem = BaseEnvelopeItem; @@ -110,7 +107,6 @@ type SessionEnvelopeHeaders = { sent_at: string }; type CheckInEnvelopeHeaders = { trace?: DynamicSamplingContext }; type ClientReportEnvelopeHeaders = BaseEnvelopeHeaders; type ReplayEnvelopeHeaders = BaseEnvelopeHeaders; -type StatsdEnvelopeHeaders = BaseEnvelopeHeaders; type SpanEnvelopeHeaders = BaseEnvelopeHeaders & { trace?: DynamicSamplingContext }; export type EventEnvelope = BaseEnvelope< @@ -121,7 +117,6 @@ export type SessionEnvelope = BaseEnvelope; export type ClientReportEnvelope = BaseEnvelope; export type ReplayEnvelope = [ReplayEnvelopeHeaders, [ReplayEventItem, ReplayRecordingItem]]; export type CheckInEnvelope = BaseEnvelope; -export type StatsdEnvelope = BaseEnvelope; export type SpanEnvelope = BaseEnvelope; export type ProfileChunkEnvelope = BaseEnvelope; export type RawSecurityEnvelope = BaseEnvelope; @@ -133,7 +128,6 @@ export type Envelope = | ProfileChunkEnvelope | ReplayEnvelope | CheckInEnvelope - | StatsdEnvelope | SpanEnvelope | RawSecurityEnvelope; diff --git a/packages/core/src/types-hoist/event.ts b/packages/core/src/types-hoist/event.ts index ff7069d2fdc8..69d6776a54ac 100644 --- a/packages/core/src/types-hoist/event.ts +++ b/packages/core/src/types-hoist/event.ts @@ -13,7 +13,7 @@ import type { PolymorphicRequest } from './polymorphics'; import type { RequestEventData } from './request'; import type { SdkInfo } from './sdkinfo'; import type { SeverityLevel } from './severity'; -import type { MetricSummary, SpanJSON } from './span'; +import type { SpanJSON } from './span'; import type { Thread } from './thread'; import type { TransactionSource } from './transaction'; import type { User } from './user'; @@ -82,7 +82,6 @@ export interface ErrorEvent extends Event { } export interface TransactionEvent extends Event { type: 'transaction'; - _metrics_summary?: Record>; } /** JSDoc */ diff --git a/packages/core/src/types-hoist/index.ts b/packages/core/src/types-hoist/index.ts index f9fbf080153a..82cae72af76d 100644 --- a/packages/core/src/types-hoist/index.ts +++ b/packages/core/src/types-hoist/index.ts @@ -45,8 +45,6 @@ export type { CheckInEnvelope, RawSecurityEnvelope, RawSecurityItem, - StatsdItem, - StatsdEnvelope, ProfileItem, ProfileChunkEnvelope, ProfileChunkItem, @@ -125,7 +123,6 @@ export type { SpanJSON, SpanContextData, TraceFlag, - MetricSummary, } from './span'; export type { SpanStatus } from './spanStatus'; export type { TimedEvent } from './timedEvent'; @@ -173,13 +170,6 @@ export type { export type { BrowserClientReplayOptions, BrowserClientProfilingOptions } from './browseroptions'; export type { CheckIn, MonitorConfig, FinishedCheckIn, InProgressCheckIn, SerializedCheckIn } from './checkin'; -export type { - MetricsAggregator, - MetricBucketItem, - MetricInstance, - MetricData, - Metrics, -} from './metrics'; export type { ParameterizedString } from './parameterize'; export type { ContinuousProfiler, ProfilingIntegration, Profiler } from './profiling'; export type { ViewHierarchyData, ViewHierarchyWindow } from './view-hierarchy'; diff --git a/packages/core/src/types-hoist/metrics.ts b/packages/core/src/types-hoist/metrics.ts deleted file mode 100644 index 474f5b94c207..000000000000 --- a/packages/core/src/types-hoist/metrics.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { Client } from './client'; -import type { DurationUnit, MeasurementUnit } from './measurement'; -import type { Primitive } from './misc'; - -export interface MetricData { - unit?: MeasurementUnit; - tags?: Record; - timestamp?: number; - client?: Client; -} - -/** - * An abstract definition of the minimum required API - * for a metric instance. - */ -export interface MetricInstance { - /** - * Returns the weight of the metric. - */ - weight: number; - - /** - * Adds a value to a metric. - */ - add(value: number | string): void; - - /** - * Serializes the metric into a statsd format string. - */ - toString(): string; -} - -export interface MetricBucketItem { - metric: MetricInstance; - timestamp: number; - metricType: 'c' | 'g' | 's' | 'd'; - name: string; - unit: MeasurementUnit; - tags: Record; -} - -/** - * A metrics aggregator that aggregates metrics in memory and flushes them periodically. - */ -export interface MetricsAggregator { - /** - * Add a metric to the aggregator. - */ - add( - metricType: 'c' | 'g' | 's' | 'd', - name: string, - value: number | string, - unit?: MeasurementUnit, - tags?: Record, - timestamp?: number, - ): void; - - /** - * Flushes the current metrics to the transport via the transport. - */ - flush(): void; - - /** - * Shuts down metrics aggregator and clears all metrics. - */ - close(): void; - - /** - * Returns a string representation of the aggregator. - */ - toString(): string; -} - -export interface Metrics { - /** - * Adds a value to a counter metric - * - * @experimental This API is experimental and might have breaking changes in the future. - */ - increment(name: string, value?: number, data?: MetricData): void; - - /** - * Adds a value to a distribution metric - * - * @experimental This API is experimental and might have breaking changes in the future. - */ - distribution(name: string, value: number, data?: MetricData): void; - - /** - * Adds a value to a set metric. Value must be a string or integer. - * - * @experimental This API is experimental and might have breaking changes in the future. - */ - set(name: string, value: number | string, data?: MetricData): void; - - /** - * Adds a value to a gauge metric - * - * @experimental This API is experimental and might have breaking changes in the future. - */ - gauge(name: string, value: number, data?: MetricData): void; - - /** - * Adds a timing metric. - * The metric is added as a distribution metric. - * - * You can either directly capture a numeric `value`, or wrap a callback function in `timing`. - * In the latter case, the duration of the callback execution will be captured as a span & a metric. - * - * @experimental This API is experimental and might have breaking changes in the future. - */ - timing(name: string, value: number, unit?: DurationUnit, data?: Omit): void; - timing(name: string, callback: () => T, unit?: DurationUnit, data?: Omit): T; -} diff --git a/packages/core/src/types-hoist/span.ts b/packages/core/src/types-hoist/span.ts index 8e87a115a8b5..c74d00e54f97 100644 --- a/packages/core/src/types-hoist/span.ts +++ b/packages/core/src/types-hoist/span.ts @@ -1,5 +1,4 @@ import type { Measurements } from './measurement'; -import type { Primitive } from './misc'; import type { HrTime } from './opentelemetry'; import type { SpanStatus } from './spanStatus'; import type { TransactionSource } from './transaction'; @@ -31,14 +30,6 @@ export type SpanAttributes = Partial<{ }> & Record; -export type MetricSummary = { - min: number; - max: number; - count: number; - sum: number; - tags?: Record | undefined; -}; - /** This type is aligned with the OpenTelemetry TimeInput type. */ export type SpanTimeInput = HrTime | number | Date; @@ -54,7 +45,6 @@ export interface SpanJSON { timestamp?: number; trace_id: string; origin?: SpanOrigin; - _metrics_summary?: Record>; profile_id?: string; exclusive_time?: number; measurements?: Measurements; diff --git a/packages/core/src/utils-hoist/envelope.ts b/packages/core/src/utils-hoist/envelope.ts index 52fb7e175070..ea2b733f1dc1 100644 --- a/packages/core/src/utils-hoist/envelope.ts +++ b/packages/core/src/utils-hoist/envelope.ts @@ -222,7 +222,6 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP: Record = { check_in: 'monitor', feedback: 'feedback', span: 'span', - statsd: 'metric_bucket', raw_security: 'security', }; diff --git a/packages/core/src/utils/spanUtils.ts b/packages/core/src/utils/spanUtils.ts index ecfae662b052..c4088fba4942 100644 --- a/packages/core/src/utils/spanUtils.ts +++ b/packages/core/src/utils/spanUtils.ts @@ -1,8 +1,6 @@ import { getAsyncContextStrategy } from '../asyncContext'; 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_CUSTOM_SPAN_NAME, SEMANTIC_ATTRIBUTE_SENTRY_OP, @@ -12,8 +10,6 @@ import { import type { SentrySpan } from '../tracing/sentrySpan'; import { SPAN_STATUS_OK, SPAN_STATUS_UNSET } from '../tracing/spanstatus'; import type { - MeasurementUnit, - Primitive, Span, SpanAttributes, SpanJSON, @@ -140,7 +136,6 @@ export function spanToJSON(span: Span): SpanJSON { status: getStatusMessage(status), op: attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP], origin: attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] as SpanOrigin | undefined, - _metrics_summary: getMetricSummaryJsonForSpan(span), }); } @@ -281,23 +276,6 @@ export function getActiveSpan(): Span | undefined { return _getSpanForScope(getCurrentScope()); } -/** - * Updates the metric summary on the currently active span - */ -export function updateMetricSummaryOnActiveSpan( - metricType: MetricType, - sanitizedName: string, - value: number, - unit: MeasurementUnit, - tags: Record, - bucketKey: string, -): void { - const span = getActiveSpan(); - if (span) { - updateMetricSummaryOnSpan(span, metricType, sanitizedName, value, unit, tags, bucketKey); - } -} - /** * Logs a warning once if `beforeSendSpan` is used to drop spans. * diff --git a/packages/core/test/lib/metrics/aggregator.test.ts b/packages/core/test/lib/metrics/aggregator.test.ts deleted file mode 100644 index 2a471d12bb04..000000000000 --- a/packages/core/test/lib/metrics/aggregator.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { MetricsAggregator } from '../../../src/metrics/aggregator'; -import { MAX_WEIGHT } from '../../../src/metrics/constants'; -import { CounterMetric } from '../../../src/metrics/instance'; -import { serializeMetricBuckets } from '../../../src/metrics/utils'; -import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; - -let testClient: TestClient; - -describe('MetricsAggregator', () => { - const options = getDefaultTestClientOptions({ tracesSampleRate: 0.0 }); - - beforeEach(() => { - jest.useFakeTimers('legacy'); - testClient = new TestClient(options); - }); - - it('adds items to buckets', () => { - const aggregator = new MetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - expect(aggregator['_buckets'].size).toEqual(1); - - const firstValue = aggregator['_buckets'].values().next().value; - expect(firstValue).toEqual({ - metric: expect.any(CounterMetric), - metricType: 'c', - name: 'requests', - tags: {}, - timestamp: expect.any(Number), - unit: 'none', - }); - }); - - it('groups same items together', () => { - const aggregator = new MetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - expect(aggregator['_buckets'].size).toEqual(1); - aggregator.add('c', 'requests', 1); - expect(aggregator['_buckets'].size).toEqual(1); - - const firstValue = aggregator['_buckets'].values().next().value; - expect(firstValue).toEqual({ - metric: expect.any(CounterMetric), - metricType: 'c', - name: 'requests', - tags: {}, - timestamp: expect.any(Number), - unit: 'none', - }); - expect(firstValue.metric._value).toEqual(2); - }); - - it('differentiates based on tag value', () => { - const aggregator = new MetricsAggregator(testClient); - aggregator.add('g', 'cpu', 50); - expect(aggregator['_buckets'].size).toEqual(1); - aggregator.add('g', 'cpu', 55, undefined, { a: 'value' }); - expect(aggregator['_buckets'].size).toEqual(2); - }); - - describe('serializeBuckets', () => { - it('serializes ', () => { - const aggregator = new MetricsAggregator(testClient); - aggregator.add('c', 'requests', 8); - aggregator.add('g', 'cpu', 50); - aggregator.add('g', 'cpu', 55); - aggregator.add('g', 'cpu', 52); - aggregator.add('d', 'lcp', 1, 'second', { a: 'value', b: 'anothervalue' }); - aggregator.add('d', 'lcp', 1.2, 'second', { a: 'value', b: 'anothervalue' }); - aggregator.add('s', 'important_people', 'a', 'none', { numericKey: 2 }); - aggregator.add('s', 'important_people', 'b', 'none', { numericKey: 2 }); - - const metricBuckets = Array.from(aggregator['_buckets']).map(([, bucketItem]) => bucketItem); - const serializedBuckets = serializeMetricBuckets(metricBuckets); - - expect(serializedBuckets).toContain('requests@none:8|c|T'); - expect(serializedBuckets).toContain('cpu@none:52:50:55:157:3|g|T'); - expect(serializedBuckets).toContain('lcp@second:1:1.2|d|#a:value,b:anothervalue|T'); - expect(serializedBuckets).toContain('important_people@none:97:98|s|#numericKey:2|T'); - }); - }); - - describe('close', () => { - test('should flush immediately', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); - const aggregator = new MetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - aggregator.close(); - // It should clear the interval. - expect(clearInterval).toHaveBeenCalled(); - expect(capture).toBeCalled(); - expect(capture).toBeCalledTimes(1); - }); - }); - - describe('flush', () => { - test('should flush immediately', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); - const aggregator = new MetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - aggregator.flush(); - expect(capture).toBeCalled(); - expect(capture).toBeCalledTimes(1); - - capture.mockReset(); - aggregator.close(); - // It should clear the interval. - expect(clearInterval).toHaveBeenCalled(); - - // It shouldn't be called since it's been already flushed. - expect(capture).toBeCalledTimes(0); - }); - - test('should not capture if empty', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); - const aggregator = new MetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - aggregator.flush(); - expect(capture).toBeCalledTimes(1); - capture.mockReset(); - aggregator.close(); - expect(capture).toBeCalledTimes(0); - }); - }); - - describe('add', () => { - test('it should respect the max weight and flush if exceeded', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); - const aggregator = new MetricsAggregator(testClient); - - for (let i = 0; i < MAX_WEIGHT; i++) { - aggregator.add('c', 'requests', 1); - } - - expect(capture).toBeCalledTimes(1); - aggregator.close(); - }); - }); -}); diff --git a/packages/core/test/lib/metrics/browser-aggregator.test.ts b/packages/core/test/lib/metrics/browser-aggregator.test.ts deleted file mode 100644 index e5ed6b3f8296..000000000000 --- a/packages/core/test/lib/metrics/browser-aggregator.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { BrowserMetricsAggregator } from '../../../src/metrics/browser-aggregator'; -import { CounterMetric } from '../../../src/metrics/instance'; -import { serializeMetricBuckets } from '../../../src/metrics/utils'; -import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; - -function _cleanupAggregator(aggregator: BrowserMetricsAggregator): void { - clearInterval(aggregator['_interval']); -} - -describe('BrowserMetricsAggregator', () => { - const options = getDefaultTestClientOptions({ tracesSampleRate: 0.0 }); - const testClient = new TestClient(options); - - it('adds items to buckets', () => { - const aggregator = new BrowserMetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - expect(aggregator['_buckets'].size).toEqual(1); - - const firstValue = aggregator['_buckets'].values().next().value; - expect(firstValue).toEqual({ - metric: expect.any(CounterMetric), - metricType: 'c', - name: 'requests', - tags: {}, - timestamp: expect.any(Number), - unit: 'none', - }); - - _cleanupAggregator(aggregator); - }); - - it('groups same items together', () => { - const aggregator = new BrowserMetricsAggregator(testClient); - aggregator.add('c', 'requests', 1); - expect(aggregator['_buckets'].size).toEqual(1); - aggregator.add('c', 'requests', 1); - expect(aggregator['_buckets'].size).toEqual(1); - - const firstValue = aggregator['_buckets'].values().next().value; - expect(firstValue).toEqual({ - metric: expect.any(CounterMetric), - metricType: 'c', - name: 'requests', - tags: {}, - timestamp: expect.any(Number), - unit: 'none', - }); - expect(firstValue.metric._value).toEqual(2); - - _cleanupAggregator(aggregator); - }); - - it('differentiates based on tag value', () => { - const aggregator = new BrowserMetricsAggregator(testClient); - aggregator.add('g', 'cpu', 50); - expect(aggregator['_buckets'].size).toEqual(1); - aggregator.add('g', 'cpu', 55, undefined, { a: 'value' }); - expect(aggregator['_buckets'].size).toEqual(2); - - _cleanupAggregator(aggregator); - }); - - describe('serializeBuckets', () => { - it('serializes ', () => { - const aggregator = new BrowserMetricsAggregator(testClient); - aggregator.add('c', 'requests', 8); - aggregator.add('g', 'cpu', 50); - aggregator.add('g', 'cpu', 55); - aggregator.add('g', 'cpu', 52); - aggregator.add('d', 'lcp', 1, 'second', { a: 'value', b: 'anothervalue' }); - aggregator.add('d', 'lcp', 1.2, 'second', { a: 'value', b: 'anothervalue' }); - aggregator.add('s', 'important_people', 'a', 'none', { numericKey: 2 }); - aggregator.add('s', 'important_people', 'b', 'none', { numericKey: 2 }); - - const metricBuckets = Array.from(aggregator['_buckets']).map(([, bucketItem]) => bucketItem); - const serializedBuckets = serializeMetricBuckets(metricBuckets); - - expect(serializedBuckets).toContain('requests@none:8|c|T'); - expect(serializedBuckets).toContain('cpu@none:52:50:55:157:3|g|T'); - expect(serializedBuckets).toContain('lcp@second:1:1.2|d|#a:value,b:anothervalue|T'); - expect(serializedBuckets).toContain('important_people@none:97:98|s|#numericKey:2|T'); - - _cleanupAggregator(aggregator); - }); - }); -}); diff --git a/packages/core/test/lib/metrics/timing.test.ts b/packages/core/test/lib/metrics/timing.test.ts deleted file mode 100644 index 3e48047c9175..000000000000 --- a/packages/core/test/lib/metrics/timing.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* eslint-disable deprecation/deprecation */ -import { getCurrentScope, getIsolationScope, setCurrentClient } from '../../../src'; -import { MetricsAggregator } from '../../../src/metrics/aggregator'; -import { metrics as metricsCore } from '../../../src/metrics/exports'; -import { metricsDefault } from '../../../src/metrics/exports-default'; -import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; - -const PUBLIC_DSN = 'https://username@domain/123'; - -describe('metrics.timing', () => { - let testClient: TestClient; - const options = getDefaultTestClientOptions({ - dsn: PUBLIC_DSN, - tracesSampleRate: 0.0, - }); - - beforeEach(() => { - testClient = new TestClient(options); - setCurrentClient(testClient); - }); - - afterEach(() => { - getCurrentScope().setClient(undefined); - getCurrentScope().clear(); - getIsolationScope().clear(); - }); - - it('works with minimal data', async () => { - const res = metricsDefault.timing('t1', 10); - expect(res).toStrictEqual(undefined); - - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); - - metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); - - expect(sendSpy).toHaveBeenCalledTimes(1); - expect(sendSpy).toHaveBeenCalledWith([ - { sent_at: expect.any(String) }, - [[{ length: expect.any(Number), type: 'statsd' }, expect.stringMatching(/t1@second:10\|d\|T(\d+)/)]], - ]); - }); - - it('allows to define a unit', async () => { - const res = metricsDefault.timing('t1', 10, 'hour'); - expect(res).toStrictEqual(undefined); - - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); - - metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); - - expect(sendSpy).toHaveBeenCalledTimes(1); - expect(sendSpy).toHaveBeenCalledWith([ - { sent_at: expect.any(String) }, - [[{ length: expect.any(Number), type: 'statsd' }, expect.stringMatching(/t1@hour:10\|d\|T(\d+)/)]], - ]); - }); - - it('allows to define data', async () => { - const res = metricsDefault.timing('t1', 10, 'hour', { - tags: { tag1: 'value1', tag2: 'value2' }, - }); - expect(res).toStrictEqual(undefined); - - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); - - metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); - - expect(sendSpy).toHaveBeenCalledTimes(1); - expect(sendSpy).toHaveBeenCalledWith([ - { sent_at: expect.any(String) }, - [ - [ - { length: expect.any(Number), type: 'statsd' }, - expect.stringMatching(/t1@hour:10\|d|#tag1:value1,tag2:value2\|T(\d+)/), - ], - ], - ]); - }); - - it('works with a sync callback', async () => { - const res = metricsDefault.timing('t1', () => { - sleepSync(200); - return 'oho'; - }); - expect(res).toStrictEqual('oho'); - - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); - - metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); - - expect(sendSpy).toHaveBeenCalledTimes(1); - expect(sendSpy).toHaveBeenCalledWith([ - { sent_at: expect.any(String) }, - [[{ length: expect.any(Number), type: 'statsd' }, expect.stringMatching(/t1@second:(0.\d+)\|d\|T(\d+)/)]], - ]); - }); - - it('works with an async callback', async () => { - const res = metricsDefault.timing('t1', async () => { - await new Promise(resolve => setTimeout(resolve, 200)); - return 'oho'; - }); - expect(res).toBeInstanceOf(Promise); - expect(await res).toStrictEqual('oho'); - - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); - - metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); - - expect(sendSpy).toHaveBeenCalledTimes(1); - expect(sendSpy).toHaveBeenCalledWith([ - { sent_at: expect.any(String) }, - [[{ length: expect.any(Number), type: 'statsd' }, expect.stringMatching(/t1@second:(0.\d+)\|d\|T(\d+)/)]], - ]); - }); -}); - -function sleepSync(milliseconds: number): void { - const start = Date.now(); - for (let i = 0; i < 1e7; i++) { - if (new Date().getTime() - start > milliseconds) { - break; - } - } -} diff --git a/packages/core/test/lib/metrics/utils.test.ts b/packages/core/test/lib/metrics/utils.test.ts deleted file mode 100644 index e25014715748..000000000000 --- a/packages/core/test/lib/metrics/utils.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - COUNTER_METRIC_TYPE, - DISTRIBUTION_METRIC_TYPE, - GAUGE_METRIC_TYPE, - SET_METRIC_TYPE, -} from '../../../src/metrics/constants'; -import { getBucketKey, sanitizeTags } from '../../../src/metrics/utils'; - -describe('getBucketKey', () => { - it.each([ - [COUNTER_METRIC_TYPE, 'requests', 'none', {}, 'crequestsnone'], - [GAUGE_METRIC_TYPE, 'cpu', 'none', {}, 'gcpunone'], - [DISTRIBUTION_METRIC_TYPE, 'lcp', 'second', { a: 'value', b: 'anothervalue' }, 'dlcpseconda,value,b,anothervalue'], - [DISTRIBUTION_METRIC_TYPE, 'lcp', 'second', { b: 'anothervalue', a: 'value' }, 'dlcpseconda,value,b,anothervalue'], - [DISTRIBUTION_METRIC_TYPE, 'lcp', 'second', { a: '1', b: '2', c: '3' }, 'dlcpseconda,1,b,2,c,3'], - [DISTRIBUTION_METRIC_TYPE, 'lcp', 'second', { numericKey: '2' }, 'dlcpsecondnumericKey,2'], - [SET_METRIC_TYPE, 'important_org_ids', 'none', { numericKey: '2' }, 'simportant_org_idsnonenumericKey,2'], - ])('should return', (metricType, name, unit, tags, expected) => { - expect(getBucketKey(metricType, name, unit, tags)).toEqual(expected); - }); - - it('should sanitize tags', () => { - const inputTags = { - 'f-oo|bar': '%$foo/', - 'foo$.$.$bar': 'blah{}', - 'foö-bar': 'snöwmän', - route: 'GET /foo', - __bar__: 'this | or , that', - 'foo/': 'hello!\n\r\t\\', - }; - - const outputTags = { - 'f-oobar': '%$foo/', - 'foo..bar': 'blah{}', - 'fo-bar': 'snöwmän', - route: 'GET /foo', - __bar__: 'this \\u{7c} or \\u{2c} that', - 'foo/': 'hello!\\n\\r\\t\\\\', - }; - - expect(sanitizeTags(inputTags)).toEqual(outputTags); - }); -}); diff --git a/packages/core/test/lib/tracing/sentrySpan.test.ts b/packages/core/test/lib/tracing/sentrySpan.test.ts index 2998542453fa..52f116df8349 100644 --- a/packages/core/test/lib/tracing/sentrySpan.test.ts +++ b/packages/core/test/lib/tracing/sentrySpan.test.ts @@ -231,7 +231,6 @@ describe('SentrySpan', () => { expect(captureEventSpy).toHaveBeenCalledTimes(1); expect(captureEventSpy).toHaveBeenCalledWith({ - _metrics_summary: undefined, contexts: { trace: { data: { diff --git a/packages/deno/src/index.ts b/packages/deno/src/index.ts index 72938e767b33..40f43bb0d5c2 100644 --- a/packages/deno/src/index.ts +++ b/packages/deno/src/index.ts @@ -64,8 +64,6 @@ export { startSpanManual, startNewTrace, suppressTracing, - // eslint-disable-next-line deprecation/deprecation - metricsDefault as metrics, inboundFiltersIntegration, linkedErrorsIntegration, functionToStringIntegration, diff --git a/packages/google-cloud-serverless/src/index.ts b/packages/google-cloud-serverless/src/index.ts index 24c1f137c5c7..2c04193da8f3 100644 --- a/packages/google-cloud-serverless/src/index.ts +++ b/packages/google-cloud-serverless/src/index.ts @@ -77,8 +77,6 @@ export { continueTrace, getAutoPerformanceIntegrations, cron, - // eslint-disable-next-line deprecation/deprecation - metrics, parameterize, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, diff --git a/packages/integration-shims/src/index.ts b/packages/integration-shims/src/index.ts index 616f9910cf35..510b26ddbb76 100644 --- a/packages/integration-shims/src/index.ts +++ b/packages/integration-shims/src/index.ts @@ -1,4 +1,3 @@ export { feedbackIntegrationShim } from './Feedback'; export { replayIntegrationShim } from './Replay'; export { browserTracingIntegrationShim } from './BrowserTracing'; -export { metricsShim } from './metrics'; diff --git a/packages/integration-shims/src/metrics.ts b/packages/integration-shims/src/metrics.ts deleted file mode 100644 index a8862ee39c03..000000000000 --- a/packages/integration-shims/src/metrics.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { consoleSandbox } from '@sentry/core'; -import type { Metrics } from '@sentry/core'; - -function warn(): void { - consoleSandbox(() => { - // eslint-disable-next-line no-console - console.warn('You are using metrics even though this bundle does not include tracing.'); - }); -} - -export const metricsShim: Metrics = { - increment: warn, - distribution: warn, - set: warn, - gauge: warn, - timing: (_name: unknown, value: number | (() => unknown)) => { - warn(); - if (typeof value === 'function') { - return value(); - } - }, -}; diff --git a/packages/nextjs/src/index.types.ts b/packages/nextjs/src/index.types.ts index 1b965828116f..1c2b17d3a9f9 100644 --- a/packages/nextjs/src/index.types.ts +++ b/packages/nextjs/src/index.types.ts @@ -36,9 +36,6 @@ export declare const createReduxEnhancer: typeof clientSdk.createReduxEnhancer; export declare const showReportDialog: typeof clientSdk.showReportDialog; export declare const withErrorBoundary: typeof clientSdk.withErrorBoundary; -// eslint-disable-next-line deprecation/deprecation -export declare const metrics: typeof clientSdk.metrics & typeof serverSdk.metrics; - export { withSentryConfig } from './config'; /** diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 66fa8cd27e4a..b4c556c39f81 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -117,8 +117,6 @@ export { dedupeIntegration, extraErrorDataIntegration, rewriteFramesIntegration, - // eslint-disable-next-line deprecation/deprecation - metricsDefault as metrics, startSession, captureSession, endSession, diff --git a/packages/nuxt/src/index.types.ts b/packages/nuxt/src/index.types.ts index fd4bd00856be..e22175f67b43 100644 --- a/packages/nuxt/src/index.types.ts +++ b/packages/nuxt/src/index.types.ts @@ -15,5 +15,3 @@ export declare const contextLinesIntegration: typeof clientSdk.contextLinesInteg export declare const getDefaultIntegrations: (options: Options) => Integration[]; export declare const defaultStackParser: StackParser; export declare const continueTrace: typeof clientSdk.continueTrace; -// eslint-disable-next-line deprecation/deprecation -export declare const metrics: typeof clientSdk.metrics & typeof serverSdk.metrics; diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index bff6518eb27d..c6a838a5574f 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -21,7 +21,6 @@ import { dropUndefinedKeys, getCapturedScopesOnSpan, getDynamicSamplingContextFromSpan, - getMetricSummaryJsonForSpan, getStatusMessage, logger, spanTimeInputToSeconds, @@ -298,7 +297,6 @@ export function createTransactionForOtelSpan(span: ReadableSpan): TransactionEve source, }, }), - _metrics_summary: getMetricSummaryJsonForSpan(span as unknown as Span), }); return transactionEvent; @@ -348,7 +346,6 @@ function createAndFinishSpanForOtelSpan(node: SpanNode, spans: SpanJSON[], sentS status: getStatusMessage(status), // As per protocol, span status is allowed to be undefined op, origin, - _metrics_summary: getMetricSummaryJsonForSpan(span as unknown as Span), measurements: timedEventsToMeasurements(span.events), }); diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index 7c4d1460edd6..109e76d7053f 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -77,8 +77,6 @@ export { linkedErrorsIntegration, localVariablesIntegration, makeNodeTransport, - // eslint-disable-next-line deprecation/deprecation - metrics, modulesIntegration, mongoIntegration, mongooseIntegration, diff --git a/packages/remix/src/index.types.ts b/packages/remix/src/index.types.ts index cfba5f67e781..77ad6e59f998 100644 --- a/packages/remix/src/index.types.ts +++ b/packages/remix/src/index.types.ts @@ -38,6 +38,3 @@ export declare const continueTrace: typeof clientSdk.continueTrace; export const close = runtime === 'client' ? clientSdk.close : serverSdk.close; export const flush = runtime === 'client' ? clientSdk.flush : serverSdk.flush; export const lastEventId = runtime === 'client' ? clientSdk.lastEventId : serverSdk.lastEventId; - -// eslint-disable-next-line deprecation/deprecation -export declare const metrics: typeof clientSdk.metrics & typeof serverSdk.metrics; diff --git a/packages/solidstart/src/index.types.ts b/packages/solidstart/src/index.types.ts index 85b712281f38..a204201081dd 100644 --- a/packages/solidstart/src/index.types.ts +++ b/packages/solidstart/src/index.types.ts @@ -26,6 +26,3 @@ export declare function flush(timeout?: number | undefined): PromiseLike; diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index 3e02465ce250..ff31b715768f 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -71,8 +71,6 @@ export { linkedErrorsIntegration, localVariablesIntegration, makeNodeTransport, - // eslint-disable-next-line deprecation/deprecation - metrics, modulesIntegration, mongoIntegration, mongooseIntegration, diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 565589bc0fbb..5dc7a916c9d7 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -83,12 +83,6 @@ import type { MeasurementUnit as MeasurementUnit_imported, Measurements as Measurements_imported, Mechanism as Mechanism_imported, - MetricBucketItem as MetricBucketItem_imported, - MetricData as MetricData_imported, - MetricInstance as MetricInstance_imported, - MetricSummary as MetricSummary_imported, - Metrics as Metrics_imported, - MetricsAggregator as MetricsAggregator_imported, MissingInstrumentationContext as MissingInstrumentationContext_imported, MonitorConfig as MonitorConfig_imported, NoneUnit as NoneUnit_imported, @@ -158,8 +152,6 @@ import type { StackParser as StackParser_imported, Stacktrace as Stacktrace_imported, StartSpanOptions as StartSpanOptions_imported, - StatsdEnvelope as StatsdEnvelope_imported, - StatsdItem as StatsdItem_imported, Thread as Thread_imported, ThreadCpuFrame as ThreadCpuFrame_imported, ThreadCpuProfile as ThreadCpuProfile_imported, @@ -282,10 +274,6 @@ export type CheckInItem = CheckInItem_imported; /** @deprecated This type has been moved to `@sentry/core`. */ export type CheckInEnvelope = CheckInEnvelope_imported; /** @deprecated This type has been moved to `@sentry/core`. */ -export type StatsdItem = StatsdItem_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ -export type StatsdEnvelope = StatsdEnvelope_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ export type ProfileItem = ProfileItem_imported; /** @deprecated This type has been moved to `@sentry/core`. */ export type ProfileChunkEnvelope = ProfileChunkEnvelope_imported; @@ -454,8 +442,6 @@ export type SpanContextData = SpanContextData_imported; /** @deprecated This type has been moved to `@sentry/core`. */ export type TraceFlag = TraceFlag_imported; /** @deprecated This type has been moved to `@sentry/core`. */ -export type MetricSummary = MetricSummary_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ export type SpanStatus = SpanStatus_imported; /** @deprecated This type has been moved to `@sentry/core`. */ export type TimedEvent = TimedEvent_imported; @@ -555,16 +541,6 @@ export type InProgressCheckIn = InProgressCheckIn_imported; /** @deprecated This type has been moved to `@sentry/core`. */ export type SerializedCheckIn = SerializedCheckIn_imported; /** @deprecated This type has been moved to `@sentry/core`. */ -export type MetricsAggregator = MetricsAggregator_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ -export type MetricBucketItem = MetricBucketItem_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ -export type MetricInstance = MetricInstance_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ -export type MetricData = MetricData_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ -export type Metrics = Metrics_imported; -/** @deprecated This type has been moved to `@sentry/core`. */ export type ParameterizedString = ParameterizedString_imported; /** @deprecated This type has been moved to `@sentry/core`. */ export type ContinuousProfiler = ContinuousProfiler_imported; diff --git a/packages/vercel-edge/src/index.ts b/packages/vercel-edge/src/index.ts index 2301d620bb05..0820a4590c70 100644 --- a/packages/vercel-edge/src/index.ts +++ b/packages/vercel-edge/src/index.ts @@ -67,8 +67,6 @@ export { withActiveSpan, getSpanDescendants, continueTrace, - // eslint-disable-next-line deprecation/deprecation - metrics, functionToStringIntegration, inboundFiltersIntegration, linkedErrorsIntegration, From d89236edbe5a8ed39422151c15223ae9ee5ab1bb Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 18 Dec 2024 08:08:33 +0000 Subject: [PATCH 4/8] docs(angular): Update README for more recent Angular versions (#14767) Update the README.md to include examples with `ApplicationConfig` as a first-class citizen, as it is now the recommended approach. Most users are likely using the latest versions, but older examples have also been preserved. --- packages/angular/README.md | 86 ++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/packages/angular/README.md b/packages/angular/README.md index 42ee54a8d81c..95e0379480d7 100644 --- a/packages/angular/README.md +++ b/packages/angular/README.md @@ -17,7 +17,7 @@ ## Angular Version Compatibility -This SDK officially supports Angular 15 to 17. +This SDK officially supports Angular 14 to 19. If you're using an older Angular version please check the [compatibility table in the docs](https://docs.sentry.io/platforms/javascript/guides/angular/#angular-version-compatibility). @@ -33,24 +33,17 @@ in `@sentry/browser` can be imported from `@sentry/angular`. To use this SDK, call `Sentry.init(options)` before you bootstrap your Angular application. ```javascript -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; import { init } from '@sentry/angular'; -import { AppModule } from './app/app.module'; +import { AppComponent } from './app/app.component'; init({ dsn: '__DSN__', // ... }); -// ... - -enableProdMode(); -platformBrowserDynamic() - .bootstrapModule(AppModule) - .then(success => console.log(`Bootstrap success`)) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig); ``` ### ErrorHandler @@ -58,10 +51,22 @@ platformBrowserDynamic() `@sentry/angular` exports a function to instantiate an ErrorHandler provider that will automatically send Javascript errors captured by the Angular's error handler. -```javascript -import { NgModule, ErrorHandler } from '@angular/core'; +```ts +import { ApplicationConfig, NgModule, ErrorHandler } from '@angular/core'; import { createErrorHandler } from '@sentry/angular'; +export const appConfig: ApplicationConfig = { + providers: [ + { + provide: ErrorHandler, + useValue: createErrorHandler({ + showDialog: true, + }), + }, + ], +}; + +// Or using an old module approach: @NgModule({ // ... providers: [ @@ -104,42 +109,27 @@ init({ }); ``` -2. Register `SentryTrace` as a provider in Angular's DI system, with a `Router` as its dependency: +2. Inject the `TraceService` in the `APP_INITIALIZER`: -```javascript -import { NgModule } from '@angular/core'; -import { Router } from '@angular/router'; -import { TraceService } from '@sentry/angular'; +```ts +import { ApplicationConfig, APP_INITIALIZER, provideAppInitializer } from '@angular/core'; -@NgModule({ - // ... +export const appConfig: ApplicationConfig = { providers: [ { - provide: TraceService, - deps: [Router], + provide: APP_INITIALIZER, + useFactory: () => () => {}, + deps: [TraceService], + multi: true, }, - ], - // ... -}) -export class AppModule {} -``` - -3. Either require the `TraceService` from inside `AppModule` or use `APP_INITIALIZER` to force-instantiate Tracing. - -```javascript -@NgModule({ - // ... -}) -export class AppModule { - constructor(trace: TraceService) {} -} -``` - -or -```javascript -import { APP_INITIALIZER } from '@angular/core'; + // Starting with Angular 19, we can use `provideAppInitializer` + // instead of directly providing `APP_INITIALIZER` (deprecated): + provideAppInitializer(() => inject(TraceService)), + ], +}; +// Or using an old module approach: @NgModule({ // ... providers: [ @@ -149,6 +139,10 @@ import { APP_INITIALIZER } from '@angular/core'; deps: [TraceService], multi: true, }, + + // Starting with Angular 19, we can use `provideAppInitializer` + // instead of directly providing `APP_INITIALIZER` (deprecated): + provideAppInitializer(() => inject(TraceService)), ], // ... }) @@ -161,15 +155,15 @@ To track Angular components as part of your transactions, you have 3 options. _TraceDirective:_ used to track a duration between `OnInit` and `AfterViewInit` lifecycle hooks in template: -```javascript +```ts import { TraceModule } from '@sentry/angular'; -@NgModule({ - // ... +@Component({ + selector: 'some-component', imports: [TraceModule], // ... }) -export class AppModule {} +export class SomeComponentThatUsesTraceDirective {} ``` Then, inside your component's template (keep in mind that the directive's name attribute is required): From 4096ab8855b1bda1d78983958c978e3896720f3e Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Wed, 18 Dec 2024 09:30:58 +0100 Subject: [PATCH 5/8] chore: Add external contributor to CHANGELOG.md (#14770) This PR adds the external contributor to the CHANGELOG.md file, so that they are credited for their contribution. See #14767 --------- Co-authored-by: Lms24 <8420481+Lms24@users.noreply.github.com> Co-authored-by: Lukas Stracke --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c8b093cc09..8e9c94e32e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott -Work in this release was contributed by @maximepvrt and @aloisklink. Thank you for your contributions! +Work in this release was contributed by @maximepvrt, @arturovt and @aloisklink. Thank you for your contributions! ## 8.45.0 From ecfec198ca1929d8633eb8f36ae28281116b9d10 Mon Sep 17 00:00:00 2001 From: Max Malm Date: Wed, 18 Dec 2024 10:00:44 +0100 Subject: [PATCH 6/8] ref(nextjs): Fix typo in source maps deletion warning (#14766) Co-authored-by: Lukas Stracke --- packages/nextjs/src/config/webpack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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()`.", ); } From 786c5ca65b2ad4264072b95be9e88e82ee44c3cd Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 18 Dec 2024 10:07:57 +0100 Subject: [PATCH 7/8] feat(node): Do not overwrite prisma `db.system` in newer Prisma versions (#14771) Since v5.22, Prisma properly adds the `db.system` to it's OTEL spans. This PR fixes the behavior so we do not overwrite it. For now, I left the fallback behavior in, that would add it if `db.system` is missing - as otherwise this would "break" on older prisma versions. This also needs to be backported to v8. --- .../node-integration-tests/package.json | 2 +- .../suites/tracing/prisma-orm/package.json | 4 +- .../suites/tracing/prisma-orm/test.ts | 228 ++++++++++-------- .../suites/tracing/prisma-orm/yarn.lock | 91 +++---- .../node/src/integrations/tracing/prisma.ts | 4 +- 5 files changed, 186 insertions(+), 143 deletions(-) diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index 24be97583c1c..4be4b830f1c2 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -30,7 +30,7 @@ "@nestjs/common": "10.4.6", "@nestjs/core": "10.4.6", "@nestjs/platform-express": "10.4.6", - "@prisma/client": "5.9.1", + "@prisma/client": "5.22.0", "@sentry/aws-serverless": "8.45.0", "@sentry/core": "8.45.0", "@sentry/node": "8.45.0", 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/packages/node/src/integrations/tracing/prisma.ts b/packages/node/src/integrations/tracing/prisma.ts index a42d41a6b5ec..010493fff77d 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'); } }); From 2853845bf7ccae81c3651bf975b5a71b62d915b4 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 18 Dec 2024 11:13:37 +0100 Subject: [PATCH 8/8] feat!: Require Node `>=18` as minimum supported version (#14749) We decided to require node 18+ in v9. This is to align with the upcoming changes in OpenTelemetry. We also believe it is a reasonable version requirement - Node 16 is EOL for some time now. This will also allow us to update a bunch of dev tooling (vitest, ...) properly and streamline some processes. For users requiring Node 14/16, they can remain on v8 (which will be continued to be supported with bug fixes for some time). ref https://github.com/getsentry/sentry-javascript/issues/14257 --- .github/ISSUE_TEMPLATE/flaky.yml | 2 +- .github/actions/restore-cache/action.yml | 15 ---- .github/workflows/build.yml | 63 ++++--------- README.md | 2 + .../browser-integration-tests/package.json | 6 +- dev-packages/e2e-tests/package.json | 2 +- .../create-next-app/package.json | 2 +- .../create-react-app/package.json | 2 +- .../default-browser/package.json | 2 +- .../ember-classic/package.json | 4 +- .../ember-embroider/package.json | 4 +- .../generic-ts3.8/package.json | 2 +- .../test-applications/nestjs-8/package.json | 2 +- .../nestjs-basic-with-graphql/package.json | 2 +- .../nestjs-basic/package.json | 2 +- .../nestjs-distributed-tracing/package.json | 2 +- .../nestjs-fastify/package.json | 2 +- .../nestjs-graphql/package.json | 2 +- .../package.json | 2 +- .../nestjs-with-submodules/package.json | 2 +- .../test-applications/nextjs-13/package.json | 2 +- .../test-applications/nextjs-14/package.json | 2 +- .../test-applications/nextjs-15/package.json | 2 +- .../nextjs-app-dir/package.json | 2 +- .../test-applications/nextjs-t3/package.json | 2 +- .../nextjs-turbo/package.json | 2 +- .../node-connect/package.json | 2 +- .../node-exports-test-app/package.json | 2 +- .../package.json | 2 +- .../node-express-send-to-sentry/package.json | 2 +- .../node-express/package.json | 2 +- .../node-fastify-5/package.json | 2 +- .../node-fastify/package.json | 2 +- .../test-applications/node-koa/package.json | 2 +- .../node-otel-custom-sampler/package.json | 2 +- .../node-otel-sdk-node/package.json | 2 +- .../node-otel-without-tracing/package.json | 2 +- .../test-applications/react-19/package.json | 2 +- .../react-create-hash-router/package.json | 2 +- .../react-router-5/package.json | 2 +- .../react-send-to-sentry/package.json | 2 +- .../test-applications/vue-3/package.json | 2 +- .../node-integration-tests/package.json | 4 +- .../{use-ts-version.js => use-ts-3_8.js} | 9 +- .../node-integration-tests/suites/anr/test.ts | 3 +- .../suites/contextLines/test.ts | 3 +- .../suites/esm/import-in-the-middle/test.ts | 3 +- .../suites/esm/modules-integration/test.ts | 3 +- .../suites/no-code/test.ts | 3 +- .../suites/public-api/LocalVariables/test.ts | 2 +- .../suites/tracing/ai/test.ts | 3 +- .../suites/tracing/prisma-orm/package.json | 2 +- .../suites/tracing/prisma-orm/setup.ts | 18 ---- .../suites/tracing/prisma-orm/test.ts | 3 +- .../requests/fetch-breadcrumbs/test.ts | 3 +- .../tracing/requests/fetch-no-tracing/test.ts | 3 +- .../fetch-sampled-no-active-span/test.ts | 3 +- .../tracing/requests/fetch-unsampled/test.ts | 3 +- .../tracing/requests/http-sampled-esm/test.ts | 3 +- .../suites/tracing/tedious/test.ts | 3 +- dev-packages/test-utils/package.json | 2 +- docs/migration/v8-to-v9.md | 4 +- package.json | 6 +- packages/angular/package.json | 3 +- packages/astro/package.json | 2 +- packages/aws-serverless/package.json | 4 +- packages/browser-utils/package.json | 2 +- packages/browser/package.json | 2 +- packages/bun/package.json | 2 +- packages/cloudflare/package.json | 4 +- packages/core/package.json | 2 +- packages/deno/package.json | 2 +- packages/ember/package.json | 2 +- packages/eslint-config-sdk/package.json | 2 +- packages/eslint-plugin-sdk/package.json | 2 +- packages/feedback/package.json | 2 +- packages/gatsby/package.json | 2 +- packages/google-cloud-serverless/package.json | 4 +- .../test/gcpfunction/cloud_event.test.ts | 2 +- .../test/gcpfunction/events.test.ts | 2 +- .../test/gcpfunction/http.test.ts | 1 + packages/integration-shims/package.json | 2 +- packages/nestjs/package.json | 2 +- packages/nextjs/package.json | 2 +- packages/nextjs/test/types/package.json | 2 +- packages/nextjs/test/types/test.ts | 12 --- packages/nitro-utils/package.json | 2 +- packages/node/package.json | 4 +- .../node/src/proxy/parse-proxy-response.ts | 2 +- packages/nuxt/package.json | 2 +- packages/opentelemetry/package.json | 2 +- packages/profiling-node/README.md | 5 +- packages/profiling-node/package.json | 4 +- packages/profiling-node/src/utils.ts | 6 +- packages/react/package.json | 2 +- packages/remix/package.json | 2 +- packages/remix/test/integration/package.json | 2 +- packages/replay-canvas/package.json | 2 +- packages/replay-internal/package.json | 2 +- packages/replay-worker/package.json | 2 +- packages/solid/package.json | 2 +- packages/solidstart/package.json | 2 +- packages/svelte/package.json | 2 +- packages/sveltekit/package.json | 2 +- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- packages/vercel-edge/package.json | 2 +- .../async-local-storage-context-manager.ts | 2 +- packages/vue/package.json | 2 +- packages/wasm/package.json | 2 +- scripts/ci-unit-tests.ts | 43 --------- yarn.lock | 89 +++++++++++++------ 112 files changed, 203 insertions(+), 302 deletions(-) rename dev-packages/node-integration-tests/scripts/{use-ts-version.js => use-ts-3_8.js} (80%) delete mode 100755 dev-packages/node-integration-tests/suites/tracing/prisma-orm/setup.ts delete mode 100644 packages/nextjs/test/types/test.ts diff --git a/.github/ISSUE_TEMPLATE/flaky.yml b/.github/ISSUE_TEMPLATE/flaky.yml index a679cf98d328..2e86f8ebd869 100644 --- a/.github/ISSUE_TEMPLATE/flaky.yml +++ b/.github/ISSUE_TEMPLATE/flaky.yml @@ -19,7 +19,7 @@ body: id: job-name attributes: label: Name of Job - placeholder: "CI: Build & Test / Nextjs (Node 14) Tests" + placeholder: "CI: Build & Test / Nextjs (Node 18) Tests" description: name of job as reported in the status report validations: required: true diff --git a/.github/actions/restore-cache/action.yml b/.github/actions/restore-cache/action.yml index 6cd63a6550e4..e523cca6d904 100644 --- a/.github/actions/restore-cache/action.yml +++ b/.github/actions/restore-cache/action.yml @@ -5,9 +5,6 @@ inputs: dependency_cache_key: description: "The dependency cache key" required: true - node_version: - description: "If set, temporarily set node version to default one before installing, then revert to this version after." - required: false runs: using: "composite" @@ -24,19 +21,7 @@ runs: with: name: build-output - - name: Use default node version for install - if: inputs.node_version && steps.dep-cache.outputs.cache-hit != 'true' - uses: actions/setup-node@v4 - with: - node-version-file: 'package.json' - - name: Install dependencies if: steps.dep-cache.outputs.cache-hit != 'true' run: yarn install --ignore-engines --frozen-lockfile shell: bash - - - name: Revert node version to ${{ inputs.node_version }} - if: inputs.node_version && steps.dep-cache.outputs.cache-hit != 'true' - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node_version }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31f5cea28bda..6dc65ca48a99 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -459,7 +459,7 @@ jobs: strategy: fail-fast: false matrix: - node: [14, 16, 18, 20, 22] + node: [18, 20, 22] steps: - name: Check out base commit (${{ github.event.pull_request.base.sha }}) uses: actions/checkout@v4 @@ -478,7 +478,6 @@ jobs: uses: ./.github/actions/restore-cache with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - node_version: ${{ matrix.node == 14 && '14' || '' }} - name: Run affected tests run: yarn test:pr:node --base=${{ github.event.pull_request.base.sha }} @@ -715,7 +714,7 @@ jobs: strategy: fail-fast: false matrix: - node: [14, 16, 18, 20, 22] + node: [18, 20, 22] typescript: - false include: @@ -735,17 +734,13 @@ jobs: uses: ./.github/actions/restore-cache with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - node_version: ${{ matrix.node == 14 && '14' || '' }} - name: Overwrite typescript version - if: matrix.typescript - run: node ./scripts/use-ts-version.js ${{ matrix.typescript }} + if: matrix.typescript == '3.8' + run: node ./scripts/use-ts-3_8.js working-directory: dev-packages/node-integration-tests - name: Run integration tests - env: - NODE_VERSION: ${{ matrix.node }} - TS_VERSION: ${{ matrix.typescript }} working-directory: dev-packages/node-integration-tests run: yarn test @@ -760,10 +755,6 @@ jobs: matrix: node: [18, 20, 22] remix: [1, 2] - # Remix v2 only supports Node 18+, so run 16 tests separately - include: - - node: 16 - remix: 1 steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) uses: actions/checkout@v4 @@ -1243,7 +1234,7 @@ jobs: echo "One of the dependent jobs have failed. You may need to re-run it." && exit 1 job_compile_bindings_profiling_node: - name: Compile & Test Profiling Bindings (v${{ matrix.node }}) ${{ matrix.target_platform || matrix.os }}, ${{ matrix.node || matrix.container }}, ${{ matrix.arch || matrix.container }}, ${{ contains(matrix.container, 'alpine') && 'musl' || 'glibc' }} + name: Compile profiling-node (v${{ matrix.node }}) ${{ matrix.target_platform || matrix.os }}, ${{ matrix.arch || matrix.container }}, ${{ contains(matrix.container, 'alpine') && 'musl' || 'glibc' }} needs: [job_get_metadata, job_build] # Compiling bindings can be very slow (especially on windows), so only run precompile # Skip precompile unless we are on a release branch as precompile slows down CI times. @@ -1251,16 +1242,14 @@ jobs: (needs.job_get_metadata.outputs.changed_profiling_node == 'true') || (needs.job_get_metadata.outputs.is_release == 'true') runs-on: ${{ matrix.os }} - container: ${{ matrix.container }} + container: + image: ${{ matrix.container }} timeout-minutes: 30 strategy: fail-fast: false matrix: include: # x64 glibc - - os: ubuntu-20.04 - node: 16 - binary: linux-x64-glibc-93 - os: ubuntu-20.04 node: 18 binary: linux-x64-glibc-108 @@ -1272,10 +1261,6 @@ jobs: binary: linux-x64-glibc-127 # x64 musl - - os: ubuntu-20.04 - container: node:16-alpine3.16 - binary: linux-x64-musl-93 - node: 16 - os: ubuntu-20.04 container: node:18-alpine3.17 node: 18 @@ -1290,10 +1275,6 @@ jobs: binary: linux-x64-musl-127 # arm64 glibc - - os: ubuntu-20.04 - arch: arm64 - node: 16 - binary: linux-arm64-glibc-93 - os: ubuntu-20.04 arch: arm64 node: 18 @@ -1308,11 +1289,6 @@ jobs: binary: linux-arm64-glibc-127 # arm64 musl - - os: ubuntu-20.04 - container: node:16-alpine3.16 - arch: arm64 - node: 16 - binary: linux-arm64-musl-93 - os: ubuntu-20.04 arch: arm64 container: node:18-alpine3.17 @@ -1330,10 +1306,6 @@ jobs: binary: linux-arm64-musl-127 # macos x64 - - os: macos-13 - node: 16 - arch: x64 - binary: darwin-x64-93 - os: macos-13 node: 18 arch: x64 @@ -1348,11 +1320,6 @@ jobs: binary: darwin-x64-127 # macos arm64 - - os: macos-13 - arch: arm64 - node: 16 - target_platform: darwin - binary: darwin-arm64-93 - os: macos-13 arch: arm64 node: 18 @@ -1370,10 +1337,6 @@ jobs: binary: darwin-arm64-127 # windows x64 - - os: windows-2022 - node: 16 - arch: x64 - binary: win32-x64-93 - os: windows-2022 node: 18 arch: x64 @@ -1399,8 +1362,13 @@ jobs: with: ref: ${{ env.HEAD_COMMIT }} + # Note: On alpine images, this does nothing + # The node version will be the one that is installed in the image + # If you want to change the node version, you need to change the image + # For non-alpine imgages, this will install the correct version of node - name: Setup Node uses: actions/setup-node@v4 + if: contains(matrix.container, 'alpine') == false with: node-version: ${{ matrix.node }} @@ -1417,10 +1385,10 @@ jobs: run: yarn config set network-timeout 600000 -g - name: Install dependencies - env: - SKIP_PLAYWRIGHT_BROWSER_INSTALL: "1" if: steps.restore-dependencies.outputs.cache-hit != 'true' run: yarn install --ignore-engines --frozen-lockfile + env: + SKIP_PLAYWRIGHT_BROWSER_INSTALL: "1" - name: Configure safe directory run: | @@ -1498,8 +1466,7 @@ jobs: BUILD_ARCH=arm64 \ yarn build:bindings:arm64 - - name: Build Monorepo - if: steps.restore-build.outputs.cache-hit != 'true' + - name: Build profiling-node & its dependencies run: yarn build --scope @sentry/profiling-node - name: Test Bindings diff --git a/README.md b/README.md index db7000a9d51f..ed4fc189f11b 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,8 @@ package. Please refer to the README and instructions of those SDKs for more deta The current version of the SDK is 8.x. Version 7.x of the SDK will continue to receive critical bugfixes until end of 2024. +All SDKs require Node v18+ to run. ESM-only SDKs require Node v18.19.1+ to run. + ## Installation and Usage To install a SDK, simply add the high-level package, for example: diff --git a/dev-packages/browser-integration-tests/package.json b/dev-packages/browser-integration-tests/package.json index 31a7ce76727e..eced2725a93b 100644 --- a/dev-packages/browser-integration-tests/package.json +++ b/dev-packages/browser-integration-tests/package.json @@ -4,12 +4,12 @@ "main": "index.js", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "private": true, "scripts": { "clean": "rimraf -g suites/**/dist loader-suites/**/dist tmp", - "install-browsers": "[[ -z \"$SKIP_PLAYWRIGHT_BROWSER_INSTALL\" ]] && yarn npx playwright install --with-deps || echo 'Skipping browser installation'", + "install-browsers": "[[ -z \"$SKIP_PLAYWRIGHT_BROWSER_INSTALL\" ]] && npx playwright install --with-deps || echo 'Skipping browser installation'", "lint": "eslint . --format stylish", "fix": "eslint . --format stylish --fix", "type-check": "tsc", @@ -52,7 +52,7 @@ }, "devDependencies": { "@types/glob": "8.0.0", - "@types/node": "^14.18.0", + "@types/node": "^18.19.1", "@types/pako": "^2.0.0", "glob": "8.0.3" }, diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index e1ff6f84550a..958b1645e1c0 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -21,7 +21,7 @@ }, "devDependencies": { "@types/glob": "8.0.0", - "@types/node": "^18.0.0", + "@types/node": "^18.19.1", "dotenv": "16.0.3", "esbuild": "0.20.0", "glob": "8.0.3", diff --git a/dev-packages/e2e-tests/test-applications/create-next-app/package.json b/dev-packages/e2e-tests/test-applications/create-next-app/package.json index e91c0ee135e5..fc8f48c822d6 100644 --- a/dev-packages/e2e-tests/test-applications/create-next-app/package.json +++ b/dev-packages/e2e-tests/test-applications/create-next-app/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@sentry/nextjs": "latest || *", - "@types/node": "18.11.17", + "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "next": "14.0.0", diff --git a/dev-packages/e2e-tests/test-applications/create-react-app/package.json b/dev-packages/e2e-tests/test-applications/create-react-app/package.json index 916a17260a2a..ee98e1ec3f48 100644 --- a/dev-packages/e2e-tests/test-applications/create-react-app/package.json +++ b/dev-packages/e2e-tests/test-applications/create-react-app/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@sentry/react": "latest || *", - "@types/node": "16.7.13", + "@types/node": "^18.19.1", "@types/react": "18.0.0", "@types/react-dom": "18.0.0", "react": "18.2.0", diff --git a/dev-packages/e2e-tests/test-applications/default-browser/package.json b/dev-packages/e2e-tests/test-applications/default-browser/package.json index dc31366f2ea8..635a4bef1955 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/package.json +++ b/dev-packages/e2e-tests/test-applications/default-browser/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@sentry/browser": "latest || *", - "@types/node": "16.7.13", + "@types/node": "^18.19.1", "typescript": "4.9.5" }, "scripts": { diff --git a/dev-packages/e2e-tests/test-applications/ember-classic/package.json b/dev-packages/e2e-tests/test-applications/ember-classic/package.json index 4c887cda10ea..a0c0b4101d09 100644 --- a/dev-packages/e2e-tests/test-applications/ember-classic/package.json +++ b/dev-packages/e2e-tests/test-applications/ember-classic/package.json @@ -48,7 +48,7 @@ "@types/ember__string": "~3.0.15", "@types/ember__template": "~4.0.7", "@types/ember__utils": "~4.0.7", - "@types/node": "18.18.0", + "@types/node": "^18.19.1", "@types/rsvp": "~4.0.9", "broccoli-asset-rev": "~3.0.0", "ember-auto-import": "~2.4.3", @@ -72,7 +72,7 @@ "webpack": "~5.97.0" }, "engines": { - "node": "14.* || 16.* || >= 18" + "node": ">=18" }, "resolutions": { "@babel/traverse": "~7.25.9" diff --git a/dev-packages/e2e-tests/test-applications/ember-embroider/package.json b/dev-packages/e2e-tests/test-applications/ember-embroider/package.json index a8a4db191d81..b96b70876f53 100644 --- a/dev-packages/e2e-tests/test-applications/ember-embroider/package.json +++ b/dev-packages/e2e-tests/test-applications/ember-embroider/package.json @@ -54,14 +54,14 @@ "@sentry/ember": "latest || *", "@sentry-internal/test-utils": "link:../../../test-utils", "@tsconfig/ember": "^3.0.6", - "@types/node": "18.18.0", + "@types/node": "^18.19.1", "@tsconfig/node18": "18.2.4", "@types/rsvp": "^4.0.9", "ts-node": "10.9.1", "typescript": "^5.4.5" }, "engines": { - "node": ">= 18" + "node": ">=18" }, "ember": { "edition": "octane" diff --git a/dev-packages/e2e-tests/test-applications/generic-ts3.8/package.json b/dev-packages/e2e-tests/test-applications/generic-ts3.8/package.json index 77bebc280ea4..c9b564bf1651 100644 --- a/dev-packages/e2e-tests/test-applications/generic-ts3.8/package.json +++ b/dev-packages/e2e-tests/test-applications/generic-ts3.8/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "typescript": "3.8.3", - "@types/node": "^14.18.0" + "@types/node": "^14.0.0" }, "dependencies": { "@sentry/browser": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-8/package.json b/dev-packages/e2e-tests/test-applications/nestjs-8/package.json index 20724e8d3b78..15ae8cf64bc8 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-8/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-8/package.json @@ -31,7 +31,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json index 62606e825e33..04c1cfc27fb7 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json @@ -33,7 +33,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json b/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json index 44dcda348383..b51f6e74d3bc 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json @@ -31,7 +31,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json b/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json index 6efae6b1c0d5..15392e604a75 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json @@ -30,7 +30,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json b/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json index 6da132e74a4c..d456c22370df 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json @@ -31,7 +31,7 @@ "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json b/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json index 2463d24df940..640889424a87 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json @@ -33,7 +33,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json index 0b03e38ccbdb..e1dd3d4b3030 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json @@ -29,7 +29,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json index 8f90e1582598..78e661aa7d4f 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json @@ -29,7 +29,7 @@ "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "@types/supertest": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/package.json b/dev-packages/e2e-tests/test-applications/nextjs-13/package.json index de03f89fce27..fa16079822b8 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-13/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@sentry/nextjs": "latest || *", - "@types/node": "18.11.17", + "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "next": "13.5.7", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/package.json b/dev-packages/e2e-tests/test-applications/nextjs-14/package.json index d1ef013e6ccc..5e42830d0874 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@sentry/nextjs": "latest || *", - "@types/node": "18.11.17", + "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "next": "14.1.3", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/package.json b/dev-packages/e2e-tests/test-applications/nextjs-15/package.json index ca92feb9c254..ace02f6a1924 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@sentry/nextjs": "latest || *", - "@types/node": "18.11.17", + "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "next": "15.0.0-canary.182", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json index 4b09aff7f937..81f576ef016b 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json @@ -16,7 +16,7 @@ }, "dependencies": { "@sentry/nextjs": "latest || *", - "@types/node": "18.11.17", + "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "next": "14.0.2", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-t3/package.json b/dev-packages/e2e-tests/test-applications/nextjs-t3/package.json index 304e26d83433..1ebef0ce37ae 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-t3/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-t3/package.json @@ -32,7 +32,7 @@ "@playwright/test": "^1.44.1", "@sentry-internal/test-utils": "link:../../../test-utils", "@types/eslint": "^8.56.10", - "@types/node": "^20.14.10", + "@types/node": "^18.19.1", "@types/react": "18.3.1", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^8.1.0", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json b/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json index 10630c257349..9db87a43cd49 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@sentry/nextjs": "latest || *", - "@types/node": "18.11.17", + "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "next": "15.0.0", diff --git a/dev-packages/e2e-tests/test-applications/node-connect/package.json b/dev-packages/e2e-tests/test-applications/node-connect/package.json index 276e8654f8f4..ffd692a2175e 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/package.json +++ b/dev-packages/e2e-tests/test-applications/node-connect/package.json @@ -14,7 +14,7 @@ "@sentry/node": "latest || *", "@sentry/core": "latest || *", "@sentry/opentelemetry": "latest || *", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "connect": "3.7.0", "typescript": "4.9.5", "ts-node": "10.9.1" diff --git a/dev-packages/e2e-tests/test-applications/node-exports-test-app/package.json b/dev-packages/e2e-tests/test-applications/node-exports-test-app/package.json index 5be4d29bbb38..975553194815 100644 --- a/dev-packages/e2e-tests/test-applications/node-exports-test-app/package.json +++ b/dev-packages/e2e-tests/test-applications/node-exports-test-app/package.json @@ -20,7 +20,7 @@ "@sentry/aws-serverless": "latest || *", "@sentry/google-cloud-serverless": "latest || *", "@sentry/bun": "latest || *", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "typescript": "4.9.5" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json b/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json index 391514a2c1dd..2931b2bea72f 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json @@ -16,7 +16,7 @@ "@trpc/server": "10.45.2", "@trpc/client": "10.45.2", "@types/express": "4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "express": "4.20.0", "typescript": "4.9.5", "zod": "~3.22.4" diff --git a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json index 49e98e2c49ad..5e964bbdd8bd 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json @@ -14,7 +14,7 @@ "@sentry/core": "latest || *", "@sentry/node": "latest || *", "@types/express": "4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "express": "4.19.2", "typescript": "4.9.5" }, diff --git a/dev-packages/e2e-tests/test-applications/node-express/package.json b/dev-packages/e2e-tests/test-applications/node-express/package.json index bc0b9b4dead7..684a6ae1a3da 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express/package.json @@ -16,7 +16,7 @@ "@trpc/server": "10.45.2", "@trpc/client": "10.45.2", "@types/express": "4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "express": "4.20.0", "typescript": "4.9.5", "zod": "~3.22.4" diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json b/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json index e0a000572a25..f720b711d1fa 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json @@ -14,7 +14,7 @@ "@sentry/node": "latest || *", "@sentry/core": "latest || *", "@sentry/opentelemetry": "latest || *", - "@types/node": "22.7.5", + "@types/node": "^18.19.1", "fastify": "5.0.0", "typescript": "5.6.3", "ts-node": "10.9.2" diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/package.json b/dev-packages/e2e-tests/test-applications/node-fastify/package.json index b657eddd1de1..1a3847ef3b12 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify/package.json @@ -14,7 +14,7 @@ "@sentry/node": "latest || *", "@sentry/core": "latest || *", "@sentry/opentelemetry": "latest || *", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "fastify": "4.23.2", "typescript": "4.9.5", "ts-node": "10.9.1" diff --git a/dev-packages/e2e-tests/test-applications/node-koa/package.json b/dev-packages/e2e-tests/test-applications/node-koa/package.json index 0f6ed61216db..7962f3153682 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/package.json +++ b/dev-packages/e2e-tests/test-applications/node-koa/package.json @@ -13,7 +13,7 @@ "@koa/bodyparser": "^5.1.1", "@koa/router": "^12.0.1", "@sentry/node": "latest || *", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "koa": "^2.15.2", "typescript": "4.9.5" }, diff --git a/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json b/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json index 30cd21643eb8..c5ffdf039553 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel-custom-sampler/package.json @@ -16,7 +16,7 @@ "@sentry/node": "latest || *", "@sentry/opentelemetry": "latest || *", "@types/express": "4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "express": "4.19.2", "typescript": "4.9.5" }, diff --git a/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json b/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json index fd2b9bf4aafe..88c6f4c3eef9 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel-sdk-node/package.json @@ -17,7 +17,7 @@ "@sentry/node": "latest || *", "@sentry/opentelemetry": "latest || *", "@types/express": "4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "express": "4.19.2", "typescript": "4.9.5" }, diff --git a/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json b/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json index efe84d86604e..905c94449732 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json +++ b/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/package.json @@ -20,7 +20,7 @@ "@sentry/node": "latest || *", "@sentry/opentelemetry": "latest || *", "@types/express": "4.17.17", - "@types/node": "18.15.1", + "@types/node": "^18.19.1", "express": "4.19.2", "typescript": "4.9.5" }, diff --git a/dev-packages/e2e-tests/test-applications/react-19/package.json b/dev-packages/e2e-tests/test-applications/react-19/package.json index 5de946437a44..b5d3d25d5fb7 100644 --- a/dev-packages/e2e-tests/test-applications/react-19/package.json +++ b/dev-packages/e2e-tests/test-applications/react-19/package.json @@ -6,7 +6,7 @@ "@sentry/react": "latest || *", "history": "4.9.0", "@types/history": "4.7.11", - "@types/node": "16.7.13", + "@types/node": "^18.19.1", "@types/react": "npm:types-react@rc", "@types/react-dom": "npm:types-react-dom@rc", "react": "19.0.0-rc-935180c7e0-20240524", diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json b/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json index e475fb505fc8..bfe148db10a6 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@sentry/react": "latest || *", - "@types/node": "16.7.13", + "@types/node": "^18.19.1", "@types/react": "18.0.0", "@types/react-dom": "18.0.0", "react": "18.2.0", diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/package.json b/dev-packages/e2e-tests/test-applications/react-router-5/package.json index 0b208b3f5a65..b23643e8be31 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-5/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-5/package.json @@ -6,7 +6,7 @@ "@sentry/react": "latest || *", "history": "4.9.0", "@types/history": "4.7.11", - "@types/node": "16.7.13", + "@types/node": "^18.19.1", "@types/react": "18.0.0", "@types/react-dom": "18.0.0", "@types/react-router": "5.1.20", diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json index 836707b3017f..9be121c97312 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@sentry/react": "latest || *", - "@types/node": "16.7.13", + "@types/node": "^18.19.1", "@types/react": "18.0.0", "@types/react-dom": "18.0.0", "react": "18.2.0", diff --git a/dev-packages/e2e-tests/test-applications/vue-3/package.json b/dev-packages/e2e-tests/test-applications/vue-3/package.json index f34bdf6d6c0e..06436101eee8 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/package.json +++ b/dev-packages/e2e-tests/test-applications/vue-3/package.json @@ -25,7 +25,7 @@ "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/core": "latest || *", "@tsconfig/node20": "^20.1.2", - "@types/node": "^20.11.10", + "@types/node": "^18.19.1", "@vitejs/plugin-vue": "^5.0.3", "@vitejs/plugin-vue-jsx": "^3.1.0", "@vue/tsconfig": "^0.5.1", diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index 4be4b830f1c2..f27d4c7e750e 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -3,7 +3,7 @@ "version": "8.45.0", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "private": true, "main": "build/cjs/index.js", @@ -16,7 +16,7 @@ "build:types": "tsc -p tsconfig.types.json", "clean": "rimraf -g **/node_modules && run-p clean:script", "clean:script": "node scripts/clean.js", - "prisma:init": "(cd suites/tracing/prisma-orm && ts-node ./setup.ts)", + "prisma:init": "cd suites/tracing/prisma-orm && yarn && yarn setup", "lint": "eslint . --format stylish", "fix": "eslint . --format stylish --fix", "type-check": "tsc", diff --git a/dev-packages/node-integration-tests/scripts/use-ts-version.js b/dev-packages/node-integration-tests/scripts/use-ts-3_8.js similarity index 80% rename from dev-packages/node-integration-tests/scripts/use-ts-version.js rename to dev-packages/node-integration-tests/scripts/use-ts-3_8.js index 0b64d735436c..e8b43ecfe6f2 100644 --- a/dev-packages/node-integration-tests/scripts/use-ts-version.js +++ b/dev-packages/node-integration-tests/scripts/use-ts-3_8.js @@ -5,11 +5,14 @@ const { writeFileSync } = require('fs'); const cwd = join(__dirname, '../../..'); -const tsVersion = process.argv[2] || '3.8'; +const tsVersion = '3.8'; -console.log(`Installing typescript@${tsVersion}...`); +console.log(`Installing typescript@${tsVersion}, and @types/node@14...`); -execSync(`yarn add --dev --ignore-workspace-root-check typescript@${tsVersion}`, { stdio: 'inherit', cwd }); +execSync(`yarn add --dev --ignore-workspace-root-check typescript@${tsVersion} @types/node@^14`, { + stdio: 'inherit', + cwd, +}); console.log('Removing unsupported tsconfig options...'); diff --git a/dev-packages/node-integration-tests/suites/anr/test.ts b/dev-packages/node-integration-tests/suites/anr/test.ts index d1d9c684bf60..1366600d5280 100644 --- a/dev-packages/node-integration-tests/suites/anr/test.ts +++ b/dev-packages/node-integration-tests/suites/anr/test.ts @@ -1,5 +1,4 @@ import type { Event } from '@sentry/core'; -import { conditionalTest } from '../../utils'; import { cleanupChildProcesses, createRunner } from '../../utils/runner'; const ANR_EVENT = { @@ -107,7 +106,7 @@ const ANR_EVENT_WITH_DEBUG_META: Event = { }, }; -conditionalTest({ min: 16 })('should report ANR when event loop blocked', () => { +describe('should report ANR when event loop blocked', () => { afterAll(() => { cleanupChildProcesses(); }); diff --git a/dev-packages/node-integration-tests/suites/contextLines/test.ts b/dev-packages/node-integration-tests/suites/contextLines/test.ts index 1912f0b57f04..06591bcfbe8e 100644 --- a/dev-packages/node-integration-tests/suites/contextLines/test.ts +++ b/dev-packages/node-integration-tests/suites/contextLines/test.ts @@ -1,8 +1,7 @@ import { join } from 'path'; -import { conditionalTest } from '../../utils'; import { createRunner } from '../../utils/runner'; -conditionalTest({ min: 18 })('ContextLines integration in ESM', () => { +describe('ContextLines integration in ESM', () => { test('reads encoded context lines from filenames with spaces', done => { expect.assertions(1); const instrumentPath = join(__dirname, 'instrument.mjs'); diff --git a/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts index d1584c2ea32d..828ff702f45b 100644 --- a/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts +++ b/dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts @@ -1,13 +1,12 @@ import { spawnSync } from 'child_process'; import { join } from 'path'; -import { conditionalTest } from '../../../utils'; import { cleanupChildProcesses } from '../../../utils/runner'; afterAll(() => { cleanupChildProcesses(); }); -conditionalTest({ min: 18 })('import-in-the-middle', () => { +describe('import-in-the-middle', () => { test('onlyIncludeInstrumentedModules', () => { const result = spawnSync('node', [join(__dirname, 'app.mjs')], { encoding: 'utf-8' }); expect(result.stderr).not.toMatch('should be the only hooked modules but we just hooked'); diff --git a/dev-packages/node-integration-tests/suites/esm/modules-integration/test.ts b/dev-packages/node-integration-tests/suites/esm/modules-integration/test.ts index 556ec1d52a57..eaee003781f3 100644 --- a/dev-packages/node-integration-tests/suites/esm/modules-integration/test.ts +++ b/dev-packages/node-integration-tests/suites/esm/modules-integration/test.ts @@ -1,11 +1,10 @@ -import { conditionalTest } from '../../../utils'; import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; afterAll(() => { cleanupChildProcesses(); }); -conditionalTest({ min: 18 })('modulesIntegration', () => { +describe('modulesIntegration', () => { test('does not crash ESM setups', done => { createRunner(__dirname, 'app.mjs').ensureNoErrorOutput().start(done); }); diff --git a/dev-packages/node-integration-tests/suites/no-code/test.ts b/dev-packages/node-integration-tests/suites/no-code/test.ts index dfaae9de7cdc..fdcd5bd25fc6 100644 --- a/dev-packages/node-integration-tests/suites/no-code/test.ts +++ b/dev-packages/node-integration-tests/suites/no-code/test.ts @@ -1,4 +1,3 @@ -import { conditionalTest } from '../../utils'; import { cleanupChildProcesses, createRunner } from '../../utils/runner'; const EVENT = { @@ -25,7 +24,7 @@ describe('no-code init', () => { .start(done); }); - conditionalTest({ min: 18 })('--import', () => { + describe('--import', () => { test('ESM', done => { createRunner(__dirname, 'app.mjs') .withFlags('--import=@sentry/node/init') diff --git a/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts b/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts index 779b341d9f40..7ed9d352474a 100644 --- a/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts @@ -37,7 +37,7 @@ const EXPECTED_LOCAL_VARIABLES_EVENT = { }, }; -conditionalTest({ min: 18 })('LocalVariables integration', () => { +describe('LocalVariables integration', () => { afterAll(() => { cleanupChildProcesses(); }); diff --git a/dev-packages/node-integration-tests/suites/tracing/ai/test.ts b/dev-packages/node-integration-tests/suites/tracing/ai/test.ts index e269f9da9db3..bc263e9fc610 100644 --- a/dev-packages/node-integration-tests/suites/tracing/ai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/ai/test.ts @@ -1,8 +1,7 @@ -import { conditionalTest } from '../../../utils'; import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; // `ai` SDK only support Node 18+ -conditionalTest({ min: 18 })('ai', () => { +describe('ai', () => { afterAll(() => { cleanupChildProcesses(); }); 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 70e2c29be629..b8721038c83b 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 @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "engines": { - "node": ">=16" + "node": ">=18" }, "scripts": { "db-up": "docker compose up -d", diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/setup.ts b/dev-packages/node-integration-tests/suites/tracing/prisma-orm/setup.ts deleted file mode 100755 index a0052511b380..000000000000 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm/setup.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { execSync } from 'child_process'; -import { parseSemver } from '@sentry/core'; - -const NODE_VERSION = parseSemver(process.versions.node); - -// Prisma v5 requires Node.js v16+ -// https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5#nodejs-minimum-version-change -if (NODE_VERSION.major && NODE_VERSION.major < 16) { - // eslint-disable-next-line no-console - console.warn(`Skipping Prisma tests on Node: ${NODE_VERSION.major}`); - process.exit(0); -} - -try { - execSync('yarn && yarn setup'); -} catch (_) { - process.exit(1); -} 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 4cc1757c0d19..d5e9f7ba372f 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 @@ -1,7 +1,6 @@ -import { conditionalTest } from '../../../utils'; import { createRunner } from '../../../utils/runner'; -conditionalTest({ min: 16 })('Prisma ORM Tests', () => { +describe('Prisma ORM Tests', () => { test('CJS - should instrument PostgreSQL queries from Prisma ORM', done => { createRunner(__dirname, 'scenario.js') .expect({ diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts index c0d783aaa594..254d197c85c3 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts @@ -1,8 +1,7 @@ -import { conditionalTest } from '../../../../utils'; import { createRunner } from '../../../../utils/runner'; import { createTestServer } from '../../../../utils/server'; -conditionalTest({ min: 18 })('outgoing fetch', () => { +describe('outgoing fetch', () => { test('outgoing fetch requests create breadcrumbs', done => { createTestServer(done) .start() diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts index 9c732d899cde..906fa6541dd6 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts @@ -1,8 +1,7 @@ -import { conditionalTest } from '../../../../utils'; import { createRunner } from '../../../../utils/runner'; import { createTestServer } from '../../../../utils/server'; -conditionalTest({ min: 18 })('outgoing fetch', () => { +describe('outgoing fetch', () => { test('outgoing fetch requests are correctly instrumented with tracing disabled', done => { expect.assertions(11); diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts index fde1c787829a..afe60d27b22a 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts @@ -1,8 +1,7 @@ -import { conditionalTest } from '../../../../utils'; import { createRunner } from '../../../../utils/runner'; import { createTestServer } from '../../../../utils/server'; -conditionalTest({ min: 18 })('outgoing fetch', () => { +describe('outgoing fetch', () => { test('outgoing sampled fetch requests without active span are correctly instrumented', done => { expect.assertions(11); diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts index d288e9a03fbf..cb85ca98ca0b 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts @@ -1,8 +1,7 @@ -import { conditionalTest } from '../../../../utils'; import { createRunner } from '../../../../utils/runner'; import { createTestServer } from '../../../../utils/server'; -conditionalTest({ min: 18 })('outgoing fetch', () => { +describe('outgoing fetch', () => { test('outgoing fetch requests are correctly instrumented when not sampled', done => { expect.assertions(11); diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-esm/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-esm/test.ts index 72f625aedeb7..f3d58877c8f3 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-esm/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-esm/test.ts @@ -1,9 +1,8 @@ import { join } from 'path'; -import { conditionalTest } from '../../../../utils'; import { createRunner } from '../../../../utils/runner'; import { createTestServer } from '../../../../utils/server'; -conditionalTest({ min: 18 })('outgoing http in ESM', () => { +describe('outgoing http in ESM', () => { test('outgoing sampled http requests are correctly instrumented in ESM', done => { expect.assertions(11); diff --git a/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts b/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts index c4a0ae29fe38..6c5fd17f833a 100644 --- a/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts @@ -1,11 +1,10 @@ -import { conditionalTest } from '../../../utils'; import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; jest.setTimeout(75000); // Tedious version we are testing against only supports Node 18+ // https://github.com/tediousjs/tedious/blob/8310c455a2cc1cba83c1ca3c16677da4f83e12a9/package.json#L38 -conditionalTest({ min: 18 })('tedious auto instrumentation', () => { +describe('tedious auto instrumentation', () => { afterAll(() => { cleanupChildProcesses(); }); diff --git a/dev-packages/test-utils/package.json b/dev-packages/test-utils/package.json index 09ad4cf5a55d..8e8afec9f698 100644 --- a/dev-packages/test-utils/package.json +++ b/dev-packages/test-utils/package.json @@ -28,7 +28,7 @@ }, "sideEffects": false, "engines": { - "node": ">=14.18" + "node": ">=18" }, "scripts": { "fix": "eslint . --format stylish --fix", diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index d6d49a0e72aa..3854a5b44ae3 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -24,8 +24,8 @@ This includes features like Nullish Coalescing (`??`), Optional Chaining (`?.`), If you observe failures due to syntax or features listed above, it may be an indicator that your current runtime does not support ES2020. If your runtime does not support ES2020, we recommend transpiling the SDK using Babel or similar tooling. -**Node.js:** The minimum supported Node.js versions are TBD, TBD, and TBD. -We no longer test against Node TBD, TBD, or TBD and cannot guarantee that the SDK will work as expected on these versions. +**Node.js:** The minimum supported Node.js version is **18.0.0**, except for ESM-only SDKs (nuxt, solidstart, astro) which require Node **18.19.1** or up. +We no longer test against Node 14 and Node 16 and cannot guarantee that the SDK will work as expected on these versions. **Browsers:** Due to SDK code now including ES2020 features, the minimum supported browser list now looks as follows: diff --git a/package.json b/package.json index e948ae773c72..c326f88d1347 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,9 @@ "yalc:publish": "lerna run yalc:publish" }, "volta": { - "node": "18.20.3", + "node": "18.20.5", "yarn": "1.22.22", - "pnpm": "9.4.0" + "pnpm": "9.15.0" }, "workspaces": [ "packages/angular", @@ -112,7 +112,7 @@ "@size-limit/webpack": "~11.1.6", "@types/jest": "^27.4.1", "@types/jsdom": "^21.1.6", - "@types/node": "^14.18.0", + "@types/node": "^18.19.1", "@vitest/coverage-v8": "^1.6.0", "deepmerge": "^4.2.2", "downlevel-dts": "~0.11.0", diff --git a/packages/angular/package.json b/packages/angular/package.json index 06bb0492c2f7..1ec948299d01 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "type": "module", "module": "build/fesm2015/sentry-angular.mjs", @@ -35,6 +35,7 @@ "@angular/platform-browser": "^14.3.0", "@angular/platform-browser-dynamic": "^14.3.0", "@angular/router": "^14.3.0", + "@types/node": "^14.8.0", "ng-packagr": "^14.2.2", "rxjs": "7.8.1", "typescript": "4.6.4", diff --git a/packages/astro/package.json b/packages/astro/package.json index 43c374a766cc..3d52f1145cd4 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -14,7 +14,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=18.14.1" + "node": ">=18.19.1" }, "type": "module", "files": [ diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 856a7dc4f51f..716b1c3fa5f7 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build/npm", @@ -73,7 +73,7 @@ "@types/aws-lambda": "^8.10.62" }, "devDependencies": { - "@types/node": "^14.18.0" + "@types/node": "^18.19.1" }, "scripts": { "build": "run-p build:transpile build:types build:bundle", diff --git a/packages/browser-utils/package.json b/packages/browser-utils/package.json index 15d5bde00065..57730a1032f2 100644 --- a/packages/browser-utils/package.json +++ b/packages/browser-utils/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/browser/package.json b/packages/browser/package.json index f588f2801eb0..bb659245699e 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build/npm" diff --git a/packages/bun/package.json b/packages/bun/package.json index ce1c85cbcd0f..753046173a9c 100644 --- a/packages/bun/package.json +++ b/packages/bun/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/cloudflare/package.json b/packages/cloudflare/package.json index efec51c5c0f5..aa84ff96c596 100644 --- a/packages/cloudflare/package.json +++ b/packages/cloudflare/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" @@ -46,7 +46,7 @@ }, "devDependencies": { "@cloudflare/workers-types": "^4.20240725.0", - "@types/node": "^14.18.0", + "@types/node": "^18.19.1", "wrangler": "^3.67.1" }, "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index ab43b79117b9..c9079fcf5a14 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/deno/package.json b/packages/deno/package.json index 851252d0435f..0bd8498ceae9 100644 --- a/packages/deno/package.json +++ b/packages/deno/package.json @@ -28,7 +28,7 @@ }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.5", - "@types/node": "20.8.2", + "@types/node": "^18.19.1", "rollup-plugin-dts": "^6.1.0" }, "scripts": { diff --git a/packages/ember/package.json b/packages/ember/package.json index 1547eed88d94..1e111f752d71 100644 --- a/packages/ember/package.json +++ b/packages/ember/package.json @@ -72,7 +72,7 @@ "webpack": "~5.95.0" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "ember": { "edition": "octane" diff --git a/packages/eslint-config-sdk/package.json b/packages/eslint-config-sdk/package.json index 246f51ed6dcf..fc85554ac878 100644 --- a/packages/eslint-config-sdk/package.json +++ b/packages/eslint-config-sdk/package.json @@ -12,7 +12,7 @@ "sentry" ], "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/src" diff --git a/packages/eslint-plugin-sdk/package.json b/packages/eslint-plugin-sdk/package.json index 7a6a729fc0cd..402a304747d5 100644 --- a/packages/eslint-plugin-sdk/package.json +++ b/packages/eslint-plugin-sdk/package.json @@ -12,7 +12,7 @@ "sentry" ], "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/src" diff --git a/packages/feedback/package.json b/packages/feedback/package.json index a5e44856378e..ec9451115a27 100644 --- a/packages/feedback/package.json +++ b/packages/feedback/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build/npm" diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 2c03fae30f14..3fe9850166dd 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -11,7 +11,7 @@ "gatsby-plugin" ], "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build", diff --git a/packages/google-cloud-serverless/package.json b/packages/google-cloud-serverless/package.json index 52008df49931..236674dc37d3 100644 --- a/packages/google-cloud-serverless/package.json +++ b/packages/google-cloud-serverless/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" @@ -57,7 +57,7 @@ "@google-cloud/common": "^3.4.1", "@google-cloud/functions-framework": "^1.7.1", "@google-cloud/pubsub": "^2.5.0", - "@types/node": "^14.18.0", + "@types/node": "^18.19.1", "google-gax": "^2.9.0", "nock": "^13.5.5" }, diff --git a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts index 941d4d259930..95323881828d 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts @@ -44,8 +44,8 @@ describe('wrapCloudEventFunction', () => { function handleCloudEvent(fn: CloudEventFunctionWithCallback): Promise { return new Promise((resolve, reject) => { + // eslint-disable-next-line deprecation/deprecation const d = domain.create(); - // d.on('error', () => res.end()); const context = { type: 'event.type', }; diff --git a/packages/google-cloud-serverless/test/gcpfunction/events.test.ts b/packages/google-cloud-serverless/test/gcpfunction/events.test.ts index 363147409fd2..aa449f5407c9 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/events.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/events.test.ts @@ -45,8 +45,8 @@ describe('wrapEventFunction', () => { function handleEvent(fn: EventFunctionWithCallback): Promise { return new Promise((resolve, reject) => { + // eslint-disable-next-line deprecation/deprecation const d = domain.create(); - // d.on('error', () => res.end()); const context = { eventType: 'event.type', resource: 'some.resource', diff --git a/packages/google-cloud-serverless/test/gcpfunction/http.test.ts b/packages/google-cloud-serverless/test/gcpfunction/http.test.ts index 5590add6f618..08d53df50b31 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/http.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/http.test.ts @@ -58,6 +58,7 @@ describe('GCPFunction', () => { headers = { ...headers, ...trace_headers }; } return new Promise((resolve, _reject) => { + // eslint-disable-next-line deprecation/deprecation const d = domain.create(); const req = { method: 'POST', diff --git a/packages/integration-shims/package.json b/packages/integration-shims/package.json index 322922a945a0..c5e3c3b4d3f8 100644 --- a/packages/integration-shims/package.json +++ b/packages/integration-shims/package.json @@ -58,7 +58,7 @@ "@sentry/core": "8.45.0" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "volta": { "extends": "../../package.json" diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index a11de76a0c31..18f83f3b36f4 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18" }, "files": [ "/build", diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index baafbe149a1d..b1412a670d8b 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "main": "build/cjs/index.server.js", "module": "build/esm/index.server.js", diff --git a/packages/nextjs/test/types/package.json b/packages/nextjs/test/types/package.json index 86f74bfe060a..a3df1aed6d76 100644 --- a/packages/nextjs/test/types/package.json +++ b/packages/nextjs/test/types/package.json @@ -1,7 +1,7 @@ { "description": "This is used to install the nextjs v12 so we can test against those types", "scripts": { - "test": "ts-node test.ts" + "test": "yarn && yarn tsc --noEmit --project tsconfig.json" }, "dependencies": { "next": "13.2.0" diff --git a/packages/nextjs/test/types/test.ts b/packages/nextjs/test/types/test.ts deleted file mode 100644 index f9f45d29f29b..000000000000 --- a/packages/nextjs/test/types/test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { execSync } from 'child_process'; -/* eslint-disable no-console */ -import { parseSemver } from '@sentry/core'; - -const NODE_VERSION = parseSemver(process.versions.node); - -if (NODE_VERSION.major && NODE_VERSION.major >= 12) { - console.log('Installing next@v12...'); - execSync('yarn install', { stdio: 'inherit' }); - console.log('Testing some types...'); - execSync('tsc --noEmit --project tsconfig.json', { stdio: 'inherit' }); -} diff --git a/packages/nitro-utils/package.json b/packages/nitro-utils/package.json index 06ec390ef87f..2f7061aa1479 100644 --- a/packages/nitro-utils/package.json +++ b/packages/nitro-utils/package.json @@ -8,7 +8,7 @@ "license": "MIT", "private": true, "engines": { - "node": ">=16.20" + "node": ">=18.19.1" }, "files": [ "/build" diff --git a/packages/node/package.json b/packages/node/package.json index 2724bb85a7ad..ca564b0e8fb7 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" @@ -101,7 +101,7 @@ "import-in-the-middle": "^1.11.2" }, "devDependencies": { - "@types/node": "^14.18.0" + "@types/node": "^18.19.1" }, "scripts": { "build": "run-p build:transpile build:types", diff --git a/packages/node/src/proxy/parse-proxy-response.ts b/packages/node/src/proxy/parse-proxy-response.ts index a2c05b1dbe2c..afad0d2435f4 100644 --- a/packages/node/src/proxy/parse-proxy-response.ts +++ b/packages/node/src/proxy/parse-proxy-response.ts @@ -89,7 +89,7 @@ export function parseProxyResponse(socket: Readable): Promise<{ connect: Connect return; } - const headerParts = buffered.slice(0, endOfHeaders).toString('ascii').split('\r\n'); + const headerParts = buffered.subarray(0, endOfHeaders).toString('ascii').split('\r\n'); const firstLine = headerParts.shift(); if (!firstLine) { socket.destroy(); diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 86ce75ba76f8..bee5e78f7582 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.19.1" }, "files": [ "/build" diff --git a/packages/opentelemetry/package.json b/packages/opentelemetry/package.json index e342a8d34be8..db008ad65f62 100644 --- a/packages/opentelemetry/package.json +++ b/packages/opentelemetry/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/profiling-node/README.md b/packages/profiling-node/README.md index 890022ae2e88..e96bc41eb569 100644 --- a/packages/profiling-node/README.md +++ b/packages/profiling-node/README.md @@ -12,8 +12,7 @@ ## Installation -Profiling works as an extension of tracing so you will need both @sentry/node and @sentry/profiling-node installed. The -minimum required major version of @sentry/node that supports profiling is 7.x. +Profiling works as an extension of tracing so you will need both @sentry/node and @sentry/profiling-node installed. ```bash # Using yarn @@ -84,7 +83,7 @@ After the binaries are built, you should see them inside the profiling-node/lib ### Prebuilt binaries -We currently ship prebuilt binaries for a few of the most common platforms and node versions (v16-22). +We currently ship prebuilt binaries for a few of the most common platforms and node versions (v18-22). - macOS x64 - Linux ARM64 (musl) diff --git a/packages/profiling-node/package.json b/packages/profiling-node/package.json index 19ecb062875e..80a35a718838 100644 --- a/packages/profiling-node/package.json +++ b/packages/profiling-node/package.json @@ -32,7 +32,7 @@ "sentry-prune-profiler-binaries": "scripts/prune-profiler-binaries.js" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "publishConfig": { "access": "public" @@ -81,7 +81,7 @@ "node-abi": "^3.61.0" }, "devDependencies": { - "@types/node": "16.18.70", + "@types/node": "^18.19.1", "@types/node-abi": "^3.0.3", "clang-format": "^1.8.0", "cross-env": "^7.0.3", diff --git a/packages/profiling-node/src/utils.ts b/packages/profiling-node/src/utils.ts index 1c0828a5468c..78844af5fa8e 100644 --- a/packages/profiling-node/src/utils.ts +++ b/packages/profiling-node/src/utils.ts @@ -37,16 +37,12 @@ export const PROFILER_THREAD_NAME = isMainThread ? 'main' : 'worker'; const FORMAT_VERSION = '1'; const CONTINUOUS_FORMAT_VERSION = '2'; -// Os machine was backported to 16.18, but this was not reflected in the types -// @ts-expect-error ignore missing -const machine = typeof os.machine === 'function' ? os.machine() : os.arch(); - // Machine properties (eval only once) const PLATFORM = os.platform(); const RELEASE = os.release(); const VERSION = os.version(); const TYPE = os.type(); -const MODEL = machine; +const MODEL = os.machine(); const ARCH = os.arch(); /** diff --git a/packages/react/package.json b/packages/react/package.json index d14ad2f112a8..81596144ae79 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/remix/package.json b/packages/remix/package.json index 9967c77676bc..05d9c5ef157a 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -10,7 +10,7 @@ "sentry-upload-sourcemaps": "scripts/sentry-upload-sourcemaps.js" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build", diff --git a/packages/remix/test/integration/package.json b/packages/remix/test/integration/package.json index b00f17b330f9..82c46d519f63 100644 --- a/packages/remix/test/integration/package.json +++ b/packages/remix/test/integration/package.json @@ -40,6 +40,6 @@ "**/path-scurry/lru-cache": "10.2.0" }, "engines": { - "node": ">=14.18" + "node": ">=18" } } diff --git a/packages/replay-canvas/package.json b/packages/replay-canvas/package.json index 4faeb7db1ef7..3f0367c201e0 100644 --- a/packages/replay-canvas/package.json +++ b/packages/replay-canvas/package.json @@ -72,7 +72,7 @@ "@sentry/core": "8.45.0" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "volta": { "extends": "../../package.json" diff --git a/packages/replay-internal/package.json b/packages/replay-internal/package.json index 4267723b8b67..9c24ba5f5511 100644 --- a/packages/replay-internal/package.json +++ b/packages/replay-internal/package.json @@ -80,7 +80,7 @@ "@sentry/core": "8.45.0" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "volta": { "extends": "../../package.json" diff --git a/packages/replay-worker/package.json b/packages/replay-worker/package.json index 7a1596319e4f..43ea5e9c0d1e 100644 --- a/packages/replay-worker/package.json +++ b/packages/replay-worker/package.json @@ -49,7 +49,7 @@ "fflate": "0.8.1" }, "engines": { - "node": ">=14.18" + "node": ">=18" }, "volta": { "extends": "../../package.json" diff --git a/packages/solid/package.json b/packages/solid/package.json index f718a1374a11..266e1b197b52 100644 --- a/packages/solid/package.json +++ b/packages/solid/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build", diff --git a/packages/solidstart/package.json b/packages/solidstart/package.json index dba27d321153..e64c0d5d4b20 100644 --- a/packages/solidstart/package.json +++ b/packages/solidstart/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.19.1" }, "files": [ "/build", diff --git a/packages/svelte/package.json b/packages/svelte/package.json index fb95251cf35b..887ae19b02da 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json index 7ae146015a74..4961d2727696 100644 --- a/packages/sveltekit/package.json +++ b/packages/sveltekit/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/types/package.json b/packages/types/package.json index 26927c6882b9..5be24f954f1b 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/utils/package.json b/packages/utils/package.json index b35f0087434b..c8e04a5dac75 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/vercel-edge/package.json b/packages/vercel-edge/package.json index 4e7f81e055af..90fc7cd39534 100644 --- a/packages/vercel-edge/package.json +++ b/packages/vercel-edge/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/vercel-edge/src/vendored/async-local-storage-context-manager.ts b/packages/vercel-edge/src/vendored/async-local-storage-context-manager.ts index 67828f4c852e..8d8a1e6dd171 100644 --- a/packages/vercel-edge/src/vendored/async-local-storage-context-manager.ts +++ b/packages/vercel-edge/src/vendored/async-local-storage-context-manager.ts @@ -52,7 +52,7 @@ export class AsyncLocalStorageContextManager extends AbstractAsyncHooksContextMa getStore() { return undefined; }, - run(_store, callback, ...args) { + run(_store: unknown, callback: () => Context, ...args: unknown[]) { return callback.apply(this, args); }, disable() { diff --git a/packages/vue/package.json b/packages/vue/package.json index 167352a6289b..bf2256e30e11 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build" diff --git a/packages/wasm/package.json b/packages/wasm/package.json index a45a87130c7c..ed871a604375 100644 --- a/packages/wasm/package.json +++ b/packages/wasm/package.json @@ -7,7 +7,7 @@ "author": "Sentry", "license": "MIT", "engines": { - "node": ">=14.18" + "node": ">=18" }, "files": [ "/build/npm" diff --git a/scripts/ci-unit-tests.ts b/scripts/ci-unit-tests.ts index 08459e9eabba..85f852052bac 100644 --- a/scripts/ci-unit-tests.ts +++ b/scripts/ci-unit-tests.ts @@ -2,16 +2,7 @@ import * as childProcess from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; -type NodeVersion = '14' | '16' | '18' | '20' | '21'; - -interface VersionConfig { - ignoredPackages: Array<`@${'sentry' | 'sentry-internal'}/${string}`>; -} - const UNIT_TEST_ENV = process.env.UNIT_TEST_ENV as 'node' | 'browser' | undefined; - -const CURRENT_NODE_VERSION = process.version.replace('v', '').split('.')[0] as NodeVersion; - const RUN_AFFECTED = process.argv.includes('--affected'); // These packages are tested separately in CI, so no need to run them here @@ -35,35 +26,6 @@ const BROWSER_TEST_PACKAGES = [ '@sentry/wasm', ]; -// These are Node-version specific tests that need to be skipped because of support -const SKIP_TEST_PACKAGES: Record = { - '14': { - ignoredPackages: [ - '@sentry/cloudflare', - '@sentry/solidstart', - '@sentry/sveltekit', - '@sentry/vercel-edge', - '@sentry/astro', - '@sentry/nuxt', - '@sentry/nestjs', - '@sentry-internal/eslint-plugin-sdk', - '@sentry-internal/nitro-utils', - ], - }, - '16': { - ignoredPackages: ['@sentry/cloudflare', '@sentry/vercel-edge', '@sentry/astro', '@sentry/solidstart'], - }, - '18': { - ignoredPackages: [], - }, - '20': { - ignoredPackages: [], - }, - '21': { - ignoredPackages: [], - }, -}; - function getAllPackages(): string[] { const { workspaces }: { workspaces: string[] } = JSON.parse( fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'), @@ -96,11 +58,6 @@ function runTests(): void { BROWSER_TEST_PACKAGES.forEach(pkg => ignores.add(pkg)); } - const versionConfig = SKIP_TEST_PACKAGES[CURRENT_NODE_VERSION]; - if (versionConfig) { - versionConfig.ignoredPackages.forEach(dep => ignores.add(dep)); - } - if (RUN_AFFECTED) { runAffectedTests(ignores); } else { diff --git a/yarn.lock b/yarn.lock index ea225a675006..c6867bdf6f75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10085,7 +10085,17 @@ dependencies: "@types/unist" "*" -"@types/history-4@npm:@types/history@4.7.8", "@types/history-5@npm:@types/history@4.7.8", "@types/history@*": +"@types/history-4@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history-5@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history@*": version "4.7.8" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== @@ -10294,36 +10304,26 @@ "@types/node" "*" "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18": - version "22.9.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" - integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ== + version "22.10.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" + integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== dependencies: - undici-types "~6.19.8" - -"@types/node@16.18.70": - version "16.18.70" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.70.tgz#d4c819be1e9f8b69a794d6f2fd929d9ff76f6d4b" - integrity sha512-8eIk20G5VVVQNZNouHjLA2b8utE2NvGybLjMaF4lyhA9uhGwnmXF8o+icdXKGSQSNANJewXva/sFUoZLwAaYAg== - -"@types/node@20.8.2": - version "20.8.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.2.tgz#d76fb80d87d0d8abfe334fc6d292e83e5524efc4" - integrity sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w== + undici-types "~6.20.0" "@types/node@^10.1.0": version "10.17.60" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== -"@types/node@^14.18.0": +"@types/node@^14.8.0": version "14.18.63" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== -"@types/node@^18.0.0": - version "18.19.64" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.64.tgz#122897fb79f2a9ec9c979bded01c11461b2b1478" - integrity sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ== +"@types/node@^18.19.1": + version "18.19.68" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.68.tgz#f4f10d9927a7eaf3568c46a6d739cc0967ccb701" + integrity sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw== dependencies: undici-types "~5.26.4" @@ -10412,7 +10412,15 @@ "@types/history" "^3" "@types/react" "*" -"@types/react-router-4@npm:@types/react-router@5.1.14", "@types/react-router-5@npm:@types/react-router@5.1.14": +"@types/react-router-4@npm:@types/react-router@5.1.14": + version "5.1.14" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" + integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-router-5@npm:@types/react-router@5.1.14": version "5.1.14" resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== @@ -31246,7 +31254,16 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0= -"string-width-cjs@npm:string-width@^4.2.0", string-width@4.2.3, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@4.2.3, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -31358,7 +31375,14 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -32742,10 +32766,10 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.19.8: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== undici@^5.25.4: version "5.28.3" @@ -34387,7 +34411,16 @@ wrangler@^3.67.1: optionalDependencies: fsevents "~2.3.2" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@7.0.0, wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@7.0.0, wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==