Skip to content

Commit 9d87fba

Browse files
committed
ref(core): Use serializeAttributes for metric attribute serialization
1 parent aaa0fea commit 9d87fba

File tree

4 files changed

+11
-129
lines changed

4 files changed

+11
-129
lines changed

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ export type {
449449
MetricType,
450450
SerializedMetric,
451451
SerializedMetricContainer,
452+
// eslint-disable-next-line deprecation/deprecation
452453
SerializedMetricAttributeValue,
453454
} from './types-hoist/metric';
454455
export type { TimedEvent } from './types-hoist/timedEvent';

packages/core/src/metrics/internal.ts

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import { serializeAttributes } from '../attributes';
12
import { getGlobalSingleton } from '../carrier';
23
import type { Client } from '../client';
34
import { getClient, getCurrentScope, getGlobalScope, getIsolationScope } from '../currentScopes';
45
import { DEBUG_BUILD } from '../debug-build';
56
import type { Scope, ScopeData } from '../scope';
67
import type { Integration } from '../types-hoist/integration';
7-
import type { Metric, SerializedMetric, SerializedMetricAttributeValue } from '../types-hoist/metric';
8+
import type { Metric, SerializedMetric } from '../types-hoist/metric';
89
import { mergeScopeData } from '../utils/applyScopeDataToEvent';
910
import { debug } from '../utils/debug-logger';
1011
import { _getSpanForScope } from '../utils/spanOnScope';
@@ -14,50 +15,6 @@ import { createMetricEnvelope } from './envelope';
1415

1516
const MAX_METRIC_BUFFER_SIZE = 1000;
1617

17-
/**
18-
* Converts a metric attribute to a serialized metric attribute.
19-
*
20-
* @param value - The value of the metric attribute.
21-
* @returns The serialized metric attribute.
22-
*/
23-
export function metricAttributeToSerializedMetricAttribute(value: unknown): SerializedMetricAttributeValue {
24-
switch (typeof value) {
25-
case 'number':
26-
if (Number.isInteger(value)) {
27-
return {
28-
value,
29-
type: 'integer',
30-
};
31-
}
32-
return {
33-
value,
34-
type: 'double',
35-
};
36-
case 'boolean':
37-
return {
38-
value,
39-
type: 'boolean',
40-
};
41-
case 'string':
42-
return {
43-
value,
44-
type: 'string',
45-
};
46-
default: {
47-
let stringValue = '';
48-
try {
49-
stringValue = JSON.stringify(value) ?? '';
50-
} catch {
51-
// Do nothing
52-
}
53-
return {
54-
value: stringValue,
55-
type: 'string',
56-
};
57-
}
58-
}
59-
}
60-
6118
/**
6219
* Sets a metric attribute if the value exists and the attribute key is not already present.
6320
*
@@ -169,14 +126,6 @@ function _enrichMetricAttributes(beforeMetric: Metric, client: Client, currentSc
169126
* Creates a serialized metric ready to be sent to Sentry.
170127
*/
171128
function _buildSerializedMetric(metric: Metric, client: Client, currentScope: Scope): SerializedMetric {
172-
// Serialize attributes
173-
const serializedAttributes: Record<string, SerializedMetricAttributeValue> = {};
174-
for (const key in metric.attributes) {
175-
if (metric.attributes[key] !== undefined) {
176-
serializedAttributes[key] = metricAttributeToSerializedMetricAttribute(metric.attributes[key]);
177-
}
178-
}
179-
180129
// Get trace context
181130
const [, traceContext] = _getTraceInfoFromScope(client, currentScope);
182131
const span = _getSpanForScope(currentScope);
@@ -191,7 +140,7 @@ function _buildSerializedMetric(metric: Metric, client: Client, currentScope: Sc
191140
type: metric.type,
192141
unit: metric.unit,
193142
value: metric.value,
194-
attributes: serializedAttributes,
143+
attributes: serializeAttributes(metric.attributes, true),
195144
};
196145
}
197146

packages/core/src/types-hoist/metric.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Attributes, TypedAttributeValue } from '../attributes';
2+
13
export type MetricType = 'counter' | 'gauge' | 'distribution';
24

35
export interface Metric {
@@ -27,11 +29,10 @@ export interface Metric {
2729
attributes?: Record<string, unknown>;
2830
}
2931

30-
export type SerializedMetricAttributeValue =
31-
| { value: string; type: 'string' }
32-
| { value: number; type: 'integer' }
33-
| { value: number; type: 'double' }
34-
| { value: boolean; type: 'boolean' };
32+
/**
33+
* @deprecated this was not intended for public consumption
34+
*/
35+
export type SerializedMetricAttributeValue = TypedAttributeValue;
3536

3637
export interface SerializedMetric {
3738
/**
@@ -72,7 +73,7 @@ export interface SerializedMetric {
7273
/**
7374
* Arbitrary structured data that stores information about the metric.
7475
*/
75-
attributes?: Record<string, SerializedMetricAttributeValue>;
76+
attributes?: Attributes;
7677
}
7778

7879
export type SerializedMetricContainer = {

packages/core/test/lib/metrics/internal.test.ts

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,82 +4,13 @@ import {
44
_INTERNAL_captureMetric,
55
_INTERNAL_flushMetricsBuffer,
66
_INTERNAL_getMetricBuffer,
7-
metricAttributeToSerializedMetricAttribute,
87
} from '../../../src/metrics/internal';
98
import type { Metric } from '../../../src/types-hoist/metric';
109
import * as loggerModule from '../../../src/utils/debug-logger';
1110
import { getDefaultTestClientOptions, TestClient } from '../../mocks/client';
1211

1312
const PUBLIC_DSN = 'https://username@domain/123';
1413

15-
describe('metricAttributeToSerializedMetricAttribute', () => {
16-
it('serializes integer values', () => {
17-
const result = metricAttributeToSerializedMetricAttribute(42);
18-
expect(result).toEqual({
19-
value: 42,
20-
type: 'integer',
21-
});
22-
});
23-
24-
it('serializes double values', () => {
25-
const result = metricAttributeToSerializedMetricAttribute(42.34);
26-
expect(result).toEqual({
27-
value: 42.34,
28-
type: 'double',
29-
});
30-
});
31-
32-
it('serializes boolean values', () => {
33-
const result = metricAttributeToSerializedMetricAttribute(true);
34-
expect(result).toEqual({
35-
value: true,
36-
type: 'boolean',
37-
});
38-
});
39-
40-
it('serializes string values', () => {
41-
const result = metricAttributeToSerializedMetricAttribute('endpoint');
42-
expect(result).toEqual({
43-
value: 'endpoint',
44-
type: 'string',
45-
});
46-
});
47-
48-
it('serializes object values as JSON strings', () => {
49-
const obj = { name: 'John', age: 30 };
50-
const result = metricAttributeToSerializedMetricAttribute(obj);
51-
expect(result).toEqual({
52-
value: JSON.stringify(obj),
53-
type: 'string',
54-
});
55-
});
56-
57-
it('serializes array values as JSON strings', () => {
58-
const array = [1, 2, 3, 'test'];
59-
const result = metricAttributeToSerializedMetricAttribute(array);
60-
expect(result).toEqual({
61-
value: JSON.stringify(array),
62-
type: 'string',
63-
});
64-
});
65-
66-
it('serializes undefined values as empty strings', () => {
67-
const result = metricAttributeToSerializedMetricAttribute(undefined);
68-
expect(result).toEqual({
69-
value: '',
70-
type: 'string',
71-
});
72-
});
73-
74-
it('serializes null values as JSON strings', () => {
75-
const result = metricAttributeToSerializedMetricAttribute(null);
76-
expect(result).toEqual({
77-
value: 'null',
78-
type: 'string',
79-
});
80-
});
81-
});
82-
8314
describe('_INTERNAL_captureMetric', () => {
8415
it('captures and sends metrics', () => {
8516
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN });

0 commit comments

Comments
 (0)