Skip to content

Commit 40dcded

Browse files
committed
feat(instrumentation): added synchronous gauge
1 parent 20182d8 commit 40dcded

File tree

7 files changed

+90
-8
lines changed

7 files changed

+90
-8
lines changed

api/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
88

99
### :rocket: (Enhancement)
1010

11+
* feat(metrics): added synchronous gauge [#4528](https://github.com/open-telemetry/opentelemetry-js/pull/4528) @clintonb
1112
* feat(api): allow adding span links after span creation [#4536](https://github.com/open-telemetry/opentelemetry-js/pull/4536) @seemk
1213
* This change is non-breaking for end-users, but breaking for Trace SDK implmentations in accordance with the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/a03382ada8afa9415266a84dafac0510ec8c160f/specification/upgrading.md?plain=1#L97-L122) as new features need to be implemented.
1314
* feat: support node 22 [#4666](https://github.com/open-telemetry/opentelemetry-js/pull/4666) @dyladan

api/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export { MeterProvider } from './metrics/MeterProvider';
4343
export {
4444
ValueType,
4545
Counter,
46+
Gauge,
4647
Histogram,
4748
MetricOptions,
4849
Observable,

api/src/metrics/Meter.ts

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import {
1818
BatchObservableCallback,
1919
Counter,
20+
Gauge,
2021
Histogram,
2122
MetricAttributes,
2223
MetricOptions,
@@ -45,6 +46,16 @@ export interface MeterOptions {
4546
* for the exported metric are deferred.
4647
*/
4748
export interface Meter {
49+
/**
50+
* Creates and returns a new `Gauge`.
51+
* @param name the name of the metric.
52+
* @param [options] the metric options.
53+
*/
54+
createGauge<AttributesTypes extends MetricAttributes = MetricAttributes>(
55+
name: string,
56+
options?: MetricOptions
57+
): Gauge<AttributesTypes>;
58+
4859
/**
4960
* Creates and returns a new `Histogram`.
5061
* @param name the name of the metric.

api/src/metrics/Metric.ts

+9
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ export interface UpDownCounter<
9898
add(value: number, attributes?: AttributesTypes, context?: Context): void;
9999
}
100100

101+
export interface Gauge<
102+
AttributesTypes extends MetricAttributes = MetricAttributes,
103+
> {
104+
/**
105+
* Records a measurement.
106+
*/
107+
record(value: number, attributes?: AttributesTypes, context?: Context): void;
108+
}
109+
101110
export interface Histogram<
102111
AttributesTypes extends MetricAttributes = MetricAttributes,
103112
> {

api/src/metrics/NoopMeter.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ import { Meter } from './Meter';
1818
import {
1919
BatchObservableCallback,
2020
Counter,
21+
Gauge,
2122
Histogram,
23+
MetricAttributes,
2224
MetricOptions,
25+
Observable,
2326
ObservableCallback,
2427
ObservableCounter,
2528
ObservableGauge,
2629
ObservableUpDownCounter,
2730
UpDownCounter,
28-
MetricAttributes,
29-
Observable,
3031
} from './Metric';
3132

3233
/**
@@ -36,6 +37,13 @@ import {
3637
export class NoopMeter implements Meter {
3738
constructor() {}
3839

40+
/**
41+
* @see {@link Meter.createGauge}
42+
*/
43+
createGauge(_name: string, _options?: MetricOptions): Histogram {
44+
return NOOP_GAUGE_METRIC;
45+
}
46+
3947
/**
4048
* @see {@link Meter.createHistogram}
4149
*/
@@ -114,6 +122,10 @@ export class NoopUpDownCounterMetric
114122
add(_value: number, _attributes: MetricAttributes): void {}
115123
}
116124

125+
export class NoopGaugeMetric extends NoopMetric implements Gauge {
126+
record(_value: number, _attributes: MetricAttributes): void {}
127+
}
128+
117129
export class NoopHistogramMetric extends NoopMetric implements Histogram {
118130
record(_value: number, _attributes: MetricAttributes): void {}
119131
}
@@ -140,6 +152,7 @@ export const NOOP_METER = new NoopMeter();
140152

141153
// Synchronous instruments
142154
export const NOOP_COUNTER_METRIC = new NoopCounterMetric();
155+
export const NOOP_GAUGE_METRIC = new NoopGaugeMetric();
143156
export const NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();
144157
export const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();
145158

api/test/common/noop-implementations/noop-meter.test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC,
2525
NOOP_UP_DOWN_COUNTER_METRIC,
2626
createNoopMeter,
27+
NOOP_GAUGE_METRIC,
2728
} from '../../../src/metrics/NoopMeter';
2829
import { NoopMeterProvider } from '../../../src/metrics/NoopMeterProvider';
2930

@@ -116,6 +117,17 @@ describe('NoopMeter', () => {
116117
);
117118
});
118119

120+
it('gauge should not crash', () => {
121+
const meter = new NoopMeterProvider().getMeter('test-noop');
122+
const observableGauge = meter.createGauge('some-name');
123+
124+
// ensure the correct noop const is returned
125+
assert.strictEqual(observableGauge, NOOP_GAUGE_METRIC);
126+
127+
const gaugeWithOptions = meter.createGauge('some-name', options);
128+
assert.strictEqual(gaugeWithOptions, NOOP_GAUGE_METRIC);
129+
});
130+
119131
it('observable up down counter should not crash', () => {
120132
const meter = new NoopMeterProvider().getMeter('test-noop');
121133
const observableUpDownCounter =

packages/sdk-metrics/test/Instruments.test.ts

+41-6
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,25 @@ import * as sinon from 'sinon';
1919
import { InstrumentationScope } from '@opentelemetry/core';
2020
import { Resource } from '@opentelemetry/resources';
2121
import {
22-
InstrumentType,
23-
MeterProvider,
24-
MetricReader,
2522
DataPoint,
2623
DataPointType,
2724
Histogram,
25+
InstrumentType,
26+
MeterProvider,
2827
MetricDescriptor,
28+
MetricReader,
2929
} from '../src';
3030
import {
3131
TestDeltaMetricReader,
3232
TestMetricReader,
3333
} from './export/TestMetricReader';
3434
import {
35-
assertMetricData,
3635
assertDataPoint,
37-
commonValues,
36+
assertMetricData,
3837
commonAttributes,
39-
defaultResource,
38+
commonValues,
4039
defaultInstrumentationScope,
40+
defaultResource,
4141
} from './util';
4242
import { ObservableResult, ValueType } from '@opentelemetry/api';
4343

@@ -764,6 +764,41 @@ describe('Instruments', () => {
764764
});
765765
});
766766
});
767+
768+
describe('Gauge', () => {
769+
it('should record common values and attributes without exceptions', async () => {
770+
const { meter } = setup();
771+
const gauge = meter.createGauge('test');
772+
773+
for (const values of commonValues) {
774+
for (const attributes of commonAttributes) {
775+
gauge.record(values, attributes);
776+
}
777+
}
778+
});
779+
780+
it('should record values', async () => {
781+
const { meter, cumulativeReader } = setup();
782+
const gauge = meter.createGauge('test');
783+
784+
gauge.record(1, { foo: 'bar' });
785+
gauge.record(-1);
786+
787+
await validateExport(cumulativeReader, {
788+
dataPointType: DataPointType.GAUGE,
789+
dataPoints: [
790+
{
791+
attributes: { foo: 'bar' },
792+
value: 1,
793+
},
794+
{
795+
attributes: {},
796+
value: -1,
797+
},
798+
],
799+
});
800+
});
801+
});
767802
});
768803

769804
function setup() {

0 commit comments

Comments
 (0)