Skip to content

Commit

Permalink
Add Instrumentation Scope and Version as labels in Prometheus (#2703)
Browse files Browse the repository at this point in the history
Fixes: #2493

Related: open-telemetry/opentelemetry-specification#1906

This is a second attempt at open-telemetry/opentelemetry-specification#2422.

## Changes

### Background: Naming Collisions

OpenTelemetry encourages the use of semantic conventions to make metric naming similar across instrumentation.  For example, if I have two http client libraries in my application, they would each produce a metric named `http.client.duration`, but with different meters (e.g. [otelmux](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/0dd27453a1ce8e433cb632e175a27f28ee83998d/instrumentation/github.com/gorilla/mux/otelmux) vs [otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/0dd27453a1ce8e433cb632e175a27f28ee83998d/instrumentation/net/http/otelhttp)).  A prometheus exporter which receives both of these metrics would not be able to serve both of those histograms.  This would occur anytime a user uses two libraries which produces the same category (e.g. http, database, rpc, etc) of metrics, or if the two libraries just happen to use the same name for a metric.  Depending on the language, it may fail to create the Prometheus exporter, or may fail to send some, or all metrics if the same labels keys and values are present in both.

### Desired User Experience

As a user, I can use a Prometheus exporter with OpenTelemetry without experiencing strange errors/behavior due to naming collisions, and without having to apply transformations to metric names to work around these, except in rare cases.

As a user, I can easily add scope attributes to my metrics in Prometheus by joining with an info-style metric.  This is a common pattern in Prometheus: https://grafana.com/blog/2021/08/04/how-to-use-promql-joins-for-more-effective-queries-of-prometheus-metrics-at-scale/.

### Design

Add `opentelemetry_scope_name` and `opentelemetry_scope_version` as labels to all metrics.  This ensures that if two libraries produce the same metric points, they don't collide because the scope name/version labels will differ.

Those labels also serve as "join keys" to be able to add scope attributes to Prometheus metrics.  This is accomplished by introducing an `opentelemetry_scope_info` metric containing the same `opentelemetry_scope_name` and `opentelemetry_scope_version` labels, but also including scope attributes.  This also enables the collector's Prometheus receiver to reconstruct the original Instrumentation Scope when receiving the metrics.
  • Loading branch information
dashpole authored Oct 12, 2022
1 parent 5537c8c commit 43b727d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ release.

### Compatibility

- Specify how Prometheus exporters and receivers handle instrumentation scope.
([#2703](https://github.com/open-telemetry/opentelemetry-specification/pull/2703)).

### OpenTelemetry Protocol

### SDK Configuration
Expand Down
59 changes: 59 additions & 0 deletions specification/metrics/data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,11 @@ linkTitle: Data Model
+ [Dropped Types](#dropped-types)
+ [Start Time](#start-time)
+ [Exemplars](#exemplars-1)
+ [Instrumentation Scope](#instrumentation-scope)
+ [Resource Attributes](#resource-attributes)
* [OTLP Metric points to Prometheus](#otlp-metric-points-to-prometheus)
+ [Metric Metadata](#metric-metadata-1)
+ [Instrumentation Scope](#instrumentation-scope-1)
+ [Gauges](#gauges-1)
+ [Sums](#sums-1)
+ [Histograms](#histograms-1)
Expand Down Expand Up @@ -1385,6 +1387,47 @@ retrieved from the `trace_id` and `span_id` label keys, respectively. All
labels not used for the trace and span ids MUST be added to the OpenTelemetry
exemplar as attributes.

#### Instrumentation Scope

Each `otel_scope_info` metric point present in a batch of metrics
SHOULD be dropped from the incoming scrape, and converted to an instrumentation
scope. The `otel_scope_name` and `otel_scope_version` labels, if present, MUST
be converted to the Name and Version of the Instrumentation Scope. Additional
labels MUST be added as scope attributes, with keys and values unaltered. Other
metrics in the batch which have `otel_scope_name` and `otel_scope_version`
labels that match an instrumentation scope MUST be placed within the matching
instrumentation scope, and MUST remove those labels. For example, the
OpenMetrics metrics:

```
# TYPE otel_scope_info info
otel_scope_info{otel_scope_name="go.opentelemetry.io.contrib.instrumentation.net.http.otelhttp",otel_scope_version="v0.24.0",library_mascot="bear"} 1
# TYPE http_server_duration counter
http_server_duration{otel_scope_name="go.opentelemetry.io.contrib.instrumentation.net.http.otelhttp",otel_scope_version="v0.24.0"...} 1
```

becomes:

```yaml
# within a resource_metrics
scope_metrics:
scope:
name: go.opentelemetry.io.contrib.instrumentation.net.http.otelhttp
version: v0.24.0
attributes:
library_mascot: bear
metrics:
- name: http_server_duration
data:
sum:
data_points:
- value: 1
```
Metrics which are not found to be associated with an instrumentation scope MUST
all be placed within an empty instrumentation scope, and MUST not have any labels
removed.
#### Resource Attributes
When scraping a Prometheus endpoint, resource attributes MUST be added to the
Expand Down Expand Up @@ -1445,6 +1488,22 @@ The data point type of an OTLP metric MUST be added as
[OpenMetrics TYPE metadata](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#metricfamily).
It also dictates type-specific conversion rules listed below.

#### Instrumentation Scope

Prometheus exporters SHOULD generate an [Info](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#info)-typed
metric named `otel_scope_info`. If present, Instrumentation Scope
`name` and `version` MUST be added as `otel_scope_name` and
`otel_scope_version` labels. Scope attributes MUST also be added as labels
following the rules described in the [`Metric Attributes`](#metric-attributes)
section below.

Prometheus exporters MUST add the scope name as the `otel_scope_name` label and
the scope version as the `otel_scope_version` label on all metric points by
default.

Prometheus exporters SHOULD provide a configuration option to disable the
`otel_scope_info` metric and `otel_scope_` labels.

#### Gauges

An [OpenTelemetry Gauge](#gauge) MUST be converted to a Prometheus Gauge.
Expand Down

0 comments on commit 43b727d

Please sign in to comment.