From cdcc9fbd17dc707edaa18cca8f575d9fdf7a9faf Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 22 Feb 2024 09:10:18 -0400 Subject: [PATCH 1/3] feat(metrics): Remove metrics method from client --- docs/event-sending.md | 8 +-- packages/browser/src/client.ts | 8 +-- packages/core/src/baseclient.ts | 55 ++++++------------- packages/core/src/metrics/aggregator.ts | 8 +-- .../core/src/metrics/browser-aggregator.ts | 9 +-- packages/core/src/metrics/utils.ts | 23 +++++++- packages/core/src/server-runtime-client.ts | 4 +- .../core/test/lib/metrics/aggregator.test.ts | 29 ++-------- .../core/test/lib/serverruntimeclient.test.ts | 6 +- .../node-experimental/test/sdk/client.test.ts | 9 +-- packages/node/test/client.test.ts | 9 +-- packages/types/src/client.ts | 7 --- 12 files changed, 72 insertions(+), 103 deletions(-) diff --git a/docs/event-sending.md b/docs/event-sending.md index 894da827508b..b72eda1d0746 100644 --- a/docs/event-sending.md +++ b/docs/event-sending.md @@ -25,7 +25,7 @@ This document gives an outline for how event sending works, and which which plac - `createEnvelope()` - `addItemToEnvelope()` - `createAttachmentEnvelopeItem()` - - `baseclient._sendEnvelope()` + - `baseclient.sendEnvelope()` - `transport.send()` ## Transactions @@ -54,7 +54,7 @@ This document gives an outline for how event sending works, and which which plac - `createEnvelope()` - `addItemToEnvelope()` - `createAttachmentEnvelopeItem()` - - `baseclient._sendEnvelope()` + - `baseclient.sendEnvelope()` - `transport.send()` ## Sessions @@ -70,7 +70,7 @@ This document gives an outline for how event sending works, and which which plac - `createSessionEnvelope()` - `getSdkMetadataForEnvelopeHeader()` - `createEnvelope()` - - `baseclient._sendEnvelope()` + - `baseclient.sendEnvelope()` - `transport.send()` - `updateSession()` @@ -94,5 +94,5 @@ This document gives an outline for how event sending works, and which which plac - `browser.client._flushOutcomes()` - `getEnvelopeEndpointWithUrlEncodedAuth()` - `createClientReportEnvelope()` - - `baseclient._sendEnvelope()` + - `baseclient.sendEnvelope()` - `transport.send()` diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 97ea8e3b5e0c..869d28c16c50 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -96,9 +96,9 @@ export class BrowserClient extends BaseClient { tunnel: this.getOptions().tunnel, }); - // _sendEnvelope should not throw + // sendEnvelope should not throw // eslint-disable-next-line @typescript-eslint/no-floating-promises - this._sendEnvelope(envelope); + this.sendEnvelope(envelope); } /** @@ -130,8 +130,8 @@ export class BrowserClient extends BaseClient { const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn)); - // _sendEnvelope should not throw + // sendEnvelope should not throw // eslint-disable-next-line @typescript-eslint/no-floating-promises - this._sendEnvelope(envelope); + this.sendEnvelope(envelope); } } diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 583e329b4beb..2adec97d6b93 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -16,7 +16,6 @@ import type { FeedbackEvent, Integration, IntegrationClass, - MetricBucketItem, Outcome, ParameterizedString, SdkMetadata, @@ -52,7 +51,6 @@ import { createEventEnvelope, createSessionEnvelope } from './envelope'; import type { IntegrationIndex } from './integration'; import { afterSetupIntegrations } from './integration'; import { setupIntegration, setupIntegrations } from './integration'; -import { createMetricEnvelope } from './metrics/envelope'; import type { Scope } from './scope'; import { updateSession } from './session'; import { getDynamicSamplingContextFromClient } from './tracing/dynamicSamplingContext'; @@ -377,7 +375,7 @@ export abstract class BaseClient implements Client { env = addItemToEnvelope(env, createAttachmentEnvelopeItem(attachment)); } - const promise = this._sendEnvelope(env); + const promise = this.sendEnvelope(env); if (promise) { promise.then(sendResponse => this.emit('afterSendEvent', event, sendResponse), null); } @@ -389,9 +387,9 @@ export abstract class BaseClient implements Client { public sendSession(session: Session | SessionAggregates): void { const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel); - // _sendEnvelope should not throw + // sendEnvelope should not throw // eslint-disable-next-line @typescript-eslint/no-floating-promises - this._sendEnvelope(env); + this.sendEnvelope(env); } /** @@ -415,23 +413,6 @@ export abstract class BaseClient implements Client { } } - /** - * @inheritDoc - */ - public captureAggregateMetrics(metricBucketItems: Array): void { - DEBUG_BUILD && logger.log(`Flushing aggregated metrics, number of metrics: ${metricBucketItems.length}`); - const metricsEnvelope = createMetricEnvelope( - metricBucketItems, - this._dsn, - this._options._metadata, - this._options.tunnel, - ); - - // _sendEnvelope should not throw - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this._sendEnvelope(metricsEnvelope); - } - // Keep on() & emit() signatures in sync with types' client.ts interface /* eslint-disable @typescript-eslint/unified-signatures */ @@ -540,6 +521,21 @@ export abstract class BaseClient implements Client { } } + /** + * @inheritdoc + */ + public sendEnvelope(envelope: Envelope): PromiseLike | void { + this.emit('beforeEnvelope', envelope); + + if (this._isEnabled() && this._transport) { + return this._transport.send(envelope).then(null, reason => { + DEBUG_BUILD && logger.error('Error while sending event:', reason); + }); + } else { + DEBUG_BUILD && logger.error('Transport disabled'); + } + } + /* eslint-enable @typescript-eslint/unified-signatures */ /** Setup integrations for this client. */ @@ -823,21 +819,6 @@ export abstract class BaseClient implements Client { ); } - /** - * @inheritdoc - */ - protected _sendEnvelope(envelope: Envelope): PromiseLike | void { - this.emit('beforeEnvelope', envelope); - - if (this._isEnabled() && this._transport) { - return this._transport.send(envelope).then(null, reason => { - DEBUG_BUILD && logger.error('Error while sending event:', reason); - }); - } else { - DEBUG_BUILD && logger.error('Transport disabled'); - } - } - /** * Clears outcomes on this client and returns them. */ diff --git a/packages/core/src/metrics/aggregator.ts b/packages/core/src/metrics/aggregator.ts index 24caf9de6610..68306e8ba471 100644 --- a/packages/core/src/metrics/aggregator.ts +++ b/packages/core/src/metrics/aggregator.ts @@ -1,16 +1,16 @@ import type { - Client, ClientOptions, MeasurementUnit, MetricsAggregator as MetricsAggregatorBase, Primitive, } from '@sentry/types'; import { timestampInSeconds } from '@sentry/utils'; +import type { BaseClient } from '../baseclient'; import { DEFAULT_FLUSH_INTERVAL, MAX_WEIGHT, NAME_AND_TAG_KEY_NORMALIZATION_REGEX, SET_METRIC_TYPE } from './constants'; import { METRIC_MAP } from './instance'; import { updateMetricSummaryOnActiveSpan } from './metric-summary'; import type { MetricBucket, MetricType } from './types'; -import { getBucketKey, sanitizeTags } from './utils'; +import { captureAggregateMetrics, getBucketKey, sanitizeTags } from './utils'; /** * A metrics aggregator that aggregates metrics in memory and flushes them periodically. @@ -39,7 +39,7 @@ export class MetricsAggregator implements MetricsAggregatorBase { // Force flush is used on either shutdown, flush() or when we exceed the max weight. private _forceFlush: boolean; - public constructor(private readonly _client: Client) { + public constructor(private readonly _client: BaseClient) { this._buckets = new Map(); this._bucketsTotalWeight = 0; this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL); @@ -166,7 +166,7 @@ export class MetricsAggregator implements MetricsAggregatorBase { // 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); - this._client.captureAggregateMetrics(buckets); + captureAggregateMetrics(this._client, buckets); } } } diff --git a/packages/core/src/metrics/browser-aggregator.ts b/packages/core/src/metrics/browser-aggregator.ts index 9d24be11a843..f1feac8c1998 100644 --- a/packages/core/src/metrics/browser-aggregator.ts +++ b/packages/core/src/metrics/browser-aggregator.ts @@ -1,10 +1,11 @@ -import type { Client, ClientOptions, MeasurementUnit, MetricsAggregator, Primitive } from '@sentry/types'; +import type { ClientOptions, MeasurementUnit, MetricsAggregator, Primitive } from '@sentry/types'; import { timestampInSeconds } from '@sentry/utils'; +import type { BaseClient } from '../baseclient'; import { DEFAULT_BROWSER_FLUSH_INTERVAL, NAME_AND_TAG_KEY_NORMALIZATION_REGEX, SET_METRIC_TYPE } from './constants'; import { METRIC_MAP } from './instance'; import { updateMetricSummaryOnActiveSpan } from './metric-summary'; import type { MetricBucket, MetricType } from './types'; -import { getBucketKey, sanitizeTags } from './utils'; +import { captureAggregateMetrics, getBucketKey, sanitizeTags } from './utils'; /** * A simple metrics aggregator that aggregates metrics in memory and flushes them periodically. @@ -19,7 +20,7 @@ export class BrowserMetricsAggregator implements MetricsAggregator { private _buckets: MetricBucket; private readonly _interval: ReturnType; - public constructor(private readonly _client: Client) { + public constructor(private readonly _client: BaseClient) { this._buckets = new Map(); this._interval = setInterval(() => this.flush(), DEFAULT_BROWSER_FLUSH_INTERVAL); } @@ -80,7 +81,7 @@ export class BrowserMetricsAggregator implements MetricsAggregator { // TODO(@anonrig): Use Object.values() when we support ES6+ const metricBuckets = Array.from(this._buckets).map(([, bucketItem]) => bucketItem); - this._client.captureAggregateMetrics(metricBuckets); + captureAggregateMetrics(this._client, metricBuckets); this._buckets.clear(); } diff --git a/packages/core/src/metrics/utils.ts b/packages/core/src/metrics/utils.ts index 7b1cf96a8462..a8601293b136 100644 --- a/packages/core/src/metrics/utils.ts +++ b/packages/core/src/metrics/utils.ts @@ -1,8 +1,29 @@ -import type { MeasurementUnit, MetricBucketItem, Primitive } from '@sentry/types'; +import type { ClientOptions, MeasurementUnit, MetricBucketItem, Primitive } from '@sentry/types'; import { dropUndefinedKeys } from '@sentry/utils'; +import type { BaseClient } from '../baseclient'; import { NAME_AND_TAG_KEY_NORMALIZATION_REGEX, TAG_VALUE_NORMALIZATION_REGEX } from './constants'; +import { createMetricEnvelope } from './envelope'; import type { MetricType } from './types'; +/** + * + */ +export function captureAggregateMetrics( + client: BaseClient, + metricBucketItems: Array, +): void { + // DEBUG_BUILD && 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); +} + /** * Generate bucket key from metric properties. */ diff --git a/packages/core/src/server-runtime-client.ts b/packages/core/src/server-runtime-client.ts index ecf0fc8ae2b6..682e58e80355 100644 --- a/packages/core/src/server-runtime-client.ts +++ b/packages/core/src/server-runtime-client.ts @@ -199,9 +199,9 @@ export class ServerRuntimeClient< DEBUG_BUILD && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status); - // _sendEnvelope should not throw + // sendEnvelope should not throw // eslint-disable-next-line @typescript-eslint/no-floating-promises - this._sendEnvelope(envelope); + this.sendEnvelope(envelope); return id; } diff --git a/packages/core/test/lib/metrics/aggregator.test.ts b/packages/core/test/lib/metrics/aggregator.test.ts index 32396cfedcc2..2a471d12bb04 100644 --- a/packages/core/test/lib/metrics/aggregator.test.ts +++ b/packages/core/test/lib/metrics/aggregator.test.ts @@ -81,7 +81,7 @@ describe('MetricsAggregator', () => { describe('close', () => { test('should flush immediately', () => { - const capture = jest.spyOn(testClient, 'captureAggregateMetrics'); + const capture = jest.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); aggregator.add('c', 'requests', 1); aggregator.close(); @@ -89,37 +89,18 @@ describe('MetricsAggregator', () => { expect(clearInterval).toHaveBeenCalled(); expect(capture).toBeCalled(); expect(capture).toBeCalledTimes(1); - expect(capture).toBeCalledWith([ - { - metric: { _value: 1 }, - metricType: 'c', - name: 'requests', - tags: {}, - timestamp: expect.any(Number), - unit: 'none', - }, - ]); }); }); describe('flush', () => { test('should flush immediately', () => { - const capture = jest.spyOn(testClient, 'captureAggregateMetrics'); + 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); - expect(capture).toBeCalledWith([ - { - metric: { _value: 1 }, - metricType: 'c', - name: 'requests', - tags: {}, - timestamp: expect.any(Number), - unit: 'none', - }, - ]); + capture.mockReset(); aggregator.close(); // It should clear the interval. @@ -130,7 +111,7 @@ describe('MetricsAggregator', () => { }); test('should not capture if empty', () => { - const capture = jest.spyOn(testClient, 'captureAggregateMetrics'); + const capture = jest.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); aggregator.add('c', 'requests', 1); aggregator.flush(); @@ -143,7 +124,7 @@ describe('MetricsAggregator', () => { describe('add', () => { test('it should respect the max weight and flush if exceeded', () => { - const capture = jest.spyOn(testClient, 'captureAggregateMetrics'); + const capture = jest.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); for (let i = 0; i < MAX_WEIGHT; i++) { diff --git a/packages/core/test/lib/serverruntimeclient.test.ts b/packages/core/test/lib/serverruntimeclient.test.ts index 4ffed6c68f81..4d5cc8f33ce4 100644 --- a/packages/core/test/lib/serverruntimeclient.test.ts +++ b/packages/core/test/lib/serverruntimeclient.test.ts @@ -78,8 +78,7 @@ describe('ServerRuntimeClient', () => { }); client = new ServerRuntimeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); const id = client.captureCheckIn( { monitorSlug: 'foo', status: 'in_progress' }, @@ -145,8 +144,7 @@ describe('ServerRuntimeClient', () => { const options = getDefaultClientOptions({ dsn: PUBLIC_DSN, serverName: 'bar', enabled: false }); client = new ServerRuntimeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); client.captureCheckIn({ monitorSlug: 'foo', status: 'in_progress' }); diff --git a/packages/node-experimental/test/sdk/client.test.ts b/packages/node-experimental/test/sdk/client.test.ts index f9e69b0b7233..6e867761c692 100644 --- a/packages/node-experimental/test/sdk/client.test.ts +++ b/packages/node-experimental/test/sdk/client.test.ts @@ -393,8 +393,7 @@ describe('NodeClient', () => { }); const client = new NodeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); const id = client.captureCheckIn( { monitorSlug: 'foo', status: 'in_progress' }, @@ -464,8 +463,7 @@ describe('NodeClient', () => { }); const client = new NodeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); const id = client.captureCheckIn({ monitorSlug: 'heartbeat-monitor', status: 'ok' }); @@ -491,8 +489,7 @@ describe('NodeClient', () => { const options = getDefaultNodeClientOptions({ serverName: 'bar', enabled: false }); const client = new NodeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); client.captureCheckIn({ monitorSlug: 'foo', status: 'in_progress' }); diff --git a/packages/node/test/client.test.ts b/packages/node/test/client.test.ts index 64c1251d1ce2..b80c3eced700 100644 --- a/packages/node/test/client.test.ts +++ b/packages/node/test/client.test.ts @@ -310,8 +310,7 @@ describe('NodeClient', () => { }); client = new NodeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); const id = client.captureCheckIn( { monitorSlug: 'foo', status: 'in_progress' }, @@ -382,8 +381,7 @@ describe('NodeClient', () => { }); client = new NodeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); const id = client.captureCheckIn({ monitorSlug: 'heartbeat-monitor', status: 'ok' }); @@ -409,8 +407,7 @@ describe('NodeClient', () => { const options = getDefaultNodeClientOptions({ dsn: PUBLIC_DSN, serverName: 'bar', enabled: false }); client = new NodeClient(options); - // @ts-expect-error accessing private method - const sendEnvelopeSpy = jest.spyOn(client, '_sendEnvelope'); + const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); client.captureCheckIn({ monitorSlug: 'foo', status: 'in_progress' }); diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index 62956f0c00d0..8566352f03ce 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -180,13 +180,6 @@ export interface Client { */ recordDroppedEvent(reason: EventDropReason, dataCategory: DataCategory, event?: Event): void; - /** - * Captures serialized metrics and sends them to Sentry. - * - * @experimental This API is experimental and might experience breaking changes - */ - captureAggregateMetrics(metricBucketItems: Array): void; - // HOOKS // TODO(v8): Make the hooks non-optional. /* eslint-disable @typescript-eslint/unified-signatures */ From 896630ead264677110e2c3db33b62db10883d66e Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 22 Feb 2024 09:13:54 -0400 Subject: [PATCH 2/3] minor --- packages/core/src/metrics/utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/metrics/utils.ts b/packages/core/src/metrics/utils.ts index a8601293b136..014c76805479 100644 --- a/packages/core/src/metrics/utils.ts +++ b/packages/core/src/metrics/utils.ts @@ -1,18 +1,18 @@ import type { ClientOptions, MeasurementUnit, MetricBucketItem, Primitive } from '@sentry/types'; -import { dropUndefinedKeys } from '@sentry/utils'; +import { dropUndefinedKeys, logger } from '@sentry/utils'; import type { BaseClient } from '../baseclient'; import { NAME_AND_TAG_KEY_NORMALIZATION_REGEX, TAG_VALUE_NORMALIZATION_REGEX } from './constants'; import { createMetricEnvelope } from './envelope'; import type { MetricType } from './types'; /** - * + * Captures aggregated metrics to the supplied client. */ export function captureAggregateMetrics( client: BaseClient, metricBucketItems: Array, ): void { - // DEBUG_BUILD && logger.log(`Flushing aggregated metrics, number of metrics: ${metricBucketItems.length}`); + logger.log(`Flushing aggregated metrics, number of metrics: ${metricBucketItems.length}`); const dsn = client.getDsn(); const metadata = client.getSdkMetadata(); const tunnel = client.getOptions().tunnel; From e8d92fae388ce1e91f57fc95e348aa959055f3c9 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 22 Feb 2024 10:11:28 -0400 Subject: [PATCH 3/3] Fix lint and circular dep --- packages/core/src/metrics/aggregator.ts | 3 +- .../core/src/metrics/browser-aggregator.ts | 3 +- packages/core/src/metrics/envelope.ts | 31 +++++++++++++++++-- packages/core/src/metrics/utils.ts | 25 ++------------- packages/types/src/client.ts | 1 - 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/packages/core/src/metrics/aggregator.ts b/packages/core/src/metrics/aggregator.ts index 68306e8ba471..5f0337e804f3 100644 --- a/packages/core/src/metrics/aggregator.ts +++ b/packages/core/src/metrics/aggregator.ts @@ -7,10 +7,11 @@ import type { import { timestampInSeconds } from '@sentry/utils'; import type { BaseClient } from '../baseclient'; import { DEFAULT_FLUSH_INTERVAL, MAX_WEIGHT, NAME_AND_TAG_KEY_NORMALIZATION_REGEX, SET_METRIC_TYPE } from './constants'; +import { captureAggregateMetrics } from './envelope'; import { METRIC_MAP } from './instance'; import { updateMetricSummaryOnActiveSpan } from './metric-summary'; import type { MetricBucket, MetricType } from './types'; -import { captureAggregateMetrics, getBucketKey, sanitizeTags } from './utils'; +import { getBucketKey, sanitizeTags } from './utils'; /** * A metrics aggregator that aggregates metrics in memory and flushes them periodically. diff --git a/packages/core/src/metrics/browser-aggregator.ts b/packages/core/src/metrics/browser-aggregator.ts index f1feac8c1998..d19aa441aef3 100644 --- a/packages/core/src/metrics/browser-aggregator.ts +++ b/packages/core/src/metrics/browser-aggregator.ts @@ -2,10 +2,11 @@ import type { ClientOptions, MeasurementUnit, MetricsAggregator, Primitive } fro import { timestampInSeconds } from '@sentry/utils'; import type { BaseClient } from '../baseclient'; import { DEFAULT_BROWSER_FLUSH_INTERVAL, NAME_AND_TAG_KEY_NORMALIZATION_REGEX, SET_METRIC_TYPE } from './constants'; +import { captureAggregateMetrics } from './envelope'; import { METRIC_MAP } from './instance'; import { updateMetricSummaryOnActiveSpan } from './metric-summary'; import type { MetricBucket, MetricType } from './types'; -import { captureAggregateMetrics, getBucketKey, sanitizeTags } from './utils'; +import { getBucketKey, sanitizeTags } from './utils'; /** * A simple metrics aggregator that aggregates metrics in memory and flushes them periodically. diff --git a/packages/core/src/metrics/envelope.ts b/packages/core/src/metrics/envelope.ts index 95622e109740..47ccc2740834 100644 --- a/packages/core/src/metrics/envelope.ts +++ b/packages/core/src/metrics/envelope.ts @@ -1,7 +1,34 @@ -import type { DsnComponents, MetricBucketItem, SdkMetadata, StatsdEnvelope, StatsdItem } from '@sentry/types'; -import { createEnvelope, dsnToString } from '@sentry/utils'; +import type { + ClientOptions, + DsnComponents, + MetricBucketItem, + SdkMetadata, + StatsdEnvelope, + StatsdItem, +} from '@sentry/types'; +import { createEnvelope, dsnToString, logger } from '@sentry/utils'; +import type { BaseClient } from '../baseclient'; import { serializeMetricBuckets } from './utils'; +/** + * Captures aggregated metrics to the supplied client. + */ +export function captureAggregateMetrics( + client: BaseClient, + 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. */ diff --git a/packages/core/src/metrics/utils.ts b/packages/core/src/metrics/utils.ts index 014c76805479..7b1cf96a8462 100644 --- a/packages/core/src/metrics/utils.ts +++ b/packages/core/src/metrics/utils.ts @@ -1,29 +1,8 @@ -import type { ClientOptions, MeasurementUnit, MetricBucketItem, Primitive } from '@sentry/types'; -import { dropUndefinedKeys, logger } from '@sentry/utils'; -import type { BaseClient } from '../baseclient'; +import type { MeasurementUnit, MetricBucketItem, Primitive } from '@sentry/types'; +import { dropUndefinedKeys } from '@sentry/utils'; import { NAME_AND_TAG_KEY_NORMALIZATION_REGEX, TAG_VALUE_NORMALIZATION_REGEX } from './constants'; -import { createMetricEnvelope } from './envelope'; import type { MetricType } from './types'; -/** - * Captures aggregated metrics to the supplied client. - */ -export function captureAggregateMetrics( - client: BaseClient, - 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); -} - /** * Generate bucket key from metric properties. */ diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index 8566352f03ce..fb8fb056cc7c 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -8,7 +8,6 @@ import type { Event, EventHint } from './event'; import type { EventProcessor } from './eventprocessor'; import type { FeedbackEvent } from './feedback'; import type { Integration, IntegrationClass } from './integration'; -import type { MetricBucketItem } from './metrics'; import type { ClientOptions } from './options'; import type { ParameterizedString } from './parameterize'; import type { Scope } from './scope';