Skip to content

Commit

Permalink
feat(api): added synchronous gauge (#4528)
Browse files Browse the repository at this point in the history
* feat(instrumentation): added synchronous gauge

* fixup! feat(instrumentation): added synchronous gauge

* fixup! feat(instrumentation): added synchronous gauge

* fixup! feat(instrumentation): added synchronous gauge
  • Loading branch information
clintonb authored May 27, 2024
1 parent 860e5d5 commit 095003d
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 16 deletions.
1 change: 1 addition & 0 deletions api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.

### :rocket: (Enhancement)

* feat(metrics): added synchronous gauge [#4528](https://github.com/open-telemetry/opentelemetry-js/pull/4528) @clintonb
* feat(api): allow adding span links after span creation [#4536](https://github.com/open-telemetry/opentelemetry-js/pull/4536) @seemk
* 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.
* feat: support node 22 [#4666](https://github.com/open-telemetry/opentelemetry-js/pull/4666) @dyladan
Expand Down
1 change: 1 addition & 0 deletions api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export { MeterProvider } from './metrics/MeterProvider';
export {
ValueType,
Counter,
Gauge,
Histogram,
MetricOptions,
Observable,
Expand Down
11 changes: 11 additions & 0 deletions api/src/metrics/Meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import {
BatchObservableCallback,
Counter,
Gauge,
Histogram,
MetricAttributes,
MetricOptions,
Expand Down Expand Up @@ -45,6 +46,16 @@ export interface MeterOptions {
* for the exported metric are deferred.
*/
export interface Meter {
/**
* Creates and returns a new `Gauge`.
* @param name the name of the metric.
* @param [options] the metric options.
*/
createGauge<AttributesTypes extends MetricAttributes = MetricAttributes>(
name: string,
options?: MetricOptions
): Gauge<AttributesTypes>;

/**
* Creates and returns a new `Histogram`.
* @param name the name of the metric.
Expand Down
9 changes: 9 additions & 0 deletions api/src/metrics/Metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ export interface UpDownCounter<
add(value: number, attributes?: AttributesTypes, context?: Context): void;
}

export interface Gauge<
AttributesTypes extends MetricAttributes = MetricAttributes,
> {
/**
* Records a measurement.
*/
record(value: number, attributes?: AttributesTypes, context?: Context): void;
}

export interface Histogram<
AttributesTypes extends MetricAttributes = MetricAttributes,
> {
Expand Down
17 changes: 15 additions & 2 deletions api/src/metrics/NoopMeter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ import { Meter } from './Meter';
import {
BatchObservableCallback,
Counter,
Gauge,
Histogram,
MetricAttributes,
MetricOptions,
Observable,
ObservableCallback,
ObservableCounter,
ObservableGauge,
ObservableUpDownCounter,
UpDownCounter,
MetricAttributes,
Observable,
} from './Metric';

/**
Expand All @@ -36,6 +37,13 @@ import {
export class NoopMeter implements Meter {
constructor() {}

/**
* @see {@link Meter.createGauge}
*/
createGauge(_name: string, _options?: MetricOptions): Gauge {
return NOOP_GAUGE_METRIC;
}

/**
* @see {@link Meter.createHistogram}
*/
Expand Down Expand Up @@ -114,6 +122,10 @@ export class NoopUpDownCounterMetric
add(_value: number, _attributes: MetricAttributes): void {}
}

export class NoopGaugeMetric extends NoopMetric implements Gauge {
record(_value: number, _attributes: MetricAttributes): void {}
}

export class NoopHistogramMetric extends NoopMetric implements Histogram {
record(_value: number, _attributes: MetricAttributes): void {}
}
Expand All @@ -140,6 +152,7 @@ export const NOOP_METER = new NoopMeter();

// Synchronous instruments
export const NOOP_COUNTER_METRIC = new NoopCounterMetric();
export const NOOP_GAUGE_METRIC = new NoopGaugeMetric();
export const NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();
export const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();

Expand Down
12 changes: 12 additions & 0 deletions api/test/common/noop-implementations/noop-meter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC,
NOOP_UP_DOWN_COUNTER_METRIC,
createNoopMeter,
NOOP_GAUGE_METRIC,
} from '../../../src/metrics/NoopMeter';
import { NoopMeterProvider } from '../../../src/metrics/NoopMeterProvider';

Expand Down Expand Up @@ -116,6 +117,17 @@ describe('NoopMeter', () => {
);
});

it('gauge should not crash', () => {
const meter = new NoopMeterProvider().getMeter('test-noop');
const observableGauge = meter.createGauge('some-name');

// ensure the correct noop const is returned
assert.strictEqual(observableGauge, NOOP_GAUGE_METRIC);

const gaugeWithOptions = meter.createGauge('some-name', options);
assert.strictEqual(gaugeWithOptions, NOOP_GAUGE_METRIC);
});

it('observable up down counter should not crash', () => {
const meter = new NoopMeterProvider().getMeter('test-noop');
const observableUpDownCounter =
Expand Down
7 changes: 1 addition & 6 deletions packages/sdk-metrics/src/Meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
ObservableUpDownCounter,
BatchObservableCallback,
Observable,
Attributes,
} from '@opentelemetry/api';
import {
createInstrumentDescriptor,
Expand All @@ -51,12 +50,8 @@ export class Meter implements IMeter {

/**
* Create a {@link Gauge} instrument.
* @experimental
*/
createGauge<AttributesTypes extends Attributes = Attributes>(
name: string,
options?: MetricOptions
): Gauge<AttributesTypes> {
createGauge(name: string, options?: MetricOptions): Gauge {
const descriptor = createInstrumentDescriptor(
name,
InstrumentType.GAUGE,
Expand Down
2 changes: 0 additions & 2 deletions packages/sdk-metrics/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ export type ShutdownOptions = CommonReaderOptions;
export type ForceFlushOptions = CommonReaderOptions;

/**
* @experimental
*
* This is intentionally not using the API's type as it's only available from @opentelemetry/api 1.9.0 and up.
* In SDK 2.0 we'll be able to bump the minimum API version and remove this workaround.
*/
Expand Down
47 changes: 41 additions & 6 deletions packages/sdk-metrics/test/Instruments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ import * as sinon from 'sinon';
import { InstrumentationScope } from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
import {
InstrumentType,
MeterProvider,
MetricReader,
DataPoint,
DataPointType,
Histogram,
InstrumentType,
MeterProvider,
MetricDescriptor,
MetricReader,
} from '../src';
import {
TestDeltaMetricReader,
TestMetricReader,
} from './export/TestMetricReader';
import {
assertMetricData,
assertDataPoint,
commonValues,
assertMetricData,
commonAttributes,
defaultResource,
commonValues,
defaultInstrumentationScope,
defaultResource,
} from './util';
import { ObservableResult, ValueType } from '@opentelemetry/api';

Expand Down Expand Up @@ -764,6 +764,41 @@ describe('Instruments', () => {
});
});
});

describe('Gauge', () => {
it('should record common values and attributes without exceptions', async () => {
const { meter } = setup();
const gauge = meter.createGauge('test');

for (const values of commonValues) {
for (const attributes of commonAttributes) {
gauge.record(values, attributes);
}
}
});

it('should record values', async () => {
const { meter, cumulativeReader } = setup();
const gauge = meter.createGauge('test');

gauge.record(1, { foo: 'bar' });
gauge.record(-1);

await validateExport(cumulativeReader, {
dataPointType: DataPointType.GAUGE,
dataPoints: [
{
attributes: { foo: 'bar' },
value: 1,
},
{
attributes: {},
value: -1,
},
],
});
});
});
});

function setup() {
Expand Down

0 comments on commit 095003d

Please sign in to comment.