Skip to content

Commit 0df43e0

Browse files
clintonbZirak
authored andcommitted
feat(api): added synchronous gauge (open-telemetry#4528)
* feat(instrumentation): added synchronous gauge * fixup! feat(instrumentation): added synchronous gauge * fixup! feat(instrumentation): added synchronous gauge * fixup! feat(instrumentation): added synchronous gauge
1 parent c998fea commit 0df43e0

File tree

9 files changed

+91
-16
lines changed

9 files changed

+91
-16
lines changed

api/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
99

1010
### :rocket: (Enhancement)
1111

12+
* feat(metrics): added synchronous gauge [#4528](https://github.com/open-telemetry/opentelemetry-js/pull/4528) @clintonb
1213
* feat(api): allow adding span links after span creation [#4536](https://github.com/open-telemetry/opentelemetry-js/pull/4536) @seemk
1314
* 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.
1415
* feat: support node 22 [#4666](https://github.com/open-telemetry/opentelemetry-js/pull/4666) @dyladan

api/src/index.ts

Lines changed: 1 addition & 0 deletions
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

Lines changed: 11 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
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

Lines changed: 15 additions & 2 deletions
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): Gauge {
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

Lines changed: 12 additions & 0 deletions
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/src/Meter.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
ObservableUpDownCounter,
2626
BatchObservableCallback,
2727
Observable,
28-
Attributes,
2928
} from '@opentelemetry/api';
3029
import {
3130
createInstrumentDescriptor,
@@ -51,12 +50,8 @@ export class Meter implements IMeter {
5150

5251
/**
5352
* Create a {@link Gauge} instrument.
54-
* @experimental
5553
*/
56-
createGauge<AttributesTypes extends Attributes = Attributes>(
57-
name: string,
58-
options?: MetricOptions
59-
): Gauge<AttributesTypes> {
54+
createGauge(name: string, options?: MetricOptions): Gauge {
6055
const descriptor = createInstrumentDescriptor(
6156
name,
6257
InstrumentType.GAUGE,

packages/sdk-metrics/src/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ export type ShutdownOptions = CommonReaderOptions;
2626
export type ForceFlushOptions = CommonReaderOptions;
2727

2828
/**
29-
* @experimental
30-
*
3129
* This is intentionally not using the API's type as it's only available from @opentelemetry/api 1.9.0 and up.
3230
* In SDK 2.0 we'll be able to bump the minimum API version and remove this workaround.
3331
*/

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

Lines changed: 41 additions & 6 deletions
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)