Skip to content
Closed
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
3f3186a
Add MeasurementProcessor specification to Metrics SDK
Blinkuu Dec 3, 2024
a8f5de3
Update TODO
Blinkuu Dec 3, 2024
1ce9e4d
Update specification/metrics/sdk.md
Blinkuu Dec 3, 2024
4b0a58d
Update specification/metrics/sdk.md
pellared Dec 3, 2024
449d2fb
Update specification/metrics/sdk.md
pellared Dec 3, 2024
60adbd3
Remove Shutdown and ForceFlush from MeasurementProcessor spec
Blinkuu Dec 6, 2024
9d60b12
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Dec 6, 2024
17f650c
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Dec 19, 2024
4cbc0ec
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jan 2, 2025
01bcc0a
feat: define built-in measurement processor
Blinkuu Jan 2, 2025
d28e993
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jan 7, 2025
90d331d
chore: update the wording
Blinkuu Jan 7, 2025
ee72e3f
chore: rename simple processor to default processor
Blinkuu Jan 7, 2025
225000a
feat: specify how we reference the next processor in the chain
Blinkuu Jan 7, 2025
8fbc341
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jan 22, 2025
f57fe00
Update specification of the `next` parameter and remove `NoopProcessor`
Blinkuu Jan 22, 2025
66c6926
Update specification/metrics/sdk.md
Blinkuu Jan 23, 2025
e585028
Update CHANGELOG.md
Blinkuu Jan 23, 2025
83a81a5
Update metrics/sdk.md
Blinkuu Jan 23, 2025
dbaffa1
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jan 23, 2025
f4c26c1
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jan 29, 2025
ebcbda8
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Feb 7, 2025
b97a231
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Feb 13, 2025
e6eec36
Ensure that the pipeline ends with DefaultProcessor
Blinkuu Feb 13, 2025
20f2977
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Feb 14, 2025
e4fbe83
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Feb 19, 2025
e706183
Apply suggestions from code review
pellared Feb 19, 2025
3ef9483
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Feb 20, 2025
00ce75f
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Feb 28, 2025
c4c9a65
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Mar 13, 2025
58baa69
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Mar 21, 2025
fc8b59d
Remove redundant CHANGELOG.md entry after conflict resolution
Blinkuu Mar 21, 2025
5c76f60
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Mar 27, 2025
45fc676
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Apr 4, 2025
edad787
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
pellared Apr 12, 2025
e872b5d
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu May 14, 2025
cb769a7
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu May 22, 2025
b4710a3
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu May 30, 2025
7f22b07
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jun 17, 2025
42781a3
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jun 17, 2025
958cb86
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jun 24, 2025
0f5e3cd
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jul 8, 2025
4242cfa
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jul 8, 2025
c8b1e76
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jul 9, 2025
756de83
Update description on DefaultProcessor
Blinkuu Jul 10, 2025
11d423b
Update sdk.md
pellared Jul 10, 2025
9cedc06
Update CHANGELOG.md
pellared Jul 10, 2025
3887c5d
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jul 15, 2025
c1a7627
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jul 19, 2025
94c43a5
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
Blinkuu Jul 21, 2025
d7254ec
Merge branch 'main' into add-measurement-processor-to-metrics-sdk-spec
cijothomas Jul 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ release.

### Metrics

- Add `MeasurementProcessor` to the Metrics SDK specification
([#4318](https://github.com/open-telemetry/opentelemetry-specification/pull/4318))
- Clarify SDK behavior for Instrument Advisory Parameter.
([#4389](https://github.com/open-telemetry/opentelemetry-specification/pull/4389))

Expand Down
67 changes: 67 additions & 0 deletions specification/metrics/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ linkTitle: SDK
+ [Instrument advisory parameter: `Attributes`](#instrument-advisory-parameter-attributes)
* [Instrument enabled](#instrument-enabled)
- [Attribute limits](#attribute-limits)
- [MeasurementProcessor](#measurementprocessor)
* [MeasurementProcessor operations](#measurementprocessor-operations)
+ [OnMeasure](#onmeasure)
* [Built-in processors](#built-in-processors)
+ [DefaultProcessor](#defaultprocessor)
- [Exemplar](#exemplar)
* [ExemplarFilter](#exemplarfilter)
+ [AlwaysOn](#alwayson)
Expand Down Expand Up @@ -1022,6 +1027,68 @@ Attributes which belong to Metrics are exempt from the
time. Attribute truncation or deletion could affect identity of metric time
series and the topic requires further analysis.

## MeasurementProcessor

**Status**: [Development](../document-status.md)

`MeasurementProcessor` is an interface which allows hooks when a `Measurement` is recorded by an `Instrument`.

Built-in measurement processors are responsible for [Measurement Processing](#measurement-processing).

`MeasurementProcessors` can be registered directly on SDK `MeterProvider` and they are invoked in the same order as they were registered.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like it would be good to specify how these are meant to be registered, similar to what we have for span processors. Can they be provided when the MeterProvider is instantiated (similar to span processors)? Does it need to be possible to dynamically register/unregister them (similar to callbacks)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion is to use the same wording as we use for Provider configuration in general.
i.e It MUST be possible to add measurement_processor as part of MeterProvider creation.
Implementations MAY allow modifications after MeterProvider is created. If they do, then all existing meter/instruments should reflect the effect of this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the exact same wording we use for LogRecordProcessor and SpanProcessor.

I think it should be consistent, it's the same concept.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should specify how MeterProviders are configured in the MeterProvider spec, not in the MeasurementProcessors spec. See this section of TracerProvider: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#configuration that @cijothomas quoted above. Make sure anything related to MeasurementProcessor is marked as Development status.


Each processor registered on the `MeterProvider` is part of a pipeline.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we consider making processors part of the View configuration? Many of the use-cases seem to apply to specific metrics (e.g. changing the unit of a metric), or aggregating specific attribute values together. It also fits nicely within the scope of what Views are meant to be able to do: Make pre-aggregation adjustments to metrics.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was considered. It looks similar, but in my opinion, Views are meant to work on a higher level of abstraction, not with individual measurements. The existing design is also deeply rooted in analysis of existing SDK implementations, where incorporating this concept into Views would be extremely difficult.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain further? Attribute filters from views are applied very early in the SDK's handling of a measurement. They apply even prior to cardinality limit enforcement. Implementing both of those features post-aggregation (i.e. not on measurements) would defeat one of their primary purpose, which is to limit memory consumption of the SDK, so I would be very surprised if they were not applied to individual measurements.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert on the Metrics SDKs, but after looking into the code when preparing this PR I concluded that supporting all the use cases we envisioned would require major overhaul of how Views work.

Please see #4298 (comment)

Perhaps I'm wrong, and there's a neat way to make Views fully programmable.

Regarding performance - MeasurementProcessor, like LogRecordProcessor and SpanProcessor is an opt-in feature. If it's not used, the cost is a single if-statement, exactly the same as with https://github.com/MrAlias/opentelemetry-go/pull/1092/files#diff-2c6f5806e27a5ab81eeba6f9d6fff1a80ac35188c8e22deea1c97a77fdb04634

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion would be to apply measurement processors immediately after the view's attribute filter, and prior to cardinality limit enforcement. The benefit of this would be that the measurement processor could reduce cardinality, and prevent hitting the limit by merging attribute values together, which is one of the intended uses.

In terms of implementation, this means you would just keep the measurement processor very close to the attribute filter (e.g. pass them to the same functions). The existing attribute filter could be thought of as a measurement processor that always comes first, and has more limited capabilities. In go, we would probably extend, or add something similar to this function to add the measurement processor in addition to the existing filter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding performance - MeasurementProcessor, like LogRecordProcessor and SpanProcessor is an opt-in feature. If it's not used, the cost is a single if-statement, exactly the same as with https://github.com/MrAlias/opentelemetry-go/pull/1092/files#diff-2c6f5806e27a5ab81eeba6f9d6fff1a80ac35188c8e22deea1c97a77fdb04634

The if statement you are referencing is in the build path. The hot-path performance has no additional branch points for the views implementation.


SDK MUST allow users to implement and configure custom processors.

SDK MUST ensure that the pipeline concludes with the built-in [DefaultProcessor](#defaultprocessor).

The following diagram shows `MeasurementProcessor`'s relationship to other components in the SDK:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please include Views in this diagram. Importantly, is View configuration applied before the Measurement processor, or after, or both? We clearly want it to be applied before the aggregation portion of views is applied, but it would be nice if it was applied after the View's attribute filter so processors don't need to consider attributes that aren't going to be kept.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Views are meant to be applied after Measurement Processors. They operate on a higher level of abstraction.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized cardinality limits should probably also be included, but we can wait until the discussion below is resolved.


```plaintext
+------------------+
| MeterProvider | +----------------------+ +-----------------+
| Meter A | Measurements... | | Measurements... | |
| Instrument X |-----------------> MeasurementProcessor +-----------------> In-memory state |
| Instrument Y + | | | |
| Meter B | +----------------------+ +-----------------+
| Instrument Z |
| ... | +----------------------+ +-----------------+
| ... | Measurements... | | Measurements... | |
| ... |-----------------> MeasurementProcessor +-----------------> In-memory state |
| ... | | | | |
| ... | +----------------------+ +-----------------+
+------------------+
```

### MeasurementProcessor operations

#### OnMeasure

`OnMeasure` is called when a `Measurement` is recorded. This method is called synchronously on the thread that emitted the `Measurement`, therefore it SHOULD NOT block or throw exceptions.

**Parameters:**

* `context` - the resolved `Context` (the explicitly passed `Context` or the current `Context`)
* `measurement` - a [Measurement](./api.md#measurement) that was recorded
* `next` - this allows the `MeasurementProcessor` to pass the measurements to the next `MeasurementProcessor` in the chain. It can be a reference to the next `MeasurementProcessor`, a bound callback to invoke `OnMeasure` on the next processor in the chain without an explicit reference to the next processor, or something else. [OpenTelemetry SDK](../overview.md#sdk) authors MAY decide the language idiomatic approach.

**Returns:** Void

For a `MeasurementProcessor` registered directly on SDK `MeterProvider`, the `measurement` mutations MUST be visible in next registered processors.

A `MeasurementProcessor` MAY freely modify `measurement` for the duration of the `OnMeasure` call.

A `MeasurementProcessor` SHOULD invoke `next`. A `MeasurementProcessor` MAY decide to drop the `Measurement` by not invoking the next processor.

### Built-in processors

The standard OpenTelemetry SDK MUST implement default processor as described below.

#### DefaultProcessor

This is an implementation of `MeasurementProcessor` which calculates an in-memory state from incoming `Measurements`.

## Exemplar

**Status**: [Stable](../document-status.md)
Expand Down
Loading