Skip to content

Commit b6e532b

Browse files
feat(metrics): prototype experimental advice support (#3876)
Co-authored-by: Marc Pichler <[email protected]>
1 parent f8e187b commit b6e532b

22 files changed

+252
-56
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/
1111

1212
### :rocket: (Enhancement)
1313

14+
* feat(metrics): prototype experimental advice support [#3876](https://github.com/open-telemetry/opentelemetry-js/pull/3876) @legendecas
15+
1416
### :bug: (Bug Fix)
1517

1618
### :books: (Refine Doc)

api/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
## Unreleased
66

7+
### :rocket: (Enhancement)
8+
9+
* feat(metrics): prototype experimental advice support [#3876](https://github.com/open-telemetry/opentelemetry-js/pull/3876) @legendecas
10+
711
## 1.6.0
812

913
### :bug: (Bug Fix)

api/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export {
5151
ObservableUpDownCounter,
5252
UpDownCounter,
5353
BatchObservableCallback,
54+
MetricAdvice,
5455
MetricAttributes,
5556
MetricAttributeValue,
5657
ObservableCallback,

api/src/metrics/Metric.ts

+18
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ import { Attributes, AttributeValue } from '../common/Attributes';
1818
import { Context } from '../context/types';
1919
import { BatchObservableResult, ObservableResult } from './ObservableResult';
2020

21+
/**
22+
* Advisory options influencing aggregation configuration parameters.
23+
* @experimental
24+
*/
25+
export interface MetricAdvice {
26+
/**
27+
* Hint the explicit bucket boundaries for SDK if the metric is been
28+
* aggregated with a HistogramAggregator.
29+
*/
30+
explicitBucketBoundaries?: number[];
31+
}
32+
2133
/**
2234
* Options needed for metric creation
2335
*/
@@ -39,6 +51,12 @@ export interface MetricOptions {
3951
* @default {@link ValueType.DOUBLE}
4052
*/
4153
valueType?: ValueType;
54+
55+
/**
56+
* The advice influencing aggregation configuration parameters.
57+
* @experimental
58+
*/
59+
advice?: MetricAdvice;
4260
}
4361

4462
/** The Type of value. It describes how the data is reported. */

packages/sdk-metrics/src/InstrumentDescriptor.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { MetricOptions, ValueType, diag } from '@opentelemetry/api';
17+
import {
18+
MetricAdvice,
19+
MetricOptions,
20+
ValueType,
21+
diag,
22+
} from '@opentelemetry/api';
1823
import { View } from './view/View';
1924
import { equalsCaseInsensitive } from './utils';
2025

@@ -31,14 +36,21 @@ export enum InstrumentType {
3136
}
3237

3338
/**
34-
* An interface describing the instrument.
39+
* An internal interface describing the instrument.
40+
*
41+
* This is intentionally distinguished from the public MetricDescriptor (a.k.a. InstrumentDescriptor)
42+
* which may not contains internal fields like metric advice.
3543
*/
3644
export interface InstrumentDescriptor {
3745
readonly name: string;
3846
readonly description: string;
3947
readonly unit: string;
4048
readonly type: InstrumentType;
4149
readonly valueType: ValueType;
50+
/**
51+
* @experimental
52+
*/
53+
readonly advice: MetricAdvice;
4254
}
4355

4456
export function createInstrumentDescriptor(
@@ -57,6 +69,7 @@ export function createInstrumentDescriptor(
5769
description: options?.description ?? '',
5870
unit: options?.unit ?? '',
5971
valueType: options?.valueType ?? ValueType.DOUBLE,
72+
advice: options?.advice ?? {},
6073
};
6174
}
6275

@@ -70,6 +83,7 @@ export function createInstrumentDescriptorWithView(
7083
type: instrument.type,
7184
unit: instrument.unit,
7285
valueType: instrument.valueType,
86+
advice: instrument.advice,
7387
};
7488
}
7589

packages/sdk-metrics/src/ObservableResult.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
} from '@opentelemetry/api';
2525
import { AttributeHashMap } from './state/HashMap';
2626
import { isObservableInstrument, ObservableInstrument } from './Instruments';
27-
import { InstrumentDescriptor } from '.';
2827

2928
/**
3029
* The class implements {@link ObservableResult} interface.
@@ -35,24 +34,24 @@ export class ObservableResultImpl implements ObservableResult {
3534
*/
3635
_buffer = new AttributeHashMap<number>();
3736

38-
constructor(private _descriptor: InstrumentDescriptor) {}
37+
constructor(
38+
private _instrumentName: string,
39+
private _valueType: ValueType
40+
) {}
3941

4042
/**
4143
* Observe a measurement of the value associated with the given attributes.
4244
*/
4345
observe(value: number, attributes: MetricAttributes = {}): void {
4446
if (typeof value !== 'number') {
4547
diag.warn(
46-
`non-number value provided to metric ${this._descriptor.name}: ${value}`
48+
`non-number value provided to metric ${this._instrumentName}: ${value}`
4749
);
4850
return;
4951
}
50-
if (
51-
this._descriptor.valueType === ValueType.INT &&
52-
!Number.isInteger(value)
53-
) {
52+
if (this._valueType === ValueType.INT && !Number.isInteger(value)) {
5453
diag.warn(
55-
`INT value type cannot accept a floating-point value for ${this._descriptor.name}, ignoring the fractional digits.`
54+
`INT value type cannot accept a floating-point value for ${this._instrumentName}, ignoring the fractional digits.`
5655
);
5756
value = Math.trunc(value);
5857
// ignore non-finite values.

packages/sdk-metrics/src/aggregator/Drop.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
import { HrTime } from '@opentelemetry/api';
1818
import { AggregationTemporality } from '../export/AggregationTemporality';
19-
import { MetricData } from '../export/MetricData';
20-
import { InstrumentDescriptor } from '../InstrumentDescriptor';
19+
import { MetricData, MetricDescriptor } from '../export/MetricData';
2120
import { Maybe } from '../utils';
2221
import { AggregatorKind, Aggregator, AccumulationRecord } from './types';
2322

@@ -38,7 +37,7 @@ export class DropAggregator implements Aggregator<undefined> {
3837
}
3938

4039
toMetricData(
41-
_descriptor: InstrumentDescriptor,
40+
_descriptor: MetricDescriptor,
4241
_aggregationTemporality: AggregationTemporality,
4342
_accumulationByAttributes: AccumulationRecord<undefined>[],
4443
_endTime: HrTime

packages/sdk-metrics/src/aggregator/ExponentialHistogram.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ import {
2424
import {
2525
DataPointType,
2626
ExponentialHistogramMetricData,
27+
MetricDescriptor,
2728
} from '../export/MetricData';
2829
import { diag, HrTime } from '@opentelemetry/api';
29-
import { InstrumentDescriptor, InstrumentType } from '../InstrumentDescriptor';
30+
import { InstrumentType } from '../InstrumentDescriptor';
3031
import { Maybe } from '../utils';
3132
import { AggregationTemporality } from '../export/AggregationTemporality';
3233
import { Buckets } from './exponential-histogram/Buckets';
@@ -555,7 +556,7 @@ export class ExponentialHistogramAggregator
555556
}
556557

557558
toMetricData(
558-
descriptor: InstrumentDescriptor,
559+
descriptor: MetricDescriptor,
559560
aggregationTemporality: AggregationTemporality,
560561
accumulationByAttributes: AccumulationRecord<ExponentialHistogramAccumulation>[],
561562
endTime: HrTime

packages/sdk-metrics/src/aggregator/Histogram.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ import {
2020
Aggregator,
2121
AggregatorKind,
2222
} from './types';
23-
import { DataPointType, HistogramMetricData } from '../export/MetricData';
23+
import {
24+
DataPointType,
25+
HistogramMetricData,
26+
MetricDescriptor,
27+
} from '../export/MetricData';
2428
import { HrTime } from '@opentelemetry/api';
25-
import { InstrumentDescriptor, InstrumentType } from '../InstrumentDescriptor';
29+
import { InstrumentType } from '../InstrumentDescriptor';
2630
import { binarySearchLB, Maybe } from '../utils';
2731
import { AggregationTemporality } from '../export/AggregationTemporality';
2832

@@ -207,7 +211,7 @@ export class HistogramAggregator implements Aggregator<HistogramAccumulation> {
207211
}
208212

209213
toMetricData(
210-
descriptor: InstrumentDescriptor,
214+
descriptor: MetricDescriptor,
211215
aggregationTemporality: AggregationTemporality,
212216
accumulationByAttributes: AccumulationRecord<HistogramAccumulation>[],
213217
endTime: HrTime

packages/sdk-metrics/src/aggregator/LastValue.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ import {
2323
} from './types';
2424
import { HrTime } from '@opentelemetry/api';
2525
import { millisToHrTime, hrTimeToMicroseconds } from '@opentelemetry/core';
26-
import { DataPointType, GaugeMetricData } from '../export/MetricData';
27-
import { InstrumentDescriptor } from '../InstrumentDescriptor';
26+
import {
27+
DataPointType,
28+
GaugeMetricData,
29+
MetricDescriptor,
30+
} from '../export/MetricData';
2831
import { Maybe } from '../utils';
2932
import { AggregationTemporality } from '../export/AggregationTemporality';
3033

@@ -103,7 +106,7 @@ export class LastValueAggregator implements Aggregator<LastValueAccumulation> {
103106
}
104107

105108
toMetricData(
106-
descriptor: InstrumentDescriptor,
109+
descriptor: MetricDescriptor,
107110
aggregationTemporality: AggregationTemporality,
108111
accumulationByAttributes: AccumulationRecord<LastValueAccumulation>[],
109112
endTime: HrTime

packages/sdk-metrics/src/aggregator/Sum.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ import {
2222
AccumulationRecord,
2323
} from './types';
2424
import { HrTime } from '@opentelemetry/api';
25-
import { DataPointType, SumMetricData } from '../export/MetricData';
26-
import { InstrumentDescriptor } from '../InstrumentDescriptor';
25+
import {
26+
DataPointType,
27+
MetricDescriptor,
28+
SumMetricData,
29+
} from '../export/MetricData';
2730
import { Maybe } from '../utils';
2831
import { AggregationTemporality } from '../export/AggregationTemporality';
2932

@@ -109,7 +112,7 @@ export class SumAggregator implements Aggregator<SumAccumulation> {
109112
}
110113

111114
toMetricData(
112-
descriptor: InstrumentDescriptor,
115+
descriptor: MetricDescriptor,
113116
aggregationTemporality: AggregationTemporality,
114117
accumulationByAttributes: AccumulationRecord<SumAccumulation>[],
115118
endTime: HrTime

packages/sdk-metrics/src/aggregator/types.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
import { HrTime, MetricAttributes } from '@opentelemetry/api';
1818
import { AggregationTemporality } from '../export/AggregationTemporality';
19-
import { MetricData } from '../export/MetricData';
20-
import { InstrumentDescriptor } from '../InstrumentDescriptor';
19+
import { MetricData, MetricDescriptor } from '../export/MetricData';
2120
import { Maybe } from '../utils';
2221

2322
/** The kind of aggregator. */
@@ -128,14 +127,14 @@ export interface Aggregator<T> {
128127
/**
129128
* Returns the {@link MetricData} that this {@link Aggregator} will produce.
130129
*
131-
* @param descriptor the metric instrument descriptor.
130+
* @param descriptor the metric descriptor.
132131
* @param aggregationTemporality the temporality of the resulting {@link MetricData}
133132
* @param accumulationByAttributes the array of attributes and accumulation pairs.
134133
* @param endTime the end time of the metric data.
135134
* @return the {@link MetricData} that this {@link Aggregator} will produce.
136135
*/
137136
toMetricData(
138-
descriptor: InstrumentDescriptor,
137+
descriptor: MetricDescriptor,
139138
aggregationTemporality: AggregationTemporality,
140139
accumulationByAttributes: AccumulationRecord<T>[],
141140
endTime: HrTime

packages/sdk-metrics/src/export/MetricData.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,30 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { HrTime, MetricAttributes } from '@opentelemetry/api';
17+
import { HrTime, MetricAttributes, ValueType } from '@opentelemetry/api';
1818
import { InstrumentationScope } from '@opentelemetry/core';
1919
import { IResource } from '@opentelemetry/resources';
20-
import { InstrumentDescriptor } from '../InstrumentDescriptor';
20+
import { InstrumentType } from '../InstrumentDescriptor';
2121
import { AggregationTemporality } from './AggregationTemporality';
2222
import { Histogram, ExponentialHistogram } from '../aggregator/types';
2323

24+
export interface MetricDescriptor {
25+
readonly name: string;
26+
readonly description: string;
27+
readonly unit: string;
28+
/**
29+
* @deprecated exporter should avoid depending on the type of the instrument
30+
* as their resulting aggregator can be re-mapped with views.
31+
*/
32+
readonly type: InstrumentType;
33+
readonly valueType: ValueType;
34+
}
35+
2436
/**
2537
* Basic metric data fields.
2638
*/
2739
interface BaseMetricData {
28-
readonly descriptor: InstrumentDescriptor;
40+
readonly descriptor: MetricDescriptor;
2941
readonly aggregationTemporality: AggregationTemporality;
3042
/**
3143
* DataPointType of the metric instrument.

packages/sdk-metrics/src/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { MetricDescriptor } from './export/MetricData';
18+
1719
export {
1820
Sum,
1921
LastValue,
@@ -38,6 +40,7 @@ export {
3840
ResourceMetrics,
3941
ScopeMetrics,
4042
MetricData,
43+
MetricDescriptor,
4144
CollectionResult,
4245
} from './export/MetricData';
4346

@@ -56,7 +59,11 @@ export { ConsoleMetricExporter } from './export/ConsoleMetricExporter';
5659

5760
export { MetricCollectOptions, MetricProducer } from './export/MetricProducer';
5861

59-
export { InstrumentDescriptor, InstrumentType } from './InstrumentDescriptor';
62+
export { InstrumentType } from './InstrumentDescriptor';
63+
/**
64+
* @deprecated Use {@link MetricDescriptor} instead.
65+
*/
66+
export type InstrumentDescriptor = MetricDescriptor;
6067

6168
export { MeterProvider, MeterProviderOptions } from './MeterProvider';
6269

packages/sdk-metrics/src/state/MetricStorage.ts

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export abstract class MetricStorage {
5454
description: description,
5555
valueType: this._instrumentDescriptor.valueType,
5656
unit: this._instrumentDescriptor.unit,
57+
advice: this._instrumentDescriptor.advice,
5758
}
5859
);
5960
}

packages/sdk-metrics/src/state/ObservableRegistry.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ export class ObservableRegistry {
144144

145145
private _observeCallbacks(observationTime: HrTime, timeoutMillis?: number) {
146146
return this._callbacks.map(async ({ callback, instrument }) => {
147-
const observableResult = new ObservableResultImpl(instrument._descriptor);
147+
const observableResult = new ObservableResultImpl(
148+
instrument._descriptor.name,
149+
instrument._descriptor.valueType
150+
);
148151
let callPromise: Promise<void> = Promise.resolve(
149152
callback(observableResult)
150153
);

packages/sdk-metrics/src/view/Aggregation.ts

+5
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ export class DefaultAggregation extends Aggregation {
184184
return LAST_VALUE_AGGREGATION;
185185
}
186186
case InstrumentType.HISTOGRAM: {
187+
if (instrument.advice.explicitBucketBoundaries) {
188+
return new ExplicitBucketHistogramAggregation(
189+
instrument.advice.explicitBucketBoundaries
190+
);
191+
}
187192
return HISTOGRAM_AGGREGATION;
188193
}
189194
}

0 commit comments

Comments
 (0)