Skip to content

Commit fcef5e2

Browse files
authored
fix(sdk-metrics-base): only record non-negative histogram values. (#3002)
1 parent fd95d42 commit fcef5e2

File tree

3 files changed

+57
-11
lines changed

3 files changed

+57
-11
lines changed

experimental/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ All notable changes to experimental packages in this project will be documented
1010

1111
### :bug: (Bug Fix)
1212

13+
* fix(sdk-metrics-base): only record non-negative histogram values #3002 @pichlermarc
14+
1315
### :books: (Refine Doc)
1416

1517
### :house: (Internal)

experimental/packages/opentelemetry-sdk-metrics-base/src/Instruments.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export class HistogramInstrument extends SyncInstrument implements metrics.Histo
7272
* Records a measurement. Value of the measurement must not be negative.
7373
*/
7474
record(value: number, attributes?: metrics.MetricAttributes, ctx?: api.Context): void {
75+
if (value < 0) {
76+
api.diag.warn(`negative value provided to histogram ${this._descriptor.name}: ${value}`);
77+
return;
78+
}
7579
this._record(value, attributes, ctx);
7680
}
7781
}

experimental/packages/opentelemetry-sdk-metrics-base/test/Instruments.test.ts

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,24 @@ import * as assert from 'assert';
1818
import * as sinon from 'sinon';
1919
import { InstrumentationScope } from '@opentelemetry/core';
2020
import { Resource } from '@opentelemetry/resources';
21-
import { AggregationTemporality, InstrumentDescriptor, InstrumentType, MeterProvider, MetricReader, DataPoint, DataPointType } from '../src';
21+
import {
22+
AggregationTemporality,
23+
InstrumentDescriptor,
24+
InstrumentType,
25+
MeterProvider,
26+
MetricReader,
27+
DataPoint,
28+
DataPointType
29+
} from '../src';
2230
import { TestMetricReader } from './export/TestMetricReader';
23-
import { assertMetricData, assertDataPoint, commonValues, commonAttributes, defaultResource, defaultInstrumentationScope } from './util';
31+
import {
32+
assertMetricData,
33+
assertDataPoint,
34+
commonValues,
35+
commonAttributes,
36+
defaultResource,
37+
defaultInstrumentationScope
38+
} from './util';
2439
import { Histogram } from '../src/aggregator/types';
2540
import { ObservableResult, ValueType } from '@opentelemetry/api-metrics';
2641

@@ -257,10 +272,10 @@ describe('Instruments', () => {
257272
});
258273

259274
histogram.record(10);
260-
// -0.1 should be trunc-ed to -0
261-
histogram.record(-0.1);
275+
// 0.1 should be trunc-ed to 0
276+
histogram.record(0.1);
262277
histogram.record(100, { foo: 'bar' });
263-
histogram.record(-0.1, { foo: 'bar' });
278+
histogram.record(0.1, { foo: 'bar' });
264279
await validateExport(deltaReader, {
265280
descriptor: {
266281
name: 'test',
@@ -297,6 +312,18 @@ describe('Instruments', () => {
297312
});
298313
});
299314

315+
it('should not record negative INT values', async () => {
316+
const { meter, deltaReader } = setup();
317+
const histogram = meter.createHistogram('test', {
318+
valueType: ValueType.DOUBLE,
319+
});
320+
321+
histogram.record(-1, { foo: 'bar' });
322+
await validateExport(deltaReader, {
323+
dataPointType: DataPointType.HISTOGRAM,
324+
dataPoints: [],
325+
});
326+
});
300327

301328
it('should record DOUBLE values', async () => {
302329
const { meter, deltaReader } = setup();
@@ -305,9 +332,9 @@ describe('Instruments', () => {
305332
});
306333

307334
histogram.record(10);
308-
histogram.record(-0.1);
335+
histogram.record(0.1);
309336
histogram.record(100, { foo: 'bar' });
310-
histogram.record(-0.1, { foo: 'bar' });
337+
histogram.record(0.1, { foo: 'bar' });
311338
await validateExport(deltaReader, {
312339
dataPointType: DataPointType.HISTOGRAM,
313340
dataPoints: [
@@ -316,26 +343,39 @@ describe('Instruments', () => {
316343
value: {
317344
buckets: {
318345
boundaries: [0, 5, 10, 25, 50, 75, 100, 250, 500, 1000],
319-
counts: [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
346+
counts: [0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
320347
},
321348
count: 2,
322-
sum: 9.9,
349+
sum: 10.1,
323350
},
324351
},
325352
{
326353
attributes: { foo: 'bar' },
327354
value: {
328355
buckets: {
329356
boundaries: [0, 5, 10, 25, 50, 75, 100, 250, 500, 1000],
330-
counts: [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
357+
counts: [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
331358
},
332359
count: 2,
333-
sum: 99.9,
360+
sum: 100.1,
334361
},
335362
},
336363
],
337364
});
338365
});
366+
367+
it('should not record negative DOUBLE values', async () => {
368+
const { meter, deltaReader } = setup();
369+
const histogram = meter.createHistogram('test', {
370+
valueType: ValueType.DOUBLE,
371+
});
372+
373+
histogram.record(-0.5, { foo: 'bar' });
374+
await validateExport(deltaReader, {
375+
dataPointType: DataPointType.HISTOGRAM,
376+
dataPoints: [],
377+
});
378+
});
339379
});
340380

341381
describe('ObservableCounter', () => {

0 commit comments

Comments
 (0)