Skip to content

Commit

Permalink
feat(sdk-metrics-base): multi-instrument async callback support
Browse files Browse the repository at this point in the history
  • Loading branch information
legendecas committed May 13, 2022
1 parent aabc5f6 commit 628ef3e
Show file tree
Hide file tree
Showing 26 changed files with 960 additions and 222 deletions.
5 changes: 5 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ All notable changes to experimental packages in this project will be documented

* feat(metrics): metric readers and exporters now select aggregation temporality based on instrument type #2902 @seemk
* refactor(metrics-sdk): rename InstrumentationLibrary -> InstrumentationScope #2959 @pichlermarc
* feat(metrics): multi-instrument async callback support #2966 @legendecas
* changes on `meter.createObservableCounter`, `meter.createObservableGauge`, `meter.createObservableUpDownCounter`
* removed the second parameter `callback`
* returns an `Observable` object on which callbacks can be registered or unregistered.
* added `meter.addBatchObservableCallback` and `meter.removeBatchObservableCallback`.

### :rocket: (Enhancement)

Expand Down
94 changes: 58 additions & 36 deletions experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@

import { Meter } from './types/Meter';
import {
MetricOptions,
MetricAttributes,
BatchObservableCallback,
Counter,
CounterOptions,
Histogram,
UpDownCounter,
HistogramOptions,
ObservableCallback,
ObservableCounter,
ObservableCounterOptions,
ObservableGauge,
ObservableGaugeOptions,
ObservableUpDownCounter,
ObservableUpDownCounterOptions,
UpDownCounter,
UpDownCounterOptions,
MetricAttributes,
Observable,
} from './types/Metric';

/**
Expand All @@ -32,67 +42,65 @@ export class NoopMeter implements Meter {
constructor() {}

/**
* Returns a constant noop histogram.
* @param name the name of the metric.
* @param [options] the metric options.
* @see {@link Meter.createHistogram}
*/
createHistogram(_name: string, _options?: MetricOptions): Histogram {
createHistogram(_name: string, _options?: HistogramOptions): Histogram {
return NOOP_HISTOGRAM_METRIC;
}

/**
* Returns a constant noop counter.
* @param name the name of the metric.
* @param [options] the metric options.
* @see {@link Meter.createCounter}
*/
createCounter(_name: string, _options?: MetricOptions): Counter {
createCounter(_name: string, _options?: CounterOptions): Counter {
return NOOP_COUNTER_METRIC;
}

/**
* Returns a constant noop UpDownCounter.
* @param name the name of the metric.
* @param [options] the metric options.
* @see {@link Meter.createUpDownCounter}
*/
createUpDownCounter(_name: string, _options?: MetricOptions): UpDownCounter {
createUpDownCounter(_name: string, _options?: UpDownCounterOptions): UpDownCounter {
return NOOP_UP_DOWN_COUNTER_METRIC;
}

/**
* Returns a constant noop observable gauge.
* @param name the name of the metric.
* @param callback the observable gauge callback
* @param [options] the metric options.
* @see {@link Meter.createObservableGauge}
*/
createObservableGauge(
_name: string,
_callback: ObservableCallback,
_options?: MetricOptions,
): void {}
_options?: ObservableGaugeOptions,
): ObservableGauge {
return NOOP_OBSERVABLE_GAUGE_METRIC;
}

/**
* Returns a constant noop observable counter.
* @param name the name of the metric.
* @param callback the observable counter callback
* @param [options] the metric options.
* @see {@link Meter.createObservableCounter}
*/
createObservableCounter(
_name: string,
_callback: ObservableCallback,
_options?: MetricOptions,
): void {}
_options?: ObservableCounterOptions,
): ObservableCounter {
return NOOP_OBSERVABLE_COUNTER_METRIC;
}

/**
* Returns a constant noop up down observable counter.
* @param name the name of the metric.
* @param callback the up down observable counter callback
* @param [options] the metric options.
* @see {@link Meter.createObservableUpDownCounter}
*/
createObservableUpDownCounter(
_name: string,
_callback: ObservableCallback,
_options?: MetricOptions,
): void {}
_options?: ObservableUpDownCounterOptions,
): ObservableUpDownCounter {
return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC;
}

/**
* @see {@link Meter.addBatchObservableCallback}
*/
addBatchObservableCallback(_callback: BatchObservableCallback, _observables: Observable[]): void {}

/**
* @see {@link Meter.removeBatchObservableCallback}
*/
removeBatchObservableCallback(_callback: BatchObservableCallback): void {}
}

export class NoopMetric {}
Expand All @@ -109,9 +117,23 @@ export class NoopHistogramMetric extends NoopMetric implements Histogram {
record(_value: number, _attributes: MetricAttributes): void {}
}

export class NoopObservableMetric {
addCallback(_callback: ObservableCallback) {}
removeCallback(_callback: ObservableCallback) {}
}

export class NoopObservableCounterMetric extends NoopObservableMetric implements ObservableCounter {}
export class NoopObservableGaugeMetric extends NoopObservableMetric implements ObservableGauge {}
export class NoopObservableUpDownCounterMetric extends NoopObservableMetric implements ObservableUpDownCounter {}

export const NOOP_METER = new NoopMeter();

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

// Asynchronous instruments
export const NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableCounterMetric();
export const NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableGaugeMetric();
export const NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableUpDownCounterMetric();
49 changes: 38 additions & 11 deletions experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,21 @@
* limitations under the License.
*/

import { CounterOptions, HistogramOptions, UpDownCounterOptions } from '..';
import {
BatchObservableCallback,
Counter,
CounterOptions,
Histogram,
ObservableCallback,
HistogramOptions,
Observable,
ObservableCounter,
ObservableCounterOptions,
ObservableGauge,
ObservableGaugeOptions,
ObservableUpDownCounter,
ObservableUpDownCounterOptions,
UpDownCounter,
UpDownCounterOptions,
} from './Metric';

/**
Expand Down Expand Up @@ -84,42 +90,63 @@ export interface Meter {
* The callback SHOULD be safe to be invoked concurrently.
*
* @param name the name of the metric.
* @param callback the observable callback
* @param [options] the metric options.
*/
createObservableGauge(
name: string,
callback: ObservableCallback,
options?: ObservableGaugeOptions
): void;
): ObservableGauge;

/**
* Creates a new `ObservableCounter` metric.
*
* The callback SHOULD be safe to be invoked concurrently.
*
* @param name the name of the metric.
* @param callback the observable callback
* @param [options] the metric options.
*/
createObservableCounter(
name: string,
callback: ObservableCallback,
options?: ObservableCounterOptions
): void;
): ObservableCounter;

/**
* Creates a new `ObservableUpDownCounter` metric.
*
* The callback SHOULD be safe to be invoked concurrently.
*
* @param name the name of the metric.
* @param callback the observable callback
* @param [options] the metric options.
*/
createObservableUpDownCounter(
name: string,
callback: ObservableCallback,
options?: ObservableUpDownCounterOptions
): void;
): ObservableUpDownCounter;

/**
* Sets up a function that will be called whenever a metric collection is
* initiated.
*
* If the function is already in the list of callbacks for this Observable,
* the function is not added a second time.
*
* Only the associated observables can be observed in the callback.
* Measurements of observables that are not associated observed in the
* callback are dropped.
*
* @param callback the batch observable callback
* @param observables the observables associated with this batch observable callback
*/
addBatchObservableCallback(callback: BatchObservableCallback, observables: Observable[]): void;

/**
* Removes a callback previously registered with {@link Meter.addBatchObservableCallback}.
*
* The callback to be removed is identified using a combination of the callback itself,
* and the set of the observables associated with it.
*
* @param callback the batch observable callback
* @param observables the observables associated with this batch observable callback
*/
removeBatchObservableCallback(callback: BatchObservableCallback, observables: Observable[]): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { Context } from '@opentelemetry/api';
import { ObservableResult } from './ObservableResult';
import { BatchObservableResult, ObservableResult } from './ObservableResult';

/**
* Options needed for metric creation
Expand Down Expand Up @@ -98,3 +98,26 @@ export type MetricAttributes = { [key: string]: string };
* The observable callback for Observable instruments.
*/
export type ObservableCallback = (observableResult: ObservableResult) => void | Promise<void>;

/**
* The observable callback for a batch of Observable instruments.
*/
export type BatchObservableCallback = (observableResult: BatchObservableResult) => void | Promise<void>;

export interface Observable {
/**
* Sets up a function that will be called whenever a metric collection is initiated.
*
* If the function is already in the list of callbacks for this Observable, the function is not added a second time.
*/
addCallback(callback: ObservableCallback): void;

/**
* Removes a callback previously registered with {@link Observable.addCallback}.
*/
removeCallback(callback: ObservableCallback): void;
}

export type ObservableCounter = Observable;
export type ObservableUpDownCounter = Observable;
export type ObservableGauge = Observable;
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* limitations under the License.
*/

import { MetricAttributes } from './Metric';
import { MetricAttributes, Observable } from './Metric';

/**
* Interface that is being used in callback function for Observable Metric
* Interface that is being used in callback function for Observable Metric.
*/
export interface ObservableResult {
/**
Expand All @@ -30,3 +30,19 @@ export interface ObservableResult {
*/
observe(value: number, attributes?: MetricAttributes): void;
}

/**
* Interface that is being used in batch observable callback function.
*/
export interface BatchObservableResult {
/**
* Observe a measurement of the value associated with the given attributes.
*
* @param metric The observable metric to be observed.
* @param value The value to be observed.
* @param attributes The attributes associated with the value. If more than
* one values associated with the same attributes values, SDK may pick the
* last one or simply drop the entire observable result.
*/
observe(metric: Observable, value: number, attributes?: MetricAttributes): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { Counter, Histogram, ObservableResult, ValueType } from '@opentelemetry/api-metrics';
import { Counter, Histogram, ObservableGauge, ObservableResult, ValueType } from '@opentelemetry/api-metrics';
import { Resource } from '@opentelemetry/resources';
import * as assert from 'assert';
import * as grpc from '@grpc/grpc-js';
Expand Down Expand Up @@ -81,16 +81,18 @@ export function mockCounter(): Counter {

export function mockObservableGauge(
callback: (observableResult: ObservableResult) => void
): void {
): ObservableGauge {
const name = 'double-observable-gauge';
return meter.createObservableGauge(
const observableGauge = meter.createObservableGauge(
name,
callback,
{
description: 'sample observable gauge description',
valueType: ValueType.DOUBLE,
},
);
observableGauge.addCallback(callback);

return observableGauge;
}

export function mockHistogram(): Histogram {
Expand Down
Loading

0 comments on commit 628ef3e

Please sign in to comment.