Skip to content

Commit 48b60c9

Browse files
authored
refactor: batch observer to be independent from metric types (#1709)
* refactor: batch observer to be independent from metric types - BatchObservers do not have to be created with names - BatchObservers do not have instruments for their own * fixup: nodejs v8 compatibilities * fixup: replace all batch observer metric occurrences with batch observer
1 parent 74d6e45 commit 48b60c9

File tree

9 files changed

+95
-159
lines changed

9 files changed

+95
-159
lines changed

examples/metrics/metrics/observer.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const cpuUsageMetric = meter.createValueObserver('cpu_usage_per_app', {
4040
description: 'Example of sync value observer used with async batch observer',
4141
});
4242

43-
meter.createBatchObserver('metric_batch_observer', (observerBatchResult) => {
43+
meter.createBatchObserver((observerBatchResult) => {
4444
Promise.all([
4545
someAsyncMetrics(),
4646
// simulate waiting

packages/opentelemetry-api/src/metrics/Meter.ts

+5-8
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ import {
2020
Counter,
2121
ValueRecorder,
2222
ValueObserver,
23-
BatchObserver,
24-
BatchMetricOptions,
23+
BatchObserverOptions,
2524
UpDownCounter,
2625
SumObserver,
2726
UpDownSumObserver,
@@ -108,15 +107,13 @@ export interface Meter {
108107
): UpDownSumObserver;
109108

110109
/**
111-
* Creates a new `BatchObserver` metric, can be used to update many metrics
110+
* Creates a new `BatchObserver`, can be used to update many metrics
112111
* at the same time and when operations needs to be async
113-
* @param name the name of the metric.
114112
* @param callback the batch observer callback
115-
* @param [options] the metric batch options.
113+
* @param [options] the batch observer options.
116114
*/
117115
createBatchObserver(
118-
name: string,
119116
callback: (batchObserverResult: BatchObserverResult) => void,
120-
options?: BatchMetricOptions
121-
): BatchObserver;
117+
options?: BatchObserverOptions
118+
): void;
122119
}

packages/opentelemetry-api/src/metrics/Metric.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,16 @@ export interface MetricOptions {
6666
boundaries?: number[];
6767
}
6868

69-
export interface BatchMetricOptions extends MetricOptions {
69+
export interface BatchObserverOptions {
7070
/**
7171
* Indicates how long the batch metric should wait to update before cancel
7272
*/
7373
maxTimeoutUpdateMS?: number;
74+
75+
/**
76+
* User provided logger.
77+
*/
78+
logger?: Logger;
7479
}
7580

7681
/** The Type of value. It describes how the data is reported. */
@@ -166,9 +171,6 @@ export type UpDownSumObserver = BaseObserver;
166171
/** Base interface for the SumObserver metrics. */
167172
export type SumObserver = BaseObserver;
168173

169-
/** Base interface for the Batch Observer metrics. */
170-
export type BatchObserver = Metric;
171-
172174
/**
173175
* key-value pairs passed by the user.
174176
*/

packages/opentelemetry-api/src/metrics/NoopMeter.ts

+4-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
Counter,
2424
ValueRecorder,
2525
ValueObserver,
26-
BatchObserver,
2726
UpDownCounter,
2827
BaseObserver,
2928
UpDownSumObserver,
@@ -119,10 +118,9 @@ export class NoopMeter implements Meter {
119118
* @param callback the batch observer callback
120119
*/
121120
createBatchObserver(
122-
_name: string,
123121
_callback: (batchObserverResult: BatchObserverResult) => void
124-
): BatchObserver {
125-
return NOOP_BATCH_OBSERVER_METRIC;
122+
): NoopBatchObserver {
123+
return NOOP_BATCH_OBSERVER;
126124
}
127125
}
128126

@@ -187,9 +185,7 @@ export class NoopBaseObserverMetric
187185
}
188186
}
189187

190-
export class NoopBatchObserverMetric
191-
extends NoopMetric<void>
192-
implements BatchObserver {}
188+
export class NoopBatchObserver {}
193189

194190
export class NoopBoundCounter implements BoundCounter {
195191
add(_value: number): void {
@@ -229,4 +225,4 @@ export const NOOP_SUM_OBSERVER_METRIC = new NoopBaseObserverMetric(
229225
NOOP_BOUND_BASE_OBSERVER
230226
);
231227

232-
export const NOOP_BATCH_OBSERVER_METRIC = new NoopBatchObserverMetric();
228+
export const NOOP_BATCH_OBSERVER = new NoopBatchObserver();

packages/opentelemetry-metrics/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ const MemUsageMetric = meter.createValueObserver('mem_usage_per_app', {
222222
description: 'Memory',
223223
});
224224

225-
meter.createBatchObserver('metric_batch_observer', (observerBatchResult) => {
225+
meter.createBatchObserver((observerBatchResult) => {
226226
getSomeAsyncMetrics().then(metrics => {
227227
observerBatchResult.observe({ app: 'myApp' }, [
228228
cpuUsageMetric.observation(metrics.value1),

packages/opentelemetry-metrics/src/BatchObserverMetric.ts renamed to packages/opentelemetry-metrics/src/BatchObserver.ts

+11-36
Original file line numberDiff line numberDiff line change
@@ -15,57 +15,32 @@
1515
*/
1616

1717
import * as api from '@opentelemetry/api';
18-
import { InstrumentationLibrary } from '@opentelemetry/core';
19-
import { Resource } from '@opentelemetry/resources';
18+
import { Logger, NoopLogger } from '@opentelemetry/api';
2019
import { BatchObserverResult } from './BatchObserverResult';
21-
import { BoundObserver } from './BoundInstrument';
22-
import { Processor } from './export/Processor';
23-
import { MetricKind, MetricRecord } from './export/types';
24-
import { Metric } from './Metric';
20+
import { MetricRecord } from './export/types';
2521

2622
const NOOP_CALLBACK = () => {};
2723
const MAX_TIMEOUT_UPDATE_MS = 500;
2824

29-
/** This is a SDK implementation of Batch Observer Metric. */
30-
export class BatchObserverMetric
31-
extends Metric<BoundObserver>
32-
implements api.BatchObserver {
25+
/** This is a SDK implementation of Batch Observer. */
26+
export class BatchObserver {
3327
private _callback: (observerResult: api.BatchObserverResult) => void;
3428
private _maxTimeoutUpdateMS: number;
29+
private _logger: Logger;
3530

3631
constructor(
37-
name: string,
38-
options: api.BatchMetricOptions,
39-
private readonly _processor: Processor,
40-
resource: Resource,
41-
instrumentationLibrary: InstrumentationLibrary,
32+
options: api.BatchObserverOptions,
4233
callback?: (observerResult: api.BatchObserverResult) => void
4334
) {
44-
super(
45-
name,
46-
options,
47-
MetricKind.BATCH_OBSERVER,
48-
resource,
49-
instrumentationLibrary
50-
);
35+
this._logger = options.logger ?? new NoopLogger();
5136
this._maxTimeoutUpdateMS =
5237
options.maxTimeoutUpdateMS ?? MAX_TIMEOUT_UPDATE_MS;
5338
this._callback = callback || NOOP_CALLBACK;
5439
}
5540

56-
protected _makeInstrument(labels: api.Labels): BoundObserver {
57-
return new BoundObserver(
58-
labels,
59-
this._disabled,
60-
this._valueType,
61-
this._logger,
62-
this._processor.aggregatorFor(this._descriptor)
63-
);
64-
}
65-
66-
getMetricRecord(): Promise<MetricRecord[]> {
41+
collect(): Promise<MetricRecord[]> {
6742
this._logger.debug('getMetricRecord - start');
68-
return new Promise((resolve, reject) => {
43+
return new Promise(resolve => {
6944
const observerResult = new BatchObserverResult();
7045

7146
// cancels after MAX_TIMEOUT_MS - no more waiting for results
@@ -74,14 +49,14 @@ export class BatchObserverMetric
7449
// remove callback to prevent user from updating the values later if
7550
// for any reason the observerBatchResult will be referenced
7651
observerResult.onObserveCalled();
77-
super.getMetricRecord().then(resolve, reject);
52+
resolve();
7853
this._logger.debug('getMetricRecord - timeout');
7954
}, this._maxTimeoutUpdateMS);
8055

8156
// sets callback for each "observe" method
8257
observerResult.onObserveCalled(() => {
8358
clearTimeout(timer);
84-
super.getMetricRecord().then(resolve, reject);
59+
resolve();
8560
this._logger.debug('getMetricRecord - end');
8661
});
8762

packages/opentelemetry-metrics/src/BatchObserverResult.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class BatchObserverResult implements api.BatchObserverResult {
2626
* Cancels the further updates.
2727
* This is used to prevent updating the value of result that took too
2828
* long to update. For example to avoid update after timeout.
29-
* See {@link BatchObserverMetric.getMetricRecord}
29+
* See {@link BatchObserver.collect}
3030
*/
3131
cancelled = false;
3232

packages/opentelemetry-metrics/src/Meter.ts

+15-43
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
import * as api from '@opentelemetry/api';
1818
import { ConsoleLogger, InstrumentationLibrary } from '@opentelemetry/core';
1919
import { Resource } from '@opentelemetry/resources';
20-
import { BatchObserverMetric } from './BatchObserverMetric';
20+
import { BatchObserver } from './BatchObserver';
2121
import { BaseBoundInstrument } from './BoundInstrument';
2222
import { Processor } from './export/Processor';
23-
import { MetricKind } from './export/types';
2423
import { UpDownCounterMetric } from './UpDownCounterMetric';
2524
import { CounterMetric } from './CounterMetric';
2625
import { UpDownSumObserverMetric } from './UpDownSumObserverMetric';
@@ -38,6 +37,7 @@ import { NoopExporter } from './export/NoopExporter';
3837
*/
3938
export class Meter implements api.Meter {
4039
private readonly _logger: api.Logger;
40+
private readonly _batchObservers: BatchObserver[] = [];
4141
private readonly _metrics = new Map<string, Metric<BaseBoundInstrument>>();
4242
private readonly _processor: Processor;
4343
private readonly _resource: Resource;
@@ -258,36 +258,20 @@ export class Meter implements api.Meter {
258258
}
259259

260260
/**
261-
* Creates a new batch observer metric.
262-
* @param name the name of the metric.
261+
* Creates a new batch observer.
263262
* @param callback the batch observer callback
264-
* @param [options] the metric batch options.
263+
* @param [options] the batch options.
265264
*/
266265
createBatchObserver(
267-
name: string,
268266
callback: (observerResult: api.BatchObserverResult) => void,
269-
options: api.BatchMetricOptions = {}
270-
): api.BatchObserver {
271-
if (!this._isValidName(name)) {
272-
this._logger.warn(
273-
`Invalid metric name ${name}. Defaulting to noop metric implementation.`
274-
);
275-
return api.NOOP_BATCH_OBSERVER_METRIC;
276-
}
277-
const opt: api.BatchMetricOptions = {
267+
options: api.BatchObserverOptions = {}
268+
): BatchObserver {
269+
const opt: api.BatchObserverOptions = {
278270
logger: this._logger,
279-
...DEFAULT_METRIC_OPTIONS,
280271
...options,
281272
};
282-
const batchObserver = new BatchObserverMetric(
283-
name,
284-
opt,
285-
this._processor,
286-
this._resource,
287-
this._instrumentationLibrary,
288-
callback
289-
);
290-
this._registerMetric(name, batchObserver);
273+
const batchObserver = new BatchObserver(opt, callback);
274+
this._batchObservers.push(batchObserver);
291275
return batchObserver;
292276
}
293277

@@ -300,27 +284,15 @@ export class Meter implements api.Meter {
300284
*/
301285
async collect(): Promise<void> {
302286
// call batch observers first
303-
const batchObservers = Array.from(this._metrics.values())
304-
.filter(metric => {
305-
return metric.getKind() === MetricKind.BATCH_OBSERVER;
306-
})
307-
.map(metric => {
308-
return metric.getMetricRecord();
309-
});
310-
await Promise.all(batchObservers).then(records => {
311-
records.forEach(metrics => {
312-
metrics.forEach(metric => this._processor.process(metric));
313-
});
287+
const observations = this._batchObservers.map(observer => {
288+
return observer.collect();
314289
});
290+
await Promise.all(observations);
315291

316292
// after this all remaining metrics can be run
317-
const metrics = Array.from(this._metrics.values())
318-
.filter(metric => {
319-
return metric.getKind() !== MetricKind.BATCH_OBSERVER;
320-
})
321-
.map(metric => {
322-
return metric.getMetricRecord();
323-
});
293+
const metrics = Array.from(this._metrics.values()).map(metric => {
294+
return metric.getMetricRecord();
295+
});
324296

325297
await Promise.all(metrics).then(records => {
326298
records.forEach(metrics => {

0 commit comments

Comments
 (0)