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

Metrics SDK spec skeleton #1673

Merged
merged 13 commits into from
May 20, 2021
2 changes: 1 addition & 1 deletion specification/metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ SDK](../overview.md#sdk) concept concept for more information.
## Specifications

* [Metrics API](./api.md)
* Metrics SDK (not available yet)
* [Metrics SDK](./sdk.md)
* [Metrics Data Model and Protocol](datamodel.md)
* [Semantic Conventions](./semantic_conventions/README.md)

Expand Down
144 changes: 144 additions & 0 deletions specification/metrics/sdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Metrics SDK

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

**Owner:**

* [Reiley Yang](https://github.com/reyang)

**Domain Experts:**

* [Bogdan Drutu](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>

* [MeterProvider](#meterprovider)
* [MeasurementProcessor](#measurementprocessor)
* [MetricProcessor](#metricprocessor)
* [MetricExporter](#metricexporter)
* [Push Metric Exporter](#push-metric-exporter)
* [Pull Metric Exporter](#pull-metric-exporter)

</details>

## MeterProvider

TODO:

* Allow multiple pipelines (processors, exporters).
* Configure "Views".
* Configure timing (related to [issue
1432](https://github.com/open-telemetry/opentelemetry-specification/issues/1432)).

## MeasurementProcessor

`MeasurementProcessor` is an interface which allows hooks when a
[Measurement](./api.md#measurement) is recorded by an
jsuereth marked this conversation as resolved.
Show resolved Hide resolved
[Instrument](./api.md#instrument).

`MeasurementProcessor` MUST have access to:

* The `Measurement`
* The `Instrument`, which is used to report the `Measurement`
* The `Resource`, which is associated with the `MeterProvider`

In addition to things listed above, if the `Measurement` is reported by a
synchronous `Instrument` (e.g. [Counter](./api.md#counter)),
`MeasurementProcessor` MUST have access to:

* [Baggage](../baggage/api.md)
* [Context](../context/context.md)
* The [Span](../trace/api.md#span) which is associated with the `Measurement`

Depending on the programming language and runtime model, these can be provided
explicitly (e.g. as input arguments) or implicitly (e.g. [implicit
Context](../context/context.md#optional-global-operations) and the [currently
active span](../trace/api.md#context-interaction)).

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

## MetricProcessor
Copy link
Contributor

Choose a reason for hiding this comment

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

@reyang

Your current pipeline is...

[API/SDK] -> measurement -> [1. MeasurementProcessor] -> [2. MetricProcessor <-> [**In-Memory-State**]] -> metric -> [3. MetricExporter]

Maybe we can fully expand to...

[API/SDK] -> measurement -> [1. MeasurementProcessor]* -> measurement -> [2. MetricProcessor <-> [**In-Memory-State**]] -> [MetricCollector] -> metric -> [MetricEnricher] -> metric -> [3. MetricExporter]

MeasurementProcessor: Allows adjustment to attributes. Can be chained/composed.

MetricCollector: Collect aggregated metrics from In-Memory-State. This is likely build-in/internal to SDK.

MetricEnricher: Allows custom adjustment to metrics. Can be chained/composed.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is something I intended to avoid 😃

I think the goal is to start from a small set of essential (ideally must-have) LEGO pieces, and depending on what we've learned while building the SDKs we can decide to introduce more if there is a strong reason.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 on avoiding this kind of strictness until there's a strong reason (thinking about mistakes I've made) 🤣


`MetricProcessor` is an interface which allows hooks for [pre-aggregated metrics
data](./datamodel.md#timeseries-model).

Built-in metric processors are responsible for batching and conversion of
metrics data to exportable representation and passing batches to exporters.

The following diagram shows `MetricProcessor`'s relationship to other components
in the SDK:

```text
+-----------------+ +-----------------+ +-----------------------+
| | Metrics... | | Metrics... | |
> In-memory state | -----------> MetricProcessor | -----------> MetricExporter (push) |--> Another process
| | | | | |
+-----------------+ +-----------------+ +-----------------------+

+-----------------+ +-----------------+ +-----------------------+
| | Metrics... | | Metrics... | |
> In-memory state |------------> MetricProcessor |------------> MetricExporter (pull) |--> Another process (scraper)
| | | | | |
+-----------------+ +-----------------+ +-----------------------+
```

## MetricExporter

`MetricExporter` defines the interface that protocol-specific exporters must
implement so that they can be plugged into OpenTelemetry SDK and support sending
of telemetry data.

The goal of the interface is to minimize burden of implementation for
protocol-dependent telemetry exporters. The protocol exporter is expected to be
primarily a simple telemetry data encoder and transmitter.

Metric Exporter has access to the [pre-aggregated metrics
Copy link
Contributor

@victlu victlu May 14, 2021

Choose a reason for hiding this comment

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

Can you clarify a bit on how Metric Exporter gain access to pre-aggregated metrics? Is it that it has access to the "in-memory state" or is it passed those via the MetricProcessor?

What is the "input" to MetricExporter? Is it metrics (pre/post aggregation?) or is it some batch / "exportable representation" format?

It may be helpful to label the arrows (like you did for input to in-memory state) between In-memory state, MetricProcessor, and MetricExporter.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've updated the diagram to clarify that exporters don't have direct access to the "in-memory-state", and it receives (whether pulls from, or being pushed) pre-aggregated metrics from the processor.

Copy link
Member Author

Choose a reason for hiding this comment

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

The "input" should be a batch of "exportable representation", similar to the tracing SDK spec https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#exportbatch. These are the meats that we'll need to add in subsequent PRs.

data](./datamodel.md#timeseries-model).

There could be multiple [Push Metric Exporters](#push-metric-exporter) or [Pull
reyang marked this conversation as resolved.
Show resolved Hide resolved
Metric Exporters](#pull-metric-exporter) or even a mixture of both configured on
a given `MeterProvider`. Different exporters can run at different schedule, for
example:

* Exporter A is a push exporter which sends data every 1 minute.
* Exporter B is a push exporter which sends data every 5 seconds.
* Exporter C is a pull exporter which reacts to a scraper over HTTP.
* Exporter D is a pull exporter which reacts to another scraper over a named
pipe.

### Push Metric Exporter

Push Metric Exporter sends the data on its own schedule. Here are some examples:

* Sends the data based on a user configured schedule, e.g. every 1 minute.
* Sends the data when there is a severe error.
Copy link
Contributor

Choose a reason for hiding this comment

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

I like that this is declared as a use case.


### Pull Metric Exporter

Pull Metric Exporter reacts to the metrics scrapers and reports the data
passively. This pattern has been widely adopted by
[Prometheus](https://prometheus.io/).