From 0cc471f69e4766bb8f23a53ad36d002b6be4e7dd Mon Sep 17 00:00:00 2001 From: legendecas Date: Tue, 8 Mar 2022 15:59:42 +0800 Subject: [PATCH 1/3] refactor(sdk-metrics-base): add ObservableRegistry and hoist invocations --- .../src/types/Meter.ts | 9 ++ .../src/state/AsyncMetricStorage.ts | 29 ++---- .../src/state/MeterSharedState.ts | 15 +++- .../src/state/MetricStorage.ts | 2 +- .../src/state/ObservableRegistry.ts | 53 +++++++++++ .../src/state/SyncMetricStorage.ts | 16 +--- .../src/state/WritableMetricStorage.ts | 17 +++- .../test/state/AsyncMetricStorage.test.ts | 38 +++++--- .../test/state/MeterSharedState.test.ts | 88 ++++++++++++++++++- .../test/state/MetricStorageRegistry.test.ts | 4 +- .../test/state/SyncMetricStorage.test.ts | 12 +-- 11 files changed, 216 insertions(+), 67 deletions(-) create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/src/state/ObservableRegistry.ts diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts b/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts index fb1978c3aa7..10ddde3a189 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts @@ -80,6 +80,9 @@ export interface Meter { /** * Creates a new `ObservableGauge` metric. + * + * The callback SHOULD be reentrant safe. + * * @param name the name of the metric. * @param callback the observable callback * @param [options] the metric options. @@ -92,6 +95,9 @@ export interface Meter { /** * Creates a new `ObservableCounter` metric. + * + * The callback SHOULD be reentrant safe. + * * @param name the name of the metric. * @param callback the observable callback * @param [options] the metric options. @@ -104,6 +110,9 @@ export interface Meter { /** * Creates a new `ObservableUpDownCounter` metric. + * + * The callback SHOULD be reentrant safe. + * * @param name the name of the metric. * @param callback the observable callback * @param [options] the metric options. diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts index 44f95b3c4c8..c8c9aedc1d8 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts @@ -15,13 +15,8 @@ */ import { HrTime } from '@opentelemetry/api'; -import { ObservableCallback } from '@opentelemetry/api-metrics'; import { Accumulation, Aggregator } from '../aggregator/types'; -import { View } from '../view/View'; -import { - createInstrumentDescriptorWithView, - InstrumentDescriptor -} from '../InstrumentDescriptor'; +import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { AttributesProcessor } from '../view/AttributesProcessor'; import { MetricStorage } from './MetricStorage'; import { MetricData } from '../export/MetricData'; @@ -29,15 +24,15 @@ import { DeltaMetricProcessor } from './DeltaMetricProcessor'; import { TemporalMetricProcessor } from './TemporalMetricProcessor'; import { Maybe } from '../utils'; import { MetricCollectorHandle } from './MetricCollector'; -import { ObservableResult } from '../ObservableResult'; import { AttributeHashMap } from './HashMap'; +import { AsyncWritableMetricStorage } from './WritableMetricStorage'; /** * Internal interface. * * Stores and aggregates {@link MetricData} for asynchronous instruments. */ -export class AsyncMetricStorage> extends MetricStorage { +export class AsyncMetricStorage> extends MetricStorage implements AsyncWritableMetricStorage { private _deltaMetricStorage: DeltaMetricProcessor; private _temporalMetricStorage: TemporalMetricProcessor; @@ -45,14 +40,13 @@ export class AsyncMetricStorage> extends MetricSto _instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator, private _attributesProcessor: AttributesProcessor, - private _callback: ObservableCallback ) { super(_instrumentDescriptor); this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); this._temporalMetricStorage = new TemporalMetricProcessor(aggregator); } - private _record(measurements: AttributeHashMap) { + record(measurements: AttributeHashMap) { const processed = new AttributeHashMap(); Array.from(measurements.entries()).forEach(([attributes, value]) => { processed.set(this._attributesProcessor.process(attributes), value); @@ -67,17 +61,12 @@ export class AsyncMetricStorage> extends MetricSto * Note: This is a stateful operation and may reset any interval-related * state for the MetricCollector. */ - async collect( + collect( collector: MetricCollectorHandle, collectors: MetricCollectorHandle[], sdkStartTime: HrTime, collectionTime: HrTime, - ): Promise> { - const observableResult = new ObservableResult(); - // TODO: timeout with callback - await this._callback(observableResult); - this._record(observableResult.buffer); - + ): Maybe { const accumulations = this._deltaMetricStorage.collect(); return this._temporalMetricStorage.buildMetrics( @@ -89,10 +78,4 @@ export class AsyncMetricStorage> extends MetricSto collectionTime ); } - - static create(view: View, instrument: InstrumentDescriptor, callback: ObservableCallback): AsyncMetricStorage> { - instrument = createInstrumentDescriptorWithView(view, instrument); - const aggregator = view.aggregation.createAggregator(instrument); - return new AsyncMetricStorage(instrument, aggregator, view.attributesProcessor, callback); - } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts index 912cf54557c..1b988eb3bff 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts @@ -25,6 +25,7 @@ import { MeterProviderSharedState } from './MeterProviderSharedState'; import { MetricCollectorHandle } from './MetricCollector'; import { MetricStorageRegistry } from './MetricStorageRegistry'; import { MultiMetricStorage } from './MultiWritableMetricStorage'; +import { ObservableRegistry } from './ObservableRegistry'; import { SyncMetricStorage } from './SyncMetricStorage'; /** @@ -32,6 +33,7 @@ import { SyncMetricStorage } from './SyncMetricStorage'; */ export class MeterSharedState { private _metricStorageRegistry = new MetricStorageRegistry(); + private _observableRegistry = new ObservableRegistry(); constructor(private _meterProviderSharedState: MeterProviderSharedState, private _instrumentationLibrary: InstrumentationLibrary) {} @@ -56,8 +58,12 @@ export class MeterSharedState { views.forEach(view => { const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor); const aggregator = view.aggregation.createAggregator(viewDescriptor); - const viewStorage = new AsyncMetricStorage(viewDescriptor, aggregator, view.attributesProcessor, callback); - this._metricStorageRegistry.register(viewStorage); + const viewStorage = new AsyncMetricStorage(viewDescriptor, aggregator, view.attributesProcessor); + const storage = this._metricStorageRegistry.register(viewStorage); + if (storage == null) { + return; + } + this._observableRegistry.addCallback(callback, storage); }); } @@ -71,7 +77,8 @@ export class MeterSharedState { * 1. Call all observable callbacks first. * 2. Collect metric result for the collector. */ - const metricDataList = await Promise.all(Array.from(this._metricStorageRegistry.getStorages()) + await this._observableRegistry.observe(); + const metricDataList = Array.from(this._metricStorageRegistry.getStorages()) .map(metricStorage => { return metricStorage.collect( collector, @@ -79,7 +86,7 @@ export class MeterSharedState { this._meterProviderSharedState.sdkStartTime, collectionTime); }) - .filter(isNotNullish)); + .filter(isNotNullish); return { instrumentationLibrary: this._instrumentationLibrary, diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts index 9344231f90b..2d92aa16839 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts @@ -40,7 +40,7 @@ export abstract class MetricStorage { collectors: MetricCollectorHandle[], sdkStartTime: HrTime, collectionTime: HrTime, - ): Promise>; + ): Maybe; getInstrumentDescriptor(): InstrumentDescriptor{ return this._instrumentDescriptor; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/ObservableRegistry.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/ObservableRegistry.ts new file mode 100644 index 00000000000..96473f5cc1b --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/ObservableRegistry.ts @@ -0,0 +1,53 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ObservableCallback } from '@opentelemetry/api-metrics'; +import { ObservableResult } from '../ObservableResult'; +import { AsyncWritableMetricStorage } from './WritableMetricStorage'; + +/** + * An internal state interface for ObservableCallbacks. + * + * An ObservableCallback can be bound to multiple AsyncMetricStorage at once + * for batch observations. And an AsyncMetricStorage may be bound to multiple + * callbacks too. + * + * However an ObservableCallback must not be called multiple times during a + * single collection operation. + */ +export class ObservableRegistry { + private _callbacks: [ObservableCallback, AsyncWritableMetricStorage][] = []; + + addCallback(callback: ObservableCallback, metricStorage: AsyncWritableMetricStorage) { + this._callbacks.push([callback, metricStorage]); + } + + async observe(): Promise { + // TODO: batch observables + // https://github.com/open-telemetry/opentelemetry-specification/pull/2363 + const promise = Promise.all(this._callbacks + .map(async ([observableCallback, metricStorage]) => { + const observableResult = new ObservableResult(); + // TODO: timeout with callback + // https://github.com/open-telemetry/opentelemetry-specification/issues/2295 + await observableCallback(observableResult); + metricStorage.record(observableResult.buffer); + }) + ); + + await promise; + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts index db9e029307a..06a69846306 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts @@ -18,11 +18,7 @@ import { Context, HrTime } from '@opentelemetry/api'; import { MetricAttributes } from '@opentelemetry/api-metrics'; import { WritableMetricStorage } from './WritableMetricStorage'; import { Accumulation, Aggregator } from '../aggregator/types'; -import { View } from '../view/View'; -import { - createInstrumentDescriptorWithView, - InstrumentDescriptor -} from '../InstrumentDescriptor'; +import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { AttributesProcessor } from '../view/AttributesProcessor'; import { MetricStorage } from './MetricStorage'; import { MetricData } from '../export/MetricData'; @@ -61,12 +57,12 @@ export class SyncMetricStorage> extends MetricStor * Note: This is a stateful operation and may reset any interval-related * state for the MetricCollector. */ - async collect( + collect( collector: MetricCollectorHandle, collectors: MetricCollectorHandle[], sdkStartTime: HrTime, collectionTime: HrTime, - ): Promise> { + ): Maybe { const accumulations = this._deltaMetricStorage.collect(); return this._temporalMetricStorage.buildMetrics( @@ -78,10 +74,4 @@ export class SyncMetricStorage> extends MetricStor collectionTime ); } - - static create(view: View, instrument: InstrumentDescriptor): SyncMetricStorage> { - instrument = createInstrumentDescriptorWithView(view, instrument); - const aggregator = view.aggregation.createAggregator(instrument); - return new SyncMetricStorage(instrument, aggregator, view.attributesProcessor); - } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/WritableMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/WritableMetricStorage.ts index 452ae9b7045..132754705f0 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/WritableMetricStorage.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/WritableMetricStorage.ts @@ -16,17 +16,26 @@ import { Context } from '@opentelemetry/api'; import { MetricAttributes } from '@opentelemetry/api-metrics'; +import { AttributeHashMap } from './HashMap'; /** - * Internal interface. + * Internal interface. Stores measurements and allows synchronous writes of + * measurements. * - * Stores {@link MetricData} and allows synchronous writes of measurements. + * An interface representing SyncMetricStorage with type parameters removed. */ export interface WritableMetricStorage { /** Records a measurement. */ record(value: number, attributes: MetricAttributes, context: Context): void; } -export class NoopWritableMetricStorage implements WritableMetricStorage { - record(_value: number, _attributes: MetricAttributes, _context: Context): void {} +/** + * Internal interface. Stores measurements and allows asynchronous writes of + * measurements. + * + * An interface representing AsyncMetricStorage with type parameters removed. + */ +export interface AsyncWritableMetricStorage { + /** Records a batch of measurements. */ + record(measurements: AttributeHashMap): void; } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts index aa6e8246663..9c0a881a6d6 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts @@ -23,8 +23,9 @@ import { DataPointType } from '../../src/export/MetricData'; import { MetricCollectorHandle } from '../../src/state/MetricCollector'; import { AsyncMetricStorage } from '../../src/state/AsyncMetricStorage'; import { NoopAttributesProcessor } from '../../src/view/AttributesProcessor'; -import { assertMetricData, assertDataPoint, defaultInstrumentDescriptor } from '../util'; +import { assertDataPoint, assertMetricData, defaultInstrumentDescriptor } from '../util'; import { ObservableCallback } from '@opentelemetry/api-metrics'; +import { ObservableRegistry } from '../../src/state/ObservableRegistry'; const deltaCollector: MetricCollectorHandle = { aggregatorTemporality: AggregationTemporality.DELTA, @@ -38,14 +39,19 @@ const sdkStartTime = hrTime(); class ObservableCallbackDelegate { private _delegate?: ObservableCallback; + private _callback: ObservableCallback; + constructor() { + this._callback = observableResult => { + this._delegate?.(observableResult); + }; + } + setDelegate(delegate: ObservableCallback) { this._delegate = delegate; } getCallback(): ObservableCallback { - return observableResult => { - this._delegate?.(observableResult); - }; + return this._callback; } } @@ -55,12 +61,13 @@ describe('AsyncMetricStorage', () => { const collectors = [deltaCollector]; it('should collect and reset memos', async () => { const delegate = new ObservableCallbackDelegate(); + const observableRegistry = new ObservableRegistry(); const metricStorage = new AsyncMetricStorage( defaultInstrumentDescriptor, new SumAggregator(), new NoopAttributesProcessor(), - delegate.getCallback(), ); + observableRegistry.addCallback(delegate.getCallback(), metricStorage); delegate.setDelegate(observableResult => { observableResult.observe(1, { key: '1' }); @@ -68,7 +75,8 @@ describe('AsyncMetricStorage', () => { observableResult.observe(3, { key: '3' }); }); { - const metric = await metricStorage.collect( + await observableRegistry.observe(); + const metric = metricStorage.collect( deltaCollector, collectors, sdkStartTime, @@ -84,7 +92,8 @@ describe('AsyncMetricStorage', () => { delegate.setDelegate(observableResult => {}); // The attributes should not be memorized if no measurement was reported. { - const metric = await metricStorage.collect( + await observableRegistry.observe(); + const metric = metricStorage.collect( deltaCollector, collectors, sdkStartTime, @@ -100,7 +109,8 @@ describe('AsyncMetricStorage', () => { observableResult.observe(6, { key: '3' }); }); { - const metric = await metricStorage.collect( + await observableRegistry.observe(); + const metric = metricStorage.collect( deltaCollector, [deltaCollector], sdkStartTime, @@ -120,12 +130,13 @@ describe('AsyncMetricStorage', () => { const collectors = [cumulativeCollector]; it('should collect cumulative metrics', async () => { const delegate = new ObservableCallbackDelegate(); + const observableRegistry = new ObservableRegistry(); const metricStorage = new AsyncMetricStorage( defaultInstrumentDescriptor, new SumAggregator(), new NoopAttributesProcessor(), - delegate.getCallback(), ); + observableRegistry.addCallback(delegate.getCallback(), metricStorage); delegate.setDelegate(observableResult => { observableResult.observe(1, { key: '1' }); @@ -133,7 +144,8 @@ describe('AsyncMetricStorage', () => { observableResult.observe(3, { key: '3' }); }); { - const metric = await metricStorage.collect( + await observableRegistry.observe(); + const metric = metricStorage.collect( cumulativeCollector, collectors, sdkStartTime, @@ -149,7 +161,8 @@ describe('AsyncMetricStorage', () => { delegate.setDelegate(observableResult => {}); // The attributes should be memorized even if no measurement was reported. { - const metric = await metricStorage.collect( + await observableRegistry.observe(); + const metric = metricStorage.collect( cumulativeCollector, collectors, sdkStartTime, @@ -168,7 +181,8 @@ describe('AsyncMetricStorage', () => { observableResult.observe(6, { key: '3' }); }); { - const metric = await metricStorage.collect( + await observableRegistry.observe(); + const metric = metricStorage.collect( cumulativeCollector, collectors, sdkStartTime, diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts index 1e0cd68f99c..9bd9dfa525b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts @@ -16,8 +16,8 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { Meter, MeterProvider, DataPointType } from '../../src'; -import { assertMetricData, defaultInstrumentationLibrary, defaultResource } from '../util'; +import { Meter, MeterProvider, DataPointType, ResourceMetrics } from '../../src'; +import { assertMetricData, defaultInstrumentationLibrary, defaultResource, sleep } from '../util'; import { TestMetricReader } from '../export/TestMetricReader'; import { TestDeltaMetricExporter, TestMetricExporter } from '../export/TestMetricExporter'; import { MeterSharedState } from '../../src/state/MeterSharedState'; @@ -93,5 +93,89 @@ describe('MeterSharedState', () => { })); }); + it('should collect async metrics with callbacks', async () => { + /** preparing test instrumentations */ + const { metricCollectors, meter } = setupInstruments(); + + /** creating metric events */ + let observableCalledCount = 0; + meter.createObservableCounter('test', observableResult => { + observableCalledCount++; + observableResult.observe(1); + + // async observers. + return sleep(10); + }); + + /** collect metrics */ + await Promise.all([ + // initiate collection concurrently. + ...metricCollectors.map(collector => collector.collect()), + sleep(1).then(() => metricCollectors[0].collect()), + ]); + // the callback is called each time the collection initiated. + assert.strictEqual(observableCalledCount, 3); + + /** collect metrics */ + await Promise.all([ + // initiate collection concurrently. + ...metricCollectors.map(collector => collector.collect()), + sleep(1).then(() => metricCollectors[0].collect()), + ]); + assert.strictEqual(observableCalledCount, 6); + }); + + it('should call observable callback with view-ed async instruments', async () => { + /** preparing test instrumentations */ + const { metricCollectors, meter, meterProvider } = setupInstruments(); + + /** creating metric events */ + meterProvider.addView({ name: 'foo' }, { + instrument: { + name: 'test', + }, + }); + meterProvider.addView({ name: 'bar' }, { + instrument: { + name: 'test', + }, + }); + + let observableCalledCount = 0; + meter.createObservableCounter('test', observableResult => { + observableCalledCount++; + observableResult.observe(1); + + // async observers. + return sleep(10); + }); + + function verifyResult(resourceMetrics: ResourceMetrics) { + assert.strictEqual(resourceMetrics.instrumentationLibraryMetrics.length, 1); + assert.strictEqual(resourceMetrics.instrumentationLibraryMetrics[0].metrics.length, 2); + assertMetricData(resourceMetrics.instrumentationLibraryMetrics[0].metrics[0], DataPointType.SINGULAR, { + name: 'foo' + }); + assertMetricData(resourceMetrics.instrumentationLibraryMetrics[0].metrics[1], DataPointType.SINGULAR, { + name: 'bar' + }); + } + + /** collect metrics */ + await Promise.all([ + // initiate collection concurrently. + ...metricCollectors.map(collector => collector.collect().then(verifyResult)), + sleep(1).then(() => metricCollectors[0].collect().then(verifyResult)), + ]); + assert.strictEqual(observableCalledCount, 6); + + /** collect metrics */ + await Promise.all([ + // initiate collection concurrently. + ...metricCollectors.map(collector => collector.collect().then(verifyResult)), + sleep(1).then(() => metricCollectors[0].collect().then(verifyResult)), + ]); + assert.strictEqual(observableCalledCount, 12); + }); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts index cd355a6d54d..88728043a45 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts @@ -35,8 +35,8 @@ class TestMetricStorage extends MetricStorage { collectors: MetricCollectorHandle[], sdkStartTime: HrTime, collectionTime: HrTime, - ): Promise> { - return Promise.resolve(undefined); + ): Maybe { + return undefined; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/SyncMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/SyncMetricStorage.test.ts index 6b7fe30c8c1..93de724e3d2 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/SyncMetricStorage.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/SyncMetricStorage.test.ts @@ -58,7 +58,7 @@ describe('SyncMetricStorage', () => { metricStorage.record(2, {}, api.context.active()); metricStorage.record(3, {}, api.context.active()); { - const metric = await metricStorage.collect( + const metric = metricStorage.collect( deltaCollector, collectors, sdkStartTime, @@ -71,7 +71,7 @@ describe('SyncMetricStorage', () => { // The attributes should not be memorized. { - const metric = await metricStorage.collect( + const metric = metricStorage.collect( deltaCollector, collectors, sdkStartTime, @@ -83,7 +83,7 @@ describe('SyncMetricStorage', () => { metricStorage.record(1, {}, api.context.active()); { - const metric = await metricStorage.collect( + const metric = metricStorage.collect( deltaCollector, [deltaCollector], sdkStartTime, @@ -104,7 +104,7 @@ describe('SyncMetricStorage', () => { metricStorage.record(2, {}, api.context.active()); metricStorage.record(3, {}, api.context.active()); { - const metric = await metricStorage.collect( + const metric = metricStorage.collect( cumulativeCollector, collectors, sdkStartTime, @@ -117,7 +117,7 @@ describe('SyncMetricStorage', () => { // The attributes should be memorized. { - const metric = await metricStorage.collect( + const metric = metricStorage.collect( cumulativeCollector, collectors, sdkStartTime, @@ -130,7 +130,7 @@ describe('SyncMetricStorage', () => { metricStorage.record(1, {}, api.context.active()); { - const metric = await metricStorage.collect( + const metric = metricStorage.collect( cumulativeCollector, collectors, sdkStartTime, From d65d3839a9a0c3790d9567554ef900a6953f718f Mon Sep 17 00:00:00 2001 From: legendecas Date: Tue, 19 Apr 2022 11:04:07 +0800 Subject: [PATCH 2/3] fixup! CHANGELOG --- experimental/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 58681558d42..7b0c1854b32 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -40,6 +40,7 @@ All notable changes to experimental packages in this project will be documented * feat(proto): add @opentelemetry/otlp-transformer package with hand-rolled transformation #2746 @dyladan * feat(sdk-metrics-base): shutdown and forceflush on MeterProvider #2890 @legendecas * feat(sdk-metrics-base): return the same meter for identical input to getMeter #2901 @legendecas +* feat(sdk-metrics-base): hoist async instrument callback invocations #2822 @legendecas ### :bug: (Bug Fix) From 482a74fa949a5e9bd90dc63bde028094272bfe21 Mon Sep 17 00:00:00 2001 From: legendecas Date: Fri, 6 May 2022 11:36:51 +0800 Subject: [PATCH 3/3] fixup! --- .../packages/opentelemetry-api-metrics/src/types/Meter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts b/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts index 10ddde3a189..5d3d16d668b 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts @@ -81,7 +81,7 @@ export interface Meter { /** * Creates a new `ObservableGauge` metric. * - * The callback SHOULD be reentrant safe. + * The callback SHOULD be safe to be invoked concurrently. * * @param name the name of the metric. * @param callback the observable callback @@ -96,7 +96,7 @@ export interface Meter { /** * Creates a new `ObservableCounter` metric. * - * The callback SHOULD be reentrant safe. + * The callback SHOULD be safe to be invoked concurrently. * * @param name the name of the metric. * @param callback the observable callback @@ -111,7 +111,7 @@ export interface Meter { /** * Creates a new `ObservableUpDownCounter` metric. * - * The callback SHOULD be reentrant safe. + * The callback SHOULD be safe to be invoked concurrently. * * @param name the name of the metric. * @param callback the observable callback