From 05ba8e463207ea599208e1bf108f6c14a3adfda3 Mon Sep 17 00:00:00 2001 From: ChengJinbao Date: Wed, 12 Oct 2022 12:22:35 -0400 Subject: [PATCH] Add Instrumentation Scope and Version as labels in Prometheus (#2703) Fixes: #2493 Related: https://github.com/open-telemetry/opentelemetry-specification/issues/1906 This is a second attempt at https://github.com/open-telemetry/opentelemetry-specification/pull/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. --- CHANGELOG.md | 3 ++ specification/metrics/data-model.md | 59 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b7199..a90c249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/specification/metrics/data-model.md b/specification/metrics/data-model.md index 24e162c..d1ba549 100644 --- a/specification/metrics/data-model.md +++ b/specification/metrics/data-model.md @@ -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) @@ -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 @@ -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.