Skip to content

Commit b5eca96

Browse files
committed
feat(metrics): add advisory attributes parameter to metric instruments
- Add experimental `attributes` parameter to MetricAdvice interface - Implement attribute filtering via ViewRegistry default views - Only applies when no Views are configured for the instrument - Views take precedence over advisory attributes when present - Add comprehensive unit and integration tests - Update documentation and changelogs Closes #4365
1 parent 957e0bf commit b5eca96

File tree

6 files changed

+59
-117
lines changed

6 files changed

+59
-117
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
1414

1515
### :rocket: Features
1616

17+
* feat(metrics): add advisory attributes parameter to metric instruments [#4365](https://github.com/open-telemetry/opentelemetry-js/issues/4365)
18+
* Added experimental `attributes` parameter to `MetricAdvice` for filtering measurement attributes
19+
* Only applies when no Views are configured for the instrument
20+
* Views take precedence over advisory attributes when present
21+
1722
### :bug: Bug Fixes
1823

1924
* fix(sdk-metrics): Remove invalid default value for `startTime` param to ExponentialHistogramAccumulation. This only impacted the closurescript compiler. [#5763](https://github.com/open-telemetry/opentelemetry-js/pull/5763) @trentm

api/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ All notable changes to this project will be documented in this file.
99

1010
### :rocket: (Enhancement)
1111

12+
* feat(metrics): add advisory attributes parameter to metric instruments [#4365](https://github.com/open-telemetry/opentelemetry-js/issues/4365)
13+
* Added experimental `attributes` parameter to `MetricAdvice` interface
14+
* Allows specifying an allow-list of attribute keys for metric instruments
15+
1216
* feat(api): improve isValidSpanId, isValidTraceId performance [#5714](https://github.com/open-telemetry/opentelemetry-js/pull/5714) @seemk
1317
* feat(diag): change types in `DiagComponentLogger` from `any` to `unknown`[#5478](https://github.com/open-telemetry/opentelemetry-js/pull/5478) @loganrosen
1418

api/src/metrics/Metric.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ export interface MetricAdvice {
3535
* @experimental
3636
* An allow-list of attribute keys for this instrument. Only these keys will be kept
3737
* on measurements recorded by this instrument. If not provided, all attributes are kept.
38+
*
39+
* @example <caption>only keep 'service' and 'version' attributes</caption>
40+
* attributes: ['service', 'version']
41+
* @example <caption>keep all attributes (default behavior)</caption>
42+
* attributes: undefined
3843
*/
3944
attributes?: string[];
4045
}

packages/sdk-metrics/README.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,6 @@ const counter = opentelemetry.metrics.getMeter('default').createCounter('foo');
3636
counter.add(1, { attributeKey: 'attribute-value' });
3737
```
3838

39-
### Advisory Attributes Parameter (Experimental)
40-
41-
The Metrics API supports an optional `attributes` advisory parameter in the `advice` configuration when creating instruments. This parameter acts as an allow-list for attribute keys, filtering out all attributes that are not in the specified list:
42-
43-
```js
44-
const counter = opentelemetry.metrics.getMeter('default').createCounter('filtered-counter', {
45-
description: 'A counter with attribute filtering',
46-
advice: {
47-
attributes: ['service', 'version'], // @experimental: Only these keys will be kept
48-
},
49-
});
50-
51-
// Only 'service' and 'version' attributes will be recorded, others are filtered out
52-
counter.add(1, {
53-
service: 'api-gateway',
54-
version: '1.0.0',
55-
region: 'us-west', // This will be filtered out
56-
method: 'GET' // This will be filtered out
57-
});
58-
```
59-
60-
**Note:** This feature is experimental and may change in future versions. The advisory attributes parameter only applies when no Views are configured for the instrument. If Views are present, they take precedence over the instrument's advisory attributes.
61-
6239
In conditions, we may need to setup an async instrument to observe costly events:
6340

6441
```js
@@ -102,6 +79,29 @@ const meterProvider = new MeterProvider({
10279
})
10380
```
10481

82+
## Advisory Attributes (Experimental)
83+
84+
The Metrics API supports an optional `attributes` advisory parameter in the `advice` configuration when creating instruments. This parameter acts as an allow-list for attribute keys, filtering out all attributes that are not in the specified list:
85+
86+
```js
87+
const counter = opentelemetry.metrics.getMeter('default').createCounter('filtered-counter', {
88+
description: 'A counter with attribute filtering',
89+
advice: {
90+
attributes: ['service', 'version'], // @experimental: Only these keys will be kept
91+
},
92+
});
93+
94+
// Only 'service' and 'version' attributes will be recorded, others are filtered out
95+
counter.add(1, {
96+
service: 'api-gateway',
97+
version: '1.0.0',
98+
region: 'us-west', // This will be filtered out
99+
method: 'GET' // This will be filtered out
100+
});
101+
```
102+
103+
**Note:** This feature is experimental and may change in future versions. The advisory attributes parameter only applies when no Views are configured for the instrument. If Views are present, they take precedence over the instrument's advisory attributes.
104+
105105
## Example
106106

107107
See [examples/prometheus](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/examples/prometheus) for an end-to-end example, including exporting metrics.

packages/sdk-metrics/examples/advisory-attributes.js

Lines changed: 0 additions & 81 deletions
This file was deleted.

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { InstrumentationScope } from '@opentelemetry/core';
1818
import { InstrumentDescriptor } from '../InstrumentDescriptor';
1919
import { InstrumentSelector } from './InstrumentSelector';
2020
import { MeterSelector } from './MeterSelector';
21-
import { View } from './View';
21+
import { View, ViewOptions } from './View';
2222
import { createAllowListAttributesProcessor } from './AttributesProcessor';
2323

2424
export class ViewRegistry {
@@ -39,29 +39,38 @@ export class ViewRegistry {
3939
);
4040
});
4141

42-
// If no registered views match, create a default view with instrument's advisory attributes
42+
// Only create a default view if advisory attributes are set and non-empty
4343
if (views.length === 0) {
44-
const defaultView = this._createDefaultView(instrument);
45-
return [defaultView];
44+
if (
45+
instrument.advice &&
46+
Array.isArray(instrument.advice.attributes) &&
47+
instrument.advice.attributes.length > 0
48+
) {
49+
return [this._createDefaultView(instrument)];
50+
}
51+
// No matching views and no advisory attributes: return empty array for backward compatibility
52+
return [];
4653
}
4754

4855
return views;
4956
}
5057

5158
private _createDefaultView(instrument: InstrumentDescriptor): View {
52-
// Create default view with instrument's advisory attributes as an allow-list
53-
const viewOptions: any = {
59+
const viewOptions: ViewOptions = {
5460
instrumentName: instrument.name,
5561
instrumentType: instrument.type,
5662
instrumentUnit: instrument.unit,
5763
};
58-
59-
// If instrument has advisory attributes, use them as an allow-list
60-
if (instrument.advice.attributes && instrument.advice.attributes.length > 0) {
61-
viewOptions.attributesProcessors = [createAllowListAttributesProcessor(instrument.advice.attributes)];
64+
65+
if (
66+
instrument.advice.attributes &&
67+
instrument.advice.attributes.length > 0
68+
) {
69+
viewOptions.attributesProcessors = [
70+
createAllowListAttributesProcessor(instrument.advice.attributes),
71+
];
6272
}
63-
64-
// Create a view that matches this specific instrument
73+
6574
return new View(viewOptions);
6675
}
6776

@@ -89,4 +98,4 @@ export class ViewRegistry {
8998
selector.getSchemaUrlFilter().match(meter.schemaUrl))
9099
);
91100
}
92-
}
101+
}

0 commit comments

Comments
 (0)