Skip to content

Commit 297e837

Browse files
obecnymayurkale22
andauthored
feat: adding new metric: up down sum observer (open-telemetry#1272)
Co-authored-by: Mayur Kale <[email protected]>
1 parent 9b905a1 commit 297e837

File tree

9 files changed

+328
-20
lines changed

9 files changed

+328
-20
lines changed

examples/metrics/metrics/observer.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ const meter = new MeterProvider({
2222

2323
meter.createValueObserver('cpu_core_usage', {
2424
description: 'Example of a sync value observer with callback',
25-
}, (observerResult) => { // this callback is called once per each interval
25+
}, async (observerResult) => { // this callback is called once per each interval
26+
await new Promise((resolve) => {
27+
setTimeout(()=> {resolve()}, 50);
28+
});
2629
observerResult.observe(getRandomValue(), { core: '1' });
2730
observerResult.observe(getRandomValue(), { core: '2' });
2831
});

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,12 @@ export interface BaseObserver extends UnboundMetric<BoundBaseObserver> {
173173
};
174174
}
175175

176-
/** Base interface for the Value Observer metrics. */
176+
/** Base interface for the ValueObserver metrics. */
177177
export type ValueObserver = BaseObserver;
178178

179+
/** Base interface for the UpDownSumObserver metrics. */
180+
export type UpDownSumObserver = BaseObserver;
181+
179182
/** Base interface for the Batch Observer metrics. */
180183
export type BatchObserver = Metric;
181184

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

+3
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,7 @@ export const NOOP_BOUND_BASE_OBSERVER = new NoopBoundBaseObserver();
202202
export const NOOP_VALUE_OBSERVER_METRIC = new NoopBaseObserverMetric(
203203
NOOP_BOUND_BASE_OBSERVER
204204
);
205+
export const NOOP_UP_DOWN_SUM_OBSERVER_METRIC = new NoopBaseObserverMetric(
206+
NOOP_BOUND_BASE_OBSERVER
207+
);
205208
export const NOOP_BATCH_OBSERVER_METRIC = new NoopBatchObserverMetric();

packages/opentelemetry-metrics/README.md

+61-4
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,75 @@ boundCounter.add(Math.random() > 0.5 ? 1 : -1);
7676

7777
### Value Observer
7878

79-
Choose this kind of metric when only last value is important without worry about aggregation
79+
Choose this kind of metric when only last value is important without worry about aggregation.
80+
The callback can be sync or async.
8081

8182
```js
8283
const { MeterProvider } = require('@opentelemetry/metrics');
8384

8485
const meter = new MeterProvider().getMeter('your-meter-name');
8586

86-
meter.createValueObserver('cpu_core_usage', {
87+
88+
// async callback - for operation that needs to wait for value
89+
meter.createValueObserver('your_metric_name', {
90+
description: 'Example of an async observer with callback',
91+
}, async (observerResult) => {
92+
const value = await getAsyncValue();
93+
observerResult.observe(value, { label: '1' });
94+
});
95+
96+
function getAsyncValue() {
97+
return new Promise((resolve) => {
98+
setTimeout(()=> {
99+
resolve(Math.random());
100+
}, 100);
101+
});
102+
}
103+
104+
// sync callback in case you don't need to wait for value
105+
meter.createValueObserver('your_metric_name', {
106+
description: 'Example of a sync observer with callback',
107+
}, (observerResult) => {
108+
observerResult.observe(getRandomValue(), { label: '1' });
109+
observerResult.observe(getRandomValue(), { label: '2' });
110+
});
111+
112+
function getRandomValue() {
113+
return Math.random();
114+
}
115+
```
116+
117+
### UpDownSumObserver
118+
119+
Choose this kind of metric when sum is important and you want to capture any value that starts at zero and rises or falls throughout the process lifetime.
120+
The callback can be sync or async.
121+
122+
```js
123+
const { MeterProvider } = require('@opentelemetry/metrics');
124+
125+
const meter = new MeterProvider().getMeter('your-meter-name');
126+
127+
// async callback - for operation that needs to wait for value
128+
meter.createUpDownSumObserver('your_metric_name', {
129+
description: 'Example of an async observer with callback',
130+
}, async (observerResult) => {
131+
const value = await getAsyncValue();
132+
observerResult.observe(value, { label: '1' });
133+
});
134+
135+
function getAsyncValue() {
136+
return new Promise((resolve) => {
137+
setTimeout(()=> {
138+
resolve(Math.random());
139+
}, 100);
140+
});
141+
}
142+
143+
// sync callback in case you don't need to wait for value
144+
meter.createUpDownSumObserver('your_metric_name', {
87145
description: 'Example of a sync observer with callback',
88146
}, (observerResult) => {
89-
observerResult.observe(getRandomValue(), { core: '1' });
90-
observerResult.observe(getRandomValue(), { core: '2' });
147+
observerResult.observe(getRandomValue(), { label: '1' });
91148
});
92149

93150
function getRandomValue() {

packages/opentelemetry-metrics/src/BaseObserverMetric.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const NOOP_CALLBACK = () => {};
3030
*/
3131
export abstract class BaseObserverMetric extends Metric<BoundObserver>
3232
implements api.BaseObserver {
33-
protected _callback: (observerResult: api.ObserverResult) => void;
33+
protected _callback: (observerResult: api.ObserverResult) => unknown;
3434

3535
constructor(
3636
name: string,
@@ -39,7 +39,7 @@ export abstract class BaseObserverMetric extends Metric<BoundObserver>
3939
resource: Resource,
4040
metricKind: MetricKind,
4141
instrumentationLibrary: InstrumentationLibrary,
42-
callback?: (observerResult: api.ObserverResult) => void
42+
callback?: (observerResult: api.ObserverResult) => unknown
4343
) {
4444
super(name, options, metricKind, resource, instrumentationLibrary);
4545
this._callback = callback || NOOP_CALLBACK;
@@ -55,9 +55,9 @@ export abstract class BaseObserverMetric extends Metric<BoundObserver>
5555
);
5656
}
5757

58-
getMetricRecord(): Promise<MetricRecord[]> {
58+
async getMetricRecord(): Promise<MetricRecord[]> {
5959
const observerResult = new ObserverResult();
60-
this._callback(observerResult);
60+
await this._callback(observerResult);
6161
observerResult.values.forEach((value, labels) => {
6262
const instrument = this.bind(labels);
6363
instrument.update(value);

packages/opentelemetry-metrics/src/Meter.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { BatchObserverMetric } from './BatchObserverMetric';
2121
import { BaseBoundInstrument } from './BoundInstrument';
2222
import { UpDownCounterMetric } from './UpDownCounterMetric';
2323
import { CounterMetric } from './CounterMetric';
24+
import { UpDownSumObserverMetric } from './UpDownSumObserverMetric';
2425
import { ValueRecorderMetric } from './ValueRecorderMetric';
2526
import { Metric } from './Metric';
2627
import { ValueObserverMetric } from './ValueObserverMetric';
@@ -156,15 +157,15 @@ export class Meter implements api.Meter {
156157
}
157158

158159
/**
159-
* Creates a new value observer metric.
160+
* Creates a new `ValueObserver` metric.
160161
* @param name the name of the metric.
161162
* @param [options] the metric options.
162163
* @param [callback] the value observer callback
163164
*/
164165
createValueObserver(
165166
name: string,
166167
options: api.MetricOptions = {},
167-
callback?: (observerResult: api.ObserverResult) => void
168+
callback?: (observerResult: api.ObserverResult) => unknown
168169
): api.ValueObserver {
169170
if (!this._isValidName(name)) {
170171
this._logger.warn(
@@ -189,6 +190,40 @@ export class Meter implements api.Meter {
189190
return valueObserver;
190191
}
191192

193+
/**
194+
* Creates a new `UpDownSumObserver` metric.
195+
* @param name the name of the metric.
196+
* @param [options] the metric options.
197+
* @param [callback] the value observer callback
198+
*/
199+
createUpDownSumObserver(
200+
name: string,
201+
options: api.MetricOptions = {},
202+
callback?: (observerResult: api.ObserverResult) => unknown
203+
): api.UpDownSumObserver {
204+
if (!this._isValidName(name)) {
205+
this._logger.warn(
206+
`Invalid metric name ${name}. Defaulting to noop metric implementation.`
207+
);
208+
return api.NOOP_UP_DOWN_SUM_OBSERVER_METRIC;
209+
}
210+
const opt: api.MetricOptions = {
211+
logger: this._logger,
212+
...DEFAULT_METRIC_OPTIONS,
213+
...options,
214+
};
215+
const upDownSumObserver = new UpDownSumObserverMetric(
216+
name,
217+
opt,
218+
this._batcher,
219+
this._resource,
220+
this._instrumentationLibrary,
221+
callback
222+
);
223+
this._registerMetric(name, upDownSumObserver);
224+
return upDownSumObserver;
225+
}
226+
192227
/**
193228
* Creates a new batch observer metric.
194229
* @param name the name of the metric.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as api from '@opentelemetry/api';
18+
import { InstrumentationLibrary } from '@opentelemetry/core';
19+
import { Resource } from '@opentelemetry/resources';
20+
import { BaseObserverMetric } from './BaseObserverMetric';
21+
import { Batcher } from './export/Batcher';
22+
import { MetricKind } from './export/types';
23+
24+
/** This is a SDK implementation of UpDownSumObserver Metric. */
25+
export class UpDownSumObserverMetric extends BaseObserverMetric
26+
implements api.UpDownSumObserver {
27+
constructor(
28+
name: string,
29+
options: api.MetricOptions,
30+
batcher: Batcher,
31+
resource: Resource,
32+
instrumentationLibrary: InstrumentationLibrary,
33+
callback?: (observerResult: api.ObserverResult) => unknown
34+
) {
35+
super(
36+
name,
37+
options,
38+
batcher,
39+
resource,
40+
MetricKind.UP_DOWN_SUM_OBSERVER,
41+
instrumentationLibrary,
42+
callback
43+
);
44+
}
45+
}

packages/opentelemetry-metrics/src/ValueObserverMetric.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class ValueObserverMetric extends BaseObserverMetric
2929
batcher: Batcher,
3030
resource: Resource,
3131
instrumentationLibrary: InstrumentationLibrary,
32-
callback?: (observerResult: api.ObserverResult) => void
32+
callback?: (observerResult: api.ObserverResult) => unknown
3333
) {
3434
super(
3535
name,

0 commit comments

Comments
 (0)