-
Notifications
You must be signed in to change notification settings - Fork 889
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
MeterProvider and Meter API spec #1557
Changes from all commits
0fc42f0
a76816c
102f90e
3e77ad7
ea0836e
7be4588
88d89a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
# Metrics API | ||
|
||
**Status**: [Experimental](../document-status.md) | ||
|
||
**Owner:** | ||
|
||
* [Reiley Yang](https://github.com/reyang) | ||
|
||
**Domain Experts:** | ||
|
||
* [Bogdan Brutu](https://github.com/bogdandrutu) | ||
* [Josh Suereth](https://github.com/jsuereth) | ||
* [Joshua MacDonald](https://github.com/jmacd) | ||
|
||
Note: this specification is subject to major changes. To avoid thrusting | ||
language client maintainers, we don't recommend OpenTelemetry clients to start | ||
the implementation unless explicitly communicated via | ||
[OTEP](https://github.com/open-telemetry/oteps#opentelemetry-enhancement-proposal-otep). | ||
|
||
<details> | ||
<summary> | ||
Table of Contents | ||
</summary> | ||
|
||
* [Overview](#overview) | ||
* [MeterProvider](#meterprovider) | ||
* [MeterProvider operations](#meterprovider-operations) | ||
* [Meter](#meter) | ||
* [Meter operations](#meter-operations) | ||
* [Instrument](#instrument) | ||
* [Counter](#counter) | ||
* [Counter Creation](#counter-creation) | ||
* [Measurement](#measurement) | ||
|
||
</details> | ||
|
||
## Overview | ||
|
||
The Metrics API consists of these main components: | ||
|
||
* [MeterProvider](#meterprovider) is the entry point of the API. It provides | ||
access to `Meters`. | ||
* [Meter](#meter) is the class responsible for creating `Instruments`. | ||
* [Instrument](#instrument) is responsible for reporting | ||
[Measurements](#measurement). | ||
|
||
Here is an example of the object hierarchy inside a process instrumented with the | ||
metrics API: | ||
|
||
```text | ||
+-- MeterProvider(default) | ||
| | ||
+-- Meter(name='io.opentelemetry.runtime', version='1.0.0') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know .NET might be a bit unique here. It's fine if MeterProvider has an API to create a Meter but we were intending that .NET libraries will also be able to create Meter directly (similar to ActivitySource), and that we would recommend them to do so. Thus on .NET MeterProvider needs to be able to subscribe to a Meter that already exists. I don't care whether the spec calls it out, but I want to make sure this isn't taking anyone by surprise in the design process. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be the same approach as what |
||
| | | ||
| +-- instruments... | ||
| | ||
+-- Meter(name='io.opentelemetry.contrib.mongodb.client', version='2.3.0') | ||
| | ||
+-- Instrument<Counter, int>(name='client.exception', attributes=['type'], unit='1') | ||
| | ||
+-- instruments... | ||
+-- MeterProvider(custom) | ||
| | ||
+-- Meter(name='bank.payment', version='23.3.5') | ||
| | ||
+-- instruments... | ||
``` | ||
|
||
## MeterProvider | ||
|
||
`Meter`s can be accessed with a `MeterProvider`. | ||
|
||
In implementations of the API, the `MeterProvider` is expected to be the | ||
stateful object that holds any configuration. | ||
|
||
Normally, the `MeterProvider` is expected to be accessed from a central place. | ||
Thus, the API SHOULD provide a way to set/register and access a global default | ||
`MeterProvider`. | ||
|
||
Notwithstanding any global `MeterProvider`, some applications may want to or | ||
have to use multiple `MeterProvider` instances, e.g. to have different | ||
configuration for each, or because its easier with dependency injection | ||
frameworks. Thus, implementations of `MeterProvider` SHOULD allow creating an | ||
arbitrary number of `MeterProvider` instances. | ||
|
||
### MeterProvider operations | ||
|
||
The `MeterProvider` MUST provide the following functions: | ||
|
||
* Get a `Meter` | ||
|
||
#### Get a Meter | ||
|
||
This API MUST accept the following parameters: | ||
|
||
* `name` (required): This name must identify the [instrumentation | ||
library](../overview.md#instrumentation-libraries) (e.g. | ||
`io.opentelemetry.contrib.mongodb`). If an application or library has built-in | ||
OpenTelemetry instrumentation, both [Instrumented | ||
library](../glossary.md#instrumented-library) and [Instrumentation | ||
library](../glossary.md#instrumentation-library) may refer to the same | ||
library. In that scenario, the `name` denotes a module name or component name | ||
within that library or application. In case an invalid name (null or empty | ||
string) is specified, a working Meter implementation MUST be returned as a | ||
fallback rather than returning null or throwing an exception, its `name` | ||
property SHOULD keep the original invalid value, and a message reporting that | ||
the specified value is invalid SHOULD be logged. A library, implementing the | ||
OpenTelemetry API *may* also ignore this name and return a default instance | ||
for all calls, if it does not support "named" functionality (e.g. an | ||
implementation which is not even observability-related). A MeterProvider | ||
could also return a no-op Meter here if application owners configure the SDK | ||
to suppress telemetry produced by this library. | ||
* `version` (optional): Specifies the version of the instrumentation library | ||
(e.g. `1.0.0`). | ||
|
||
It is unspecified whether or under which conditions the same or different | ||
`Meter` instances are returned from this functions. | ||
|
||
Implementations MUST NOT require users to repeatedly obtain a `Meter` again with | ||
the same name+version to pick up configuration changes. This can be achieved | ||
either by allowing to work with an outdated configuration or by ensuring that | ||
new configuration applies also to previously returned `Meter`s. | ||
|
||
Note: This could, for example, be implemented by storing any mutable | ||
configuration in the `MeterProvider` and having `Meter` implementation objects | ||
have a reference to the `MeterProvider` from which they were obtained. If | ||
configuration must be stored per-meter (such as disabling a certain meter), the | ||
meter could, for example, do a look-up with its name+version in a map in the | ||
`MeterProvider`, or the `MeterProvider` could maintain a registry of all | ||
returned `Meter`s and actively update their configuration if it changes. | ||
|
||
## Meter | ||
|
||
The meter is responsible for creating [Instruments](#instrument). | ||
|
||
Note: `Meter` SHOULD NOT be responsible for the configuration. This should be | ||
the responsibility of the `MeterProvider` instead. | ||
|
||
### Meter operations | ||
|
||
The `Meter` MUST provide functions to create new [Instruments](#instrument): | ||
|
||
* [Create a new Counter](#counter-creation) (see the section on `Counter`) | ||
|
||
## Instrument | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to say anything about the lifetime of these objects? I'm fine if lifetime is left as the language implementer's choice, or if the spec wants to declare something more specific. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is fine to not specify the lifetime here (similar like the trace spec). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK I'm assuming anything not specified is implicitly implementer's choice : ) |
||
|
||
Instruments are used to report [Measurements](#measurement). Each Instrument | ||
will have the following information: | ||
|
||
* The `name` of the Instrument | ||
* The `kind` of the Instrument - whether it is a [Counter](#counter) or other | ||
instruments, whether it is synchronous or asynchronous | ||
* An optional `unit of measure` | ||
* An optional `description` | ||
* An optional list of [`Attribute`](../common/common.md#attributes) names and | ||
types | ||
|
||
Instruments are associated with the Meter during creation, and are identified by | ||
the name: | ||
|
||
* Meter implementations MUST return an error when multiple Instruments are | ||
registered under the same Meter instance using the same name. | ||
* Different Meters MUST be treated as separate namespaces. The names of the | ||
Instruments under one Meter SHOULD NOT interfere with Instruments under | ||
another Meter. | ||
Comment on lines
+164
to
+166
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jmacd mentioned in Slack:
However, unless I'm misreading, I don't see this explicitly stated here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "are identified by their name". Maybe that need some highlights/implciations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm assuming this is related to: #1113 |
||
|
||
Instrument names MUST conform to the following syntax (described using the | ||
[Augmented Backus-Naur Form](https://tools.ietf.org/html/rfc5234)): | ||
|
||
```abnf | ||
instrument-name = ALPHA 0*62 ("_" / "." / "-" / ALPHA / DIGIT) | ||
ALPHA = %x41-5A / %x61-7A; A-Z / a-z | ||
DIGIT = %x30-39 ; 0-9 | ||
``` | ||
|
||
* They are not null or empty strings. | ||
* They are case-insensitive, ASCII strings. | ||
* The first character must be an alphabetic character. | ||
reyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* Subsequent characters must belong to the alphanumeric characters, '_', '.', | ||
and '-'. | ||
* They can have a maximum length of 63 characters. | ||
reyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Counter | ||
|
||
#### Counter Creation | ||
|
||
## Measurement | ||
|
||
A `Measurement` represents a data point reported via the metrics API to the SDK. | ||
Please refer to the [Metrics Programming Model](./README.md#programming-model) | ||
for the interaction between the API and SDK. | ||
|
||
`Measurement`s encapsulate: | ||
|
||
* A value | ||
* [`Attributes`](../common/common.md#attributes) | ||
|
||
## Concurrency | ||
|
||
For languages which support concurrent execution the Metrics APIs provide | ||
specific guarantees and safeties. | ||
|
||
**MeterProvider** - all methods are safe to be called concurrently. | ||
|
||
**Meter** - all methods are safe to be called concurrently. | ||
|
||
**Instrument** - All methods of any Instrument are safe to be called | ||
concurrently. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NB: This is questioned in #1503 and might be removed again.
cc @bogdandrutu