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 bee6f56336d0..7a8c9f975d87 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'; @@ -177,7 +174,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,