Skip to content

Commit f1cd311

Browse files
committed
refactor client logic
1 parent 5d95eca commit f1cd311

File tree

6 files changed

+49
-17
lines changed

6 files changed

+49
-17
lines changed

packages/core/src/baseclient.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import { createEventEnvelope, createSessionEnvelope } from './envelope';
4949
import { getCurrentHub } from './hub';
5050
import type { IntegrationIndex } from './integration';
5151
import { setupIntegration, setupIntegrations } from './integration';
52+
import { createMetricEnvelope } from './metrics/envelope';
5253
import type { MetricsAggregator } from './metrics/types';
5354
import type { Scope } from './scope';
5455
import { updateSession } from './session';
@@ -289,6 +290,9 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
289290
public close(timeout?: number): PromiseLike<boolean> {
290291
return this.flush(timeout).then(result => {
291292
this.getOptions().enabled = false;
293+
if (this.metricsAggregator) {
294+
this.metricsAggregator.close();
295+
}
292296
return result;
293297
});
294298
}
@@ -394,6 +398,19 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
394398
}
395399
}
396400

401+
/**
402+
* @inheritDoc
403+
*/
404+
public captureSerializedMetrics(serializedMetrics: string): void {
405+
const metricsEnvelope = createMetricEnvelope(
406+
serializedMetrics,
407+
this._dsn,
408+
this._options._metadata,
409+
this._options.tunnel,
410+
);
411+
void this._sendEnvelope(metricsEnvelope);
412+
}
413+
397414
// Keep on() & emit() signatures in sync with types' client.ts interface
398415
/* eslint-disable @typescript-eslint/unified-signatures */
399416

packages/core/src/metrics/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ export const DISTRIBUTION_METRIC_TYPE = 'd';
55

66
export const NAME_AND_TAG_KEY_REGEX = /[^a-zA-Z0-9_/.-]+"/g;
77
export const TAG_VALUE_REGEX = /[^\w\d_:/@.{}[\]$-]+/g;
8+
9+
export const DEFAULT_FLUSH_INTERVAL = 5000;

packages/core/src/metrics/envelope.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { createEnvelope, dsnToString } from '@sentry/utils';
66
*/
77
export function createMetricEnvelope(
88
metricAggregate: string,
9+
dsn?: DsnComponents,
910
metadata?: SdkMetadata,
1011
tunnel?: string,
11-
dsn?: DsnComponents,
1212
): StatsdEnvelope {
1313
const headers: StatsdEnvelope[0] = {
1414
sent_at: new Date().toISOString(),

packages/core/src/metrics/simpleaggregator.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import type { ClientOptions, MeasurementUnit, Primitive } from '@sentry/types';
1+
import type { Client, ClientOptions, MeasurementUnit, Primitive } from '@sentry/types';
22
import { timestampInSeconds } from '@sentry/utils';
3-
import type { BaseClient } from '../baseclient';
4-
import { NAME_AND_TAG_KEY_REGEX, TAG_VALUE_REGEX } from './constants';
5-
import { createMetricEnvelope } from './envelope';
3+
import { DEFAULT_FLUSH_INTERVAL, NAME_AND_TAG_KEY_REGEX, TAG_VALUE_REGEX } from './constants';
64
import type { Metric } from './instance';
75
import { METRIC_MAP } from './instance';
86
import type { MetricType, MetricsAggregator } from './types';
@@ -22,14 +20,17 @@ type SimpleMetricBucket = Map<
2220

2321
/**
2422
* A simple metrics aggregator that aggregates metrics in memory and flushes them periodically.
23+
* Default flush interval is 5 seconds.
2524
*
2625
* @experimental This API is experimental and might change in the future.
2726
*/
2827
export class SimpleMetricsAggregator implements MetricsAggregator {
2928
private _buckets: SimpleMetricBucket;
29+
private readonly _interval: ReturnType<typeof setInterval>;
3030

31-
public constructor(private readonly _client: BaseClient<ClientOptions>) {
31+
public constructor(private readonly _client: Client<ClientOptions>) {
3232
this._buckets = new Map();
33+
this._interval = setInterval(() => this.flush(), DEFAULT_FLUSH_INTERVAL);
3334
}
3435

3536
/**
@@ -71,18 +72,18 @@ export class SimpleMetricsAggregator implements MetricsAggregator {
7172
return;
7273
}
7374

74-
// Allow of this logic should be in the client, but we want to
75-
const metrics = serializeBuckets(this._buckets);
76-
const sdkMetadata = this._client.getSdkMetadata && this._client.getSdkMetadata();
77-
const metricsEnvelope = createMetricEnvelope(
78-
metrics,
79-
sdkMetadata,
80-
this._client.getOptions().tunnel,
81-
this._client.getDsn(),
82-
);
75+
if (this._client.captureSerializedMetrics) {
76+
this._client.captureSerializedMetrics(serializeBuckets(this._buckets));
77+
}
78+
this._buckets.clear();
79+
}
8380

84-
// TODO(abhi): Remove this hack - only here until we decide on final API for metrics on client
85-
void this._client['_sendEnvelope'](metricsEnvelope);
81+
/**
82+
* @inheritDoc
83+
*/
84+
public close(): void {
85+
clearInterval(this._interval);
86+
this.flush();
8687
this._buckets.clear();
8788
}
8889
}

packages/core/src/metrics/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ export interface MetricsAggregator {
2828
* Flushes the current metrics to the transport via the transport.
2929
*/
3030
flush(): void;
31+
32+
/**
33+
* Shuts down metrics aggregator and clears all metrics.
34+
*/
35+
close(): void;
3136
}

packages/types/src/client.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ export interface Client<O extends ClientOptions = ClientOptions> {
179179
*/
180180
recordDroppedEvent(reason: EventDropReason, dataCategory: DataCategory, event?: Event): void;
181181

182+
/**
183+
* Captures serialized metrics and sends them to Sentry.
184+
*
185+
* @experimental This API is experimental and might experience breaking changes
186+
*/
187+
captureSerializedMetrics?(serializedMetrics: string): void;
188+
182189
// HOOKS
183190
// TODO(v8): Make the hooks non-optional.
184191
/* eslint-disable @typescript-eslint/unified-signatures */

0 commit comments

Comments
 (0)