Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option for multi-instrument callbacks #2363

Merged
merged 16 commits into from Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -26,6 +26,8 @@ release.
([#2317](https://github.com/open-telemetry/opentelemetry-specification/pull/2317)).
- Clarify that expectations for user callback behavior are documentation REQUIREMENTs.
([#2361](https://github.com/open-telemetry/opentelemetry-specification/pull/2361)).
- Clarify that API support for multi-instrument callbacks is permitted.
([#2263](https://github.com/open-telemetry/opentelemetry-specification/pull/2263)).

### Logs

Expand Down
87 changes: 78 additions & 9 deletions specification/metrics/api.md
Expand Up @@ -45,6 +45,7 @@
+ [Asynchronous UpDownCounter creation](#asynchronous-updowncounter-creation)
+ [Asynchronous UpDownCounter operations](#asynchronous-updowncounter-operations)
- [Measurement](#measurement)
* [Multiple-instrument callbacks](#multiple-instrument-callbacks)
- [Compatibility requirements](#compatibility-requirements)
- [Concurrency requirements](#concurrency-requirements)

Expand Down Expand Up @@ -337,19 +338,27 @@ The API to construct asynchronous instruments MUST accept the following paramete
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
* Zero or more `callback` functions.
* Zero or more `callback` functions, responsible for reporting
[Measurement](#measurement) values of the created instrument.

The API MUST support creation of asynchronous instruments by passing
zero or more callback functions to be permanently registered to the
zero or more `callback` functions to be permanently registered to the
newly created instrument.

The API SHOULD support registration of callback functions to
The API SHOULD support registration of `callback` functions associated with
asynchronous instruments after they are created.

Where the API supports registration of callback functions after
Where the API supports registration of `callback` functions after
asynchronous instrumentation creation, it MUST return something (e.g.,
a registration handle, receipt or token) to the user that supports
reyang marked this conversation as resolved.
Show resolved Hide resolved
undoing the effect of callback registation.
undoing the effect of `callback` registation.

A Callback is the conceptual entity created each time a `callback`
function is registered through an OpenTelemetry API.

Every currently registered Callback associated with an instrument MUST
be evaluted exactly once during collection prior to reading data for
reyang marked this conversation as resolved.
Show resolved Hide resolved
that instrument.
reyang marked this conversation as resolved.
Show resolved Hide resolved

Callback functions MUST be documented as follows for the end user:

Expand All @@ -366,11 +375,28 @@ RECOMMENDATIONS is explicitly not specified at the API level.
[OpenTelemetry API](../overview.md#api) authors MAY decide what is the idiomatic
approach for capturing measurements from callback functions. Here are some examples:

* Return a list (or tuple, generator, enumerator, etc.) of `Measurement`s.
* Use an observable result argument to allow individual `Measurement`s to be
reported.
* Return a list (or tuple, generator, enumerator, etc.) of individual
`Measurement` values.
* Pass an *Observable Result* as a formal parameter of the callback,
where `result.Observe()` captures individual `Measurement` values.

Callbacks registered at the time of instrument creation MUST apply to
the single instruments which is under construction.
reyang marked this conversation as resolved.
Show resolved Hide resolved

The API MUST treat observations from a single callback as logically
Callbacks registered after the time of instrument creation MAY be
associated with multiple instruments.

Idiomatic APIs for multiple-instrument Callbacks MUST distinguish the
instrument associated with each observed `Measurement` value.

Multiple-instrument Callbacks MUST be associated at the time of
registration with a declared set of asynchronous instruments from the
same `Meter` instance. This REQUIREMENT that Instruments be
jmacd marked this conversation as resolved.
Show resolved Hide resolved
declaratively associated with Callbacks allows an SDK to execute only
those Callbacks that are necessary to evaluate instruments that are in
use by a configured [View](sdk.md#view).

The API MUST treat observations from a single Callback as logically
taking place at a single instant, such that when recorded,
observations from a single callback MUST be reported with identical
timestamps.
Expand Down Expand Up @@ -1063,6 +1089,49 @@ for the interaction between the API and SDK.
* A value
* [`Attributes`](../common/common.md#attributes)

### Multiple-instrument callbacks

[The Metrics API MAY support an interface allowing the use of multiple
instruments from a single registered
Callback](#asynchronous-instrument-api). The API to register a new
Callback SHOULD accept:

- A `callback` function
- A list (or tuple, etc.) of Instruments used in the `callback` function.

It is RECOMMENDED that the API authors use one of the following forms
for the `callback` function:

* The list (or tuple, etc.) returned by the `callback` function
contains `(Instrument, Measurement)` pairs.
* the Observable Result parameter receives an additional `(Instrument,
Measurement)` pairs

This interface is typically a more performant way to report multiple
measurements when they are obtained through an expensive process, such
as reading `/proc` files or probing the garbage collection subsystem.

For example,

```Python
# Python
class Device:
"""A device with two instruments"""

def __init__(self, meter, proeprty):
self.property = property
self.usage = meter.create_observable_counter(name="usage", description="count of items used")
self.pressure = meter.create_observable_gauge(name="pressure", description="force per unit area")

# Note the two associated instruments are passed to the callback.
meter.register_callback([self.usage, self.pressure], self.observe)
jmacd marked this conversation as resolved.
Show resolved Hide resolved
reyang marked this conversation as resolved.
Show resolved Hide resolved

def observe(self, result):
usage, pressure = expensive_system_call()
result.observe(self.usage, usage, {'property', self.property})
result.observe(self.pressure, pressure, {'property', self.property})
```

## Compatibility requirements

All the metrics components SHOULD allow new APIs to be added to
Expand Down