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

Refactor the Metrics API specification for instruments #2360

Merged
merged 9 commits into from
Feb 28, 2022
194 changes: 72 additions & 122 deletions specification/metrics/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
- [Meter](#meter)
* [Meter operations](#meter-operations)
- [Instrument](#instrument)
* [General characteristics](#general-characteristics)
+ [Instrument type conflict detection](#instrument-type-conflict-detection)
+ [Instrument namespace](#instrument-namespace)
+ [Instrument naming rule](#instrument-naming-rule)
+ [Instrument unit](#instrument-unit)
+ [Instrument description](#instrument-description)
+ [Synchronous/Asynchronous property](#synchronousasynchronous-property)
+ [Synchronous Instrument API](#synchronous-instrument-api)
+ [Asynchronous Instrument API](#asynchronous-instrument-api)
* [Counter](#counter)
+ [Counter creation](#counter-creation)
+ [Counter operations](#counter-operations)
Expand Down Expand Up @@ -193,7 +202,9 @@ are identified by all of these fields.
Language-level features such as the distinction between integer and
floating point numbers SHOULD be considered as identifying.

<a name="instrument-type-conflict-detection"></a>
### General characteristics

#### Instrument type conflict detection

When more than one Instrument of the same `name` is created for
identical Meters, denoted *duplicate instrument registration*, the
Expand Down Expand Up @@ -221,13 +232,13 @@ model](datamodel.md#opentelemetry-protocol-data-model-producer-recommendations)
when more than one `Metric` is written for a given instrument `name`
and Meter identity by the same MeterProvider.

<a name="instrument-namespace"></a>
#### Instrument namespace

Distinct Meters MUST be treated as separate namespaces for the
purposes of detecting [duplicate instrument registration
conflicts](#instrument-type-conflict-detection).

<a name="instrument-naming-rule"></a>
#### Instrument naming rule

Instrument names MUST conform to the following syntax (described using the
[Augmented Backus-Naur Form](https://tools.ietf.org/html/rfc5234)):
Expand All @@ -246,7 +257,7 @@ DIGIT = %x30-39 ; 0-9
and '-'.
* They can have a maximum length of 63 characters.

<a name="instrument-unit"></a>
#### Instrument unit

The `unit` is an optional string provided by the author of the Instrument. It
SHOULD be treated as an opaque string from the API and SDK (e.g. the SDK is not
Expand All @@ -261,7 +272,7 @@ expected to validate the unit of measurement, or perform the unit conversion).
runtimes) to be stored and compared as fixed size array/struct when
performance is critical.

<a name="instrument-description"></a>
#### Instrument description

The `description` is an optional free-form text provided by the author of the
instrument. It MUST be treated as an opaque string from the API and SDK.
Expand All @@ -280,16 +291,14 @@ instrument. It MUST be treated as an opaque string from the API and SDK.
Instruments are categorized on whether they are synchronous or
asynchronous:

<a name="synchronous-instrument"></a>
#### Synchronous/Asynchronous property

* Synchronous instruments (e.g. [Counter](#counter)) are meant to be invoked
inline with application/business processing logic. For example, an HTTP client
could use a Counter to record the number of bytes it has received.
[Measurements](#measurement) recorded by synchronous instruments can be
associated with the [Context](../context/context.md).

<a name="asynchronous-instrument"></a>
jmacd marked this conversation as resolved.
Show resolved Hide resolved

* Asynchronous instruments (e.g. [Asynchronous Gauge](#asynchronous-gauge)) give
the user a way to register callback function, and the callback function will
be invoked only on demand (see SDK [collection](sdk.md#collect) for reference). For example, a piece of embedded software
Expand All @@ -302,6 +311,29 @@ Please note that the term *synchronous* and *asynchronous* have nothing to do
with the [asynchronous
pattern](https://en.wikipedia.org/wiki/Asynchronous_method_invocation).

#### Synchronous Instrument API

The API to construct synchronous instruments MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).

#### Asynchronous Instrument API

The API to construct asynchronous instruments MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
* Zero or more `callback` functions.

The API MUST support creation of asynchronous instruments by passing
zero or more callback functions to be permanently registered to the
newly created instrument.
Expand All @@ -314,16 +346,39 @@ asynchronous instrumentation creation, it MUST return something (e.g.,
a registration handle, receipt or token) to the user that supports
undoing the effect of callback registation.

The `callback` function is responsible for reporting
[Measurement](#measurement)s. It will only be called when the Meter is being
observed. [OpenTelemetry API](../overview.md#api) authors SHOULD define whether
this callback function needs to be reentrant safe / thread safe or not.

Callback functions SHOULD NOT take an indefinite amount of time.

Callback functions SHOULD NOT make duplicate observations from asynchronous
instrument callbacks. The resulting behavior when a callback observes
multiple values for identical instrument and attributes is explicitly
not specified.

[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.

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.

The API SHOULD provide some way to pass `state` to the
callback. [OpenTelemetry API](../overview.md#api) authors MAY decide
what is the idiomatic approach (e.g. it could be an additional
parameter to the callback function, or captured by the lambda closure,
or something else).

### Counter

`Counter` is a [synchronous Instrument](#synchronous-instrument) which supports
`Counter` is a [synchronous Instrument](#synchronous-instrument-api) which supports
non-negative increments.

Example uses for `Counter`:
Expand All @@ -342,14 +397,7 @@ desired, [OpenTelemetry API](../overview.md#api) authors MAY decide the language
idiomatic name(s), for example `CreateUInt64Counter`, `CreateDoubleCounter`,
`CreateCounter<UInt64>`, `CreateCounter<double>`.

The API MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
See the [general requirements for synchronous instruments](#synchronous-instrument-api).

Here are some examples that [OpenTelemetry API](../overview.md#api) authors
might consider:
Expand Down Expand Up @@ -445,20 +493,7 @@ a strong reason not to do so. Please note that the name has nothing to do with
pattern](https://en.wikipedia.org/wiki/Asynchronous_method_invocation) and
[observer pattern](https://en.wikipedia.org/wiki/Observer_pattern).

The API MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
* Zero or more `callback` functions. [See the general requirements](#asynchronous-instrument).

The `callback` function is responsible for reporting
[Measurement](#measurement)s. It will only be called when the Meter is being
observed. [OpenTelemetry API](../overview.md#api) authors SHOULD define whether
this callback function needs to be reentrant safe / thread safe or not.
See the [general requirements for asynchronous instruments](#asynchronous-instrument-api).

Note: Unlike [Counter.Add()](#add) which takes the increment/delta value, the
callback function reports the absolute value of the counter. To determine the
Expand Down Expand Up @@ -566,7 +601,7 @@ class Device:

### Histogram

`Histogram` is a [synchronous Instrument](#synchronous-instrument) which can be
`Histogram` is a [synchronous Instrument](#synchronous-instrument-api) which can be
used to report arbitrary values that are likely to be statistically meaningful.
It is intended for statistics such as histograms, summaries, and percentile.

Expand All @@ -583,14 +618,7 @@ desired, [OpenTelemetry API](../overview.md#api) authors MAY decide the language
idiomatic name(s), for example `CreateUInt64Histogram`, `CreateDoubleHistogram`,
`CreateHistogram<UInt64>`, `CreateHistogram<double>`.

The API MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
See the [general requirements for synchronous instruments](#synchronous-instrument-api).

Here are some examples that [OpenTelemetry API](../overview.md#api) authors
might consider:
Expand Down Expand Up @@ -683,42 +711,7 @@ a strong reason not to do so. Please note that the name has nothing to do with
pattern](https://en.wikipedia.org/wiki/Asynchronous_method_invocation) and
[observer pattern](https://en.wikipedia.org/wiki/Observer_pattern).

The API MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
* Zero or more `callback` functions. [See the general requirements](#asynchronous-instrument).

The `callback` function is responsible for reporting
[Measurement](#measurement)s. It will only be called when the Meter is being
observed. [OpenTelemetry API](../overview.md#api) authors SHOULD define whether
this callback function needs to be reentrant safe / thread safe or not.

[OpenTelemetry API](../overview.md#api) authors MAY decide what is the idiomatic
approach. 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.

User code is recommended not to provide more than one `Measurement` with the
same `attributes` in a single callback. If it happens, the
[SDK](./README.md#sdk) can decide how to handle it. For example, during the
callback invocation if two measurements `value=3.38, attributes={cpu:1, core:2}`
and `value=3.51, attributes={cpu:1, core:2}` are reported, the SDK can decide to
simply let them pass through (so the downstream consumer can handle
duplication), drop the entire data, pick the last one, or something else. The
jmacd marked this conversation as resolved.
Show resolved Hide resolved
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.

The API SHOULD provide some way to pass `state` to the callback. [OpenTelemetry
API](../overview.md#api) authors MAY decide what is the idiomatic approach (e.g.
it could be an additional parameter to the callback function, or captured by the
lambda closure, or something else).
See the [general requirements for asynchronous instruments](#asynchronous-instrument-api).

Here are some examples that [OpenTelemetry API](../overview.md#api) authors
might consider:
Expand Down Expand Up @@ -802,7 +795,7 @@ class Device:

### UpDownCounter

`UpDownCounter` is a [synchronous Instrument](#synchronous-instrument) which
`UpDownCounter` is a [synchronous Instrument](#synchronous-instrument-api) which
supports increments and decrements.

Note: if the value is
Expand Down Expand Up @@ -878,14 +871,7 @@ idiomatic name(s), for example `CreateInt64UpDownCounter`,
`CreateDoubleUpDownCounter`, `CreateUpDownCounter<Int64>`,
`CreateUpDownCounter<double>`.

The API MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
See the [general requirements for synchronous instruments](#synchronous-instrument-api).

Here are some examples that [OpenTelemetry API](../overview.md#api) authors
might consider:
Expand Down Expand Up @@ -976,49 +962,13 @@ note that the name has nothing to do with [asynchronous
pattern](https://en.wikipedia.org/wiki/Asynchronous_method_invocation) and
[observer pattern](https://en.wikipedia.org/wiki/Observer_pattern).

The API MUST accept the following parameters:

* The `name` of the Instrument, following the [instrument naming
rule](#instrument-naming-rule).
* An optional `unit` of measure, following the [instrument unit
rule](#instrument-unit).
* An optional `description`, following the [instrument description
rule](#instrument-description).
* Zero or more `callback` functions. [See the general requirements](#asynchronous-instrument).

The `callback` function is responsible for reporting
[Measurement](#measurement)s. It will only be called when the Meter is being
observed. [OpenTelemetry API](../overview.md#api) authors SHOULD define whether
this callback function needs to be reentrant safe / thread safe or not.
See the [general requirements for asynchronous instruments](#asynchronous-instrument-api).

Note: Unlike [UpDownCounter.Add()](#add-1) which takes the increment/delta value,
the callback function reports the absolute value of the Asynchronous
UpDownCounter. To determine the reported rate the Asynchronous UpDownCounter is
changing, the difference between successive measurements is used.

[OpenTelemetry API](../overview.md#api) authors MAY decide what is the idiomatic
approach. 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.

User code is recommended not to provide more than one `Measurement` with the
same `attributes` in a single callback. If it happens, the
[SDK](./README.md#sdk) MAY decide how to handle it. For example, during the
callback invocation if two measurements `value=1, attributes={pid:4,
bitness:64}` and `value=2, attributes={pid:4, bitness:64}` are reported, the SDK
can decide to simply let them pass through (so the downstream consumer can
handle duplication), drop the entire data, pick the last one, or something else.
jmacd marked this conversation as resolved.
Show resolved Hide resolved
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.

The API SHOULD provide some way to pass `state` to the callback. [OpenTelemetry
API](../overview.md#api) authors MAY decide what is the idiomatic approach (e.g.
it could be an additional parameter to the callback function, or captured by the
lambda closure, or something else).

Here are some examples that [OpenTelemetry API](../overview.md#api) authors
might consider:

Expand Down