From eae5a24a3d6c7ef94f95c50b7c2e4c91b9540938 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 29 Nov 2023 10:11:02 -0500 Subject: [PATCH 1/2] feat(metrics): Add interfaces for metrics --- packages/core/src/metrics/index.ts | 43 ++++++++++++++++++++++++++++++ packages/types/src/envelope.ts | 2 +- packages/types/src/index.ts | 3 +++ packages/types/src/metrics.ts | 32 ++++++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/metrics/index.ts create mode 100644 packages/types/src/metrics.ts diff --git a/packages/core/src/metrics/index.ts b/packages/core/src/metrics/index.ts new file mode 100644 index 000000000000..c55a02e3ec7c --- /dev/null +++ b/packages/core/src/metrics/index.ts @@ -0,0 +1,43 @@ +import type { DsnComponents, DynamicSamplingContext, SdkMetadata, StatsdEnvelope, StatsdItem } from '@sentry/types' +import { createEnvelope, dropUndefinedKeys, dsnToString } from '@sentry/utils'; + +/** + * Create envelope from a metric aggregate. + */ +export function createMetricEnvelope( + // TODO(abhi): Add type for this + metricAggregate: string, + dynamicSamplingContext?: Partial, + metadata?: SdkMetadata, + tunnel?: string, + dsn?: DsnComponents, +): 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); + } + + if (dynamicSamplingContext) { + headers.trace = dropUndefinedKeys(dynamicSamplingContext) as DynamicSamplingContext; + } + + const item = createMetricEnvelopeItem(metricAggregate); + return createEnvelope(headers, [item]); +} + +function createMetricEnvelopeItem(metricAggregate: string): StatsdItem { + const metricHeaders: StatsdItem[0] = { + type: 'statsd', + }; + return [metricHeaders, metricAggregate]; +} diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index d479b9f8a4e9..20fc00392168 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -109,5 +109,5 @@ export type ReplayEnvelope = [ReplayEnvelopeHeaders, [ReplayEventItem, ReplayRec export type CheckInEnvelope = BaseEnvelope; export type StatsdEnvelope = BaseEnvelope; -export type Envelope = EventEnvelope | SessionEnvelope | ClientReportEnvelope | ReplayEnvelope | CheckInEnvelope; +export type Envelope = EventEnvelope | SessionEnvelope | ClientReportEnvelope | ReplayEnvelope | CheckInEnvelope | StatsdEnvelope; export type EnvelopeItem = Envelope[1][number]; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 627879493365..615bf71ff785 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -42,6 +42,8 @@ export type { UserFeedbackItem, CheckInItem, CheckInEnvelope, + StatsdItem, + StatsdEnvelope, } from './envelope'; export type { ExtendedError } from './error'; export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent } from './event'; @@ -136,3 +138,4 @@ export type { export type { BrowserClientReplayOptions, BrowserClientProfilingOptions } from './browseroptions'; export type { CheckIn, MonitorConfig, FinishedCheckIn, InProgressCheckIn, SerializedCheckIn } from './checkin'; +export type { Metric, CounterMetric, GaugeMetric, DistributionMetric, SetMetric } from './metrics'; diff --git a/packages/types/src/metrics.ts b/packages/types/src/metrics.ts new file mode 100644 index 000000000000..f09ea946cf41 --- /dev/null +++ b/packages/types/src/metrics.ts @@ -0,0 +1,32 @@ +import type { Primitive } from './misc'; +import type { MeasurementUnit } from './measurement'; + +export interface BaseMetric { + name: string; + timestamp: number; + unit: MeasurementUnit; + tags?: { [key: string]: Primitive }; +} + +export interface CounterMetric extends BaseMetric { + value: number; +} + +export interface GaugeMetric extends BaseMetric { + value: number; + first: number; + min: number; + max: number; + sum: number; + count: number; +} + +export interface DistributionMetric extends BaseMetric { + value: number[]; +} + +export interface SetMetric extends BaseMetric { + value: Set; +} + +export type Metric = CounterMetric | GaugeMetric | DistributionMetric | SetMetric; From 477e2a419ccb8e55fde412e412be0fe29b372050 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 29 Nov 2023 10:47:40 -0500 Subject: [PATCH 2/2] make unit optional --- packages/core/src/metrics/index.ts | 2 +- packages/types/src/envelope.ts | 8 +++++++- packages/types/src/metrics.ts | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/core/src/metrics/index.ts b/packages/core/src/metrics/index.ts index c55a02e3ec7c..3cfeae37e03f 100644 --- a/packages/core/src/metrics/index.ts +++ b/packages/core/src/metrics/index.ts @@ -1,4 +1,4 @@ -import type { DsnComponents, DynamicSamplingContext, SdkMetadata, StatsdEnvelope, StatsdItem } from '@sentry/types' +import type { DsnComponents, DynamicSamplingContext, SdkMetadata, StatsdEnvelope, StatsdItem } from '@sentry/types'; import { createEnvelope, dropUndefinedKeys, dsnToString } from '@sentry/utils'; /** diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index 20fc00392168..fbe593dd21f9 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -109,5 +109,11 @@ export type ReplayEnvelope = [ReplayEnvelopeHeaders, [ReplayEventItem, ReplayRec export type CheckInEnvelope = BaseEnvelope; export type StatsdEnvelope = BaseEnvelope; -export type Envelope = EventEnvelope | SessionEnvelope | ClientReportEnvelope | ReplayEnvelope | CheckInEnvelope | StatsdEnvelope; +export type Envelope = + | EventEnvelope + | SessionEnvelope + | ClientReportEnvelope + | ReplayEnvelope + | CheckInEnvelope + | StatsdEnvelope; export type EnvelopeItem = Envelope[1][number]; diff --git a/packages/types/src/metrics.ts b/packages/types/src/metrics.ts index f09ea946cf41..b55096950b2f 100644 --- a/packages/types/src/metrics.ts +++ b/packages/types/src/metrics.ts @@ -1,10 +1,10 @@ -import type { Primitive } from './misc'; import type { MeasurementUnit } from './measurement'; +import type { Primitive } from './misc'; export interface BaseMetric { name: string; timestamp: number; - unit: MeasurementUnit; + unit?: MeasurementUnit; tags?: { [key: string]: Primitive }; }