From 203136919809561b96911b167ff6b56c5363f341 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 28 Sep 2021 16:59:15 -0700 Subject: [PATCH 01/15] Avoid using gRPC when generic RPC systems have same properties (#1914) * Avoid using gRPC when generic RPC systems have same properties The concept of "streaming" is supported by multiple protocols including gRPC, but also others. Signed-off-by: Bogdan Drutu * Update specification/trace/semantic_conventions/rpc.md Co-authored-by: Armin Ruech Co-authored-by: Armin Ruech --- CHANGELOG.md | 4 ++ semantic_conventions/trace/rpc.yaml | 8 +-- .../trace/semantic_conventions/rpc.md | 55 +++++++++---------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b93e83d2bc..154f2a8dc08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ release. - Prefer global user defined limits over model-sepcific default values. ([#1893](https://github.com/open-telemetry/opentelemetry-specification/pull/1893)) +- Add InstrumentationLibrary to Sampler.ShouldSample. + ([#1850](https://github.com/open-telemetry/opentelemetry-specification/pull/1850)) +- Generalize the "message" event to apply to all RPC systems not just gRPC + ([#1914](https://github.com/open-telemetry/opentelemetry-specification/pull/1914)) ### Metrics diff --git a/semantic_conventions/trace/rpc.yaml b/semantic_conventions/trace/rpc.yaml index c4399519f23..6b37a1fa93b 100644 --- a/semantic_conventions/trace/rpc.yaml +++ b/semantic_conventions/trace/rpc.yaml @@ -2,7 +2,7 @@ groups: - id: rpc prefix: rpc brief: 'This document defines semantic conventions for remote procedure calls.' - events: [rpc.grpc.message] + events: [rpc.message] attributes: - id: system type: string @@ -142,10 +142,10 @@ groups: note: > This is always required for jsonrpc. See the note in the general RPC conventions for more information. - - id: rpc.grpc.message - prefix: "message" # TODO: Change the prefix to rpc.grpc.message? + - id: rpc.message + prefix: "message" # TODO: Change the prefix to rpc.message? type: event - brief: "gRPC received/sent message." + brief: "RPC received/sent message." attributes: - id: type type: diff --git a/specification/trace/semantic_conventions/rpc.md b/specification/trace/semantic_conventions/rpc.md index 87879313a6b..49078143be8 100644 --- a/specification/trace/semantic_conventions/rpc.md +++ b/specification/trace/semantic_conventions/rpc.md @@ -14,11 +14,11 @@ This document defines how to describe remote procedure calls - [Span name](#span-name) - [Attributes](#attributes) - [Service name](#service-name) + - [Events](#events) - [Distinction from HTTP spans](#distinction-from-http-spans) - [gRPC](#grpc) - [gRPC Attributes](#grpc-attributes) - [gRPC Status](#grpc-status) - - [Events](#events) - [JSON RPC](#json-rpc) - [JSON RPC Attributes](#json-rpc-attributes) @@ -95,6 +95,32 @@ Generally, a user SHOULD NOT set `peer.service` to a fully qualified RPC service [`service.name`]: ../../resource/semantic_conventions/README.md#service [`peer.service`]: span-general.md#general-remote-service-attributes +### Events + +In the lifetime of an RPC stream, an event for each message sent/received on +client and server spans SHOULD be created. In case of unary calls only one sent +and one received message will be recorded for both client and server spans. + +The event name MUST be `"message"`. + + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `message.type` | string | Whether this is a received or sent message. | `SENT` | No | +| `message.id` | int | MUST be calculated as two different counters starting from `1` one for sent messages and one for received message. [1] | | No | +| `message.compressed_size` | int | Compressed size of the message in bytes. | | No | +| `message.uncompressed_size` | int | Uncompressed size of the message in bytes. | | No | + +**[1]:** This way we guarantee that the values will be consistent between different implementations. + +`message.type` MUST be one of the following: + +| Value | Description | +|---|---| +| `SENT` | sent | +| `RECEIVED` | received | + + ### Distinction from HTTP spans HTTP calls can generally be represented using just [HTTP spans](./http.md). @@ -143,33 +169,6 @@ For remote procedure calls via [gRPC][], additional conventions are described in The [Span Status](../api.md#set-status) MUST be left unset for an `OK` gRPC status code, and set to `Error` for all others. -### Events - -In the lifetime of a gRPC stream, an event for each message sent/received on -client and server spans SHOULD be created. In case of -unary calls only one sent and one received message will be recorded for both -client and server spans. - -The event name MUST be `"message"`. - - -| Attribute | Type | Description | Examples | Required | -|---|---|---|---|---| -| `message.type` | string | Whether this is a received or sent message. | `SENT` | No | -| `message.id` | int | MUST be calculated as two different counters starting from `1` one for sent messages and one for received message. [1] | | No | -| `message.compressed_size` | int | Compressed size of the message in bytes. | | No | -| `message.uncompressed_size` | int | Uncompressed size of the message in bytes. | | No | - -**[1]:** This way we guarantee that the values will be consistent between different implementations. - -`message.type` MUST be one of the following: - -| Value | Description | -|---|---| -| `SENT` | sent | -| `RECEIVED` | received | - - ## JSON RPC Conventions specific to [JSON RPC](https://www.jsonrpc.org/). From fc72838189f689541c740e99206987de097750f4 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 29 Sep 2021 11:48:10 +0200 Subject: [PATCH 02/15] Allow implementations to use their own default for OTLP compression. (#1923) --- CHANGELOG.md | 2 ++ specification/protocol/exporter.md | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 154f2a8dc08..1ea56f14405 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,8 @@ release. ### OpenTelemetry Protocol - Add environment variables for configuring the OTLP exporter protocol (`grpc`, `http/protobuf`, `http/json`) ([#1880](https://github.com/open-telemetry/opentelemetry-specification/pull/1880)) +- Allow implementations to use their own default for OTLP compression, with `none` denotating no compression + ([#1923](https://github.com/open-telemetry/opentelemetry-specification/pull/1923)) ### SDK Configuration diff --git a/specification/protocol/exporter.md b/specification/protocol/exporter.md index 5a3268f2f54..aa56ed8e26d 100644 --- a/specification/protocol/exporter.md +++ b/specification/protocol/exporter.md @@ -15,14 +15,18 @@ The following configuration options MUST be available to configure the OTLP expo | Insecure | Whether to enable client transport security for the exporter's gRPC connection. This option only applies to OTLP/gRPC - OTLP/HTTP always uses the scheme provided for the `endpoint`. Implementations MAY choose to not implement the `insecure` option if it is not required or supported by the underlying gRPC client implementation. | `false` | `OTEL_EXPORTER_OTLP_INSECURE` `OTEL_EXPORTER_OTLP_SPAN_INSECURE` `OTEL_EXPORTER_OTLP_METRIC_INSECURE` | | Certificate File | The trusted certificate to use when verifying a server's TLS credentials. Should only be used for a secure connection. | n/a | `OTEL_EXPORTER_OTLP_CERTIFICATE` `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE` `OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE` | | Headers | Key-value pairs to be used as headers associated with gRPC or HTTP requests. See [Specifying headers](./exporter.md#specifying-headers-via-environment-variables) for more details. | n/a | `OTEL_EXPORTER_OTLP_HEADERS` `OTEL_EXPORTER_OTLP_TRACES_HEADERS` `OTEL_EXPORTER_OTLP_METRICS_HEADERS` | -| Compression | Compression key for supported compression types. Supported compression: `gzip`| No value | `OTEL_EXPORTER_OTLP_COMPRESSION` `OTEL_EXPORTER_OTLP_TRACES_COMPRESSION` `OTEL_EXPORTER_OTLP_METRICS_COMPRESSION` | +| Compression | Compression key for supported compression types. Supported compression: `gzip`| No value [1] | `OTEL_EXPORTER_OTLP_COMPRESSION` `OTEL_EXPORTER_OTLP_TRACES_COMPRESSION` `OTEL_EXPORTER_OTLP_METRICS_COMPRESSION` | | Timeout | Maximum time the OTLP exporter will wait for each batch export. | 10s | `OTEL_EXPORTER_OTLP_TIMEOUT` `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` | | Protocol | The transport protocol. Options MAY include `grpc`, `http/protobuf`, and `http/json`. See [Specify Protocol](./exporter.md#specify-protocol) for more details. | n/a | `OTEL_EXPORTER_OTLP_PROTOCOL` `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | +**[1]**: If no compression value is explicitly specified, SIGs can default to the value they deem +most useful among the supported options. This is especially important in the presence of technical constraints, +e.g. directly sending telemetry data from mobile devices to backend servers. + Supported values for `OTEL_EXPORTER_OTLP_*COMPRESSION` options: -- If the value is missing, then compression is disabled. -- `gzip` is the only specified compression method for now. Other options MAY be supported by language SDKs and should be documented for each particular language. +- `none` if compression is disabled. +- `gzip` is the only specified compression method for now. Example 1 From 517d74a01e6366473aefaac171d947fde869b818 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 29 Sep 2021 12:40:23 +0200 Subject: [PATCH 03/15] Clarify OTLP server components MUST support none/gzip compression. (#1955) --- CHANGELOG.md | 2 ++ specification/protocol/otlp.md | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ea56f14405..efc4fc97150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,8 @@ release. - Add environment variables for configuring the OTLP exporter protocol (`grpc`, `http/protobuf`, `http/json`) ([#1880](https://github.com/open-telemetry/opentelemetry-specification/pull/1880)) - Allow implementations to use their own default for OTLP compression, with `none` denotating no compression ([#1923](https://github.com/open-telemetry/opentelemetry-specification/pull/1923)) +- Clarify OTLP server components MUST support none/gzip compression + ([#1955](https://github.com/open-telemetry/opentelemetry-specification/pull/1955)) ### SDK Configuration diff --git a/specification/protocol/otlp.md b/specification/protocol/otlp.md index 6c83e2dc571..0e5e6da0b41 100644 --- a/specification/protocol/otlp.md +++ b/specification/protocol/otlp.md @@ -70,6 +70,11 @@ OTLP is a request/response style protocols: the clients send requests, the server replies with corresponding responses. This document defines one requests and response type: `Export`. +All server components MUST support the following transport compression options: + +* No compression, denotated by `none`. +* Gzip compression, denoted by `gzip`. + ### OTLP/gRPC **Status**: [Stable](../document-status.md) From 90d9aab8a871db4954831e8447eb325ef020a80c Mon Sep 17 00:00:00 2001 From: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> Date: Wed, 29 Sep 2021 16:50:55 -0400 Subject: [PATCH 04/15] Change OTLP/HTTP port from 4317 to 4318 (#1839) (#1970) Related to https://github.com/open-telemetry/opentelemetry-specification/issues/1816 Fixes https://github.com/open-telemetry/opentelemetry-specification/issues/1835 Fixes https://github.com/open-telemetry/opentelemetry-specification/issues/1920 Some historical context: we wanted to make grpc and http use the same port and we had an open issue in the Collector to do so: https://github.com/open-telemetry/opentelemetry-collector/issues/1256 The conclusion is that there are technical hurdles that make it unfeasible: https://github.com/open-telemetry/opentelemetry-collector/issues/1256#issuecomment-880048833 Because of that we need to keep grpc and http ports separate. This means we need to change the spec to say that otlp/http uses port 4318. Once this PR is merged we will also need to submit for port 4318 registration with IANA like we did previously with port 4317: https://github.com/open-telemetry/opentelemetry-specification/issues/1148#issuecomment-725067404 There was also a draft PR to merge the ports in the Collector but it was not completed: https://github.com/open-telemetry/opentelemetry-collector/pull/3765 Note that this change was initially submitted in PR https://github.com/open-telemetry/opentelemetry-specification/pull/1839 and then reverted in PR https://github.com/open-telemetry/opentelemetry-specification/pull/1847 because we hoped that the merging could be successfully done. We believe that we should no longer pursue this and should consider the ports separate from now on. Note 2: we consider this a spec bug fix (spec was impossible to implement), rather than a functionality change, that's why we believe this is an allowed change. --- CHANGELOG.md | 1 + specification/protocol/exporter.md | 2 +- specification/protocol/otlp.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efc4fc97150..465be6679d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ release. ([#1923](https://github.com/open-telemetry/opentelemetry-specification/pull/1923)) - Clarify OTLP server components MUST support none/gzip compression ([#1955](https://github.com/open-telemetry/opentelemetry-specification/pull/1955)) +- Change OTLP/HTTP port from 4317 to 4318 ([#1970](https://github.com/open-telemetry/opentelemetry-specification/pull/1970)) ### SDK Configuration diff --git a/specification/protocol/exporter.md b/specification/protocol/exporter.md index aa56ed8e26d..b3076309d6c 100644 --- a/specification/protocol/exporter.md +++ b/specification/protocol/exporter.md @@ -10,7 +10,7 @@ The following configuration options MUST be available to configure the OTLP expo | Configuration Option | Description | Default | Env variable | | -------------------- | ------------------------------------------------------------ | ----------------- | ------------------------------------------------------------ | -| Endpoint (OTLP/HTTP) | Target to which the exporter is going to send spans or metrics. The endpoint MUST be a valid URL with scheme (http or https) and host, and MAY contain a port and path. A scheme of https indicates a secure connection. When using `OTEL_EXPORTER_OTLP_ENDPOINT`, exporters SHOULD follow the collector convention of appending the version and signal to the path (e.g. `v1/traces` or `v1/metrics`), if not present already. The per-signal endpoint configuration options take precedence and can be used to override this behavior. See the [OTLP Specification][otlphttp-req] for more details. | `https://localhost:4317` | `OTEL_EXPORTER_OTLP_ENDPOINT` `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | +| Endpoint (OTLP/HTTP) | Target to which the exporter is going to send spans or metrics. The endpoint MUST be a valid URL with scheme (http or https) and host, and MAY contain a port and path. A scheme of https indicates a secure connection. When using `OTEL_EXPORTER_OTLP_ENDPOINT`, exporters SHOULD follow the collector convention of appending the version and signal to the path (e.g. `v1/traces` or `v1/metrics`), if not present already. The per-signal endpoint configuration options take precedence and can be used to override this behavior. See the [OTLP Specification][otlphttp-req] for more details. | `https://localhost:4318` | `OTEL_EXPORTER_OTLP_ENDPOINT` `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | | Endpoint (OTLP/gRPC) | Target to which the exporter is going to send spans or metrics. The endpoint SHOULD accept any form allowed by the underlying gRPC client implementation. Additionally, the endpoint MUST accept a URL with a scheme of either `http` or `https`. A scheme of `https` indicates a secure connection and takes precedence over the `insecure` configuration setting. If the gRPC client implementation does not support an endpoint with a scheme of `http` or `https` then the endpoint SHOULD be transformed to the most sensible format for that implementation. | `https://localhost:4317` | `OTEL_EXPORTER_OTLP_ENDPOINT` `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | | Insecure | Whether to enable client transport security for the exporter's gRPC connection. This option only applies to OTLP/gRPC - OTLP/HTTP always uses the scheme provided for the `endpoint`. Implementations MAY choose to not implement the `insecure` option if it is not required or supported by the underlying gRPC client implementation. | `false` | `OTEL_EXPORTER_OTLP_INSECURE` `OTEL_EXPORTER_OTLP_SPAN_INSECURE` `OTEL_EXPORTER_OTLP_METRIC_INSECURE` | | Certificate File | The trusted certificate to use when verifying a server's TLS credentials. Should only be used for a secure connection. | n/a | `OTEL_EXPORTER_OTLP_CERTIFICATE` `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE` `OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE` | diff --git a/specification/protocol/otlp.md b/specification/protocol/otlp.md index 0e5e6da0b41..ff5f5679a99 100644 --- a/specification/protocol/otlp.md +++ b/specification/protocol/otlp.md @@ -478,7 +478,7 @@ connections SHOULD be configurable. #### OTLP/HTTP Default Port -The default network port for OTLP/HTTP is 4317. +The default network port for OTLP/HTTP is 4318. ## Implementation Recommendations From 16da729707e02e83f3a1b25b4faa3094c3f9e29b Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Thu, 30 Sep 2021 06:59:58 -0700 Subject: [PATCH 05/15] Multiple improvements to the Metrics SDK (#1958) * Added concurrency/compatibility requirements section in the Metrics SDK * Added MetricReader.Shutdown * Updated the ToC --- CHANGELOG.md | 3 +- specification/library-guidelines.md | 3 +- specification/metrics/api.md | 8 ++-- specification/metrics/sdk.md | 58 +++++++++++++++++++++++++---- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 465be6679d8..039817421e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,8 @@ release. [#1888](https://github.com/open-telemetry/opentelemetry-specification/pull/1888), [#1912](https://github.com/open-telemetry/opentelemetry-specification/pull/1912), [#1913](https://github.com/open-telemetry/opentelemetry-specification/pull/1913), - [#1938](https://github.com/open-telemetry/opentelemetry-specification/pull/1938)) + [#1938](https://github.com/open-telemetry/opentelemetry-specification/pull/1938), + [#1958](https://github.com/open-telemetry/opentelemetry-specification/pull/1958)) ### Logs diff --git a/specification/library-guidelines.md b/specification/library-guidelines.md index ceff34e568a..dd837c08d91 100644 --- a/specification/library-guidelines.md +++ b/specification/library-guidelines.md @@ -132,5 +132,6 @@ guidelines on the performance expectations that API implementations should meet, Please refer to individual API specification for guidelines on what concurrency safeties should API implementations provide and how they should be documented: -* [Metrics API](./metrics/api.md#concurrency) +* [Metrics API](./metrics/api.md#concurrency-requirements) +* [Metrics SDK](./metrics/sdk.md#concurrency-requirements) * [Tracing API](./trace/api.md#concurrency) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index 1fefb5e4a25..3a86f9a5023 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -32,6 +32,8 @@ Table of Contents * [Asynchronous UpDownCounter creation](#asynchronous-updowncounter-creation) * [Asynchronous UpDownCounter operations](#asynchronous-updowncounter-operations) * [Measurement](#measurement) +* [Compatibility requirements](#compatibility-requirements) +* [Concurrency requirements](#concurrency-requirements) @@ -978,15 +980,15 @@ for the interaction between the API and SDK. * A value * [`Attributes`](../common/common.md#attributes) -## Compatibility +## Compatibility requirements All the metrics components SHOULD allow new APIs to be added to existing components without introducing breaking changes. All the metrics APIs SHOULD allow optional parameter(s) to be added to existing -APIs without introducing breaking changes. +APIs without introducing breaking changes, if possible. -## Concurrency +## Concurrency requirements For languages which support concurrent execution the Metrics APIs provide specific guarantees and safeties. diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 2862383297e..b67a478517b 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -8,17 +8,19 @@ Table of Contents * [MeterProvider](#meterprovider) -* [Attribute Limits](#attribute-limits) +* [Attribute limits](#attribute-limits) * [Exemplar](#exemplar) * [ExemplarFilter](#exemplarfilter) * [ExemplarReservoir](#exemplarreservoir) - * [Exemplar Defaults](#exemplar-defaults) + * [Exemplar defaults](#exemplar-defaults) * [MetricReader](#metricreader) * [Periodic exporting MetricReader](#periodic-exporting-metricreader) * [MetricExporter](#metricexporter) * [Push Metric Exporter](#push-metric-exporter) * [Pull Metric Exporter](#pull-metric-exporter) -* [Defaults and Configuration](#defaults-and-configuration) +* [Defaults and configuration](#defaults-and-configuration) +* [Compatibility requirements](#compatibility-requirements) +* [Concurrency requirements](#concurrency-requirements) @@ -393,7 +395,7 @@ This Aggregation informs the SDK to collect: - Count of `Measurement` values falling within explicit bucket boundaries. - Arithmetic sum of `Measurement` values in population. -## Attribute Limits +## Attribute limits Attributes which belong to Metrics are exempt from the [common rules of attribute limits](../common/common.md#attribute-limits) at this @@ -477,7 +479,7 @@ from the original sample measurement. The `ExemplarReservoir` SHOULD avoid allocations when sampling exemplars. -### Exemplar Defaults +### Exemplar defaults The SDK will come with two types of built-in exemplar reservoirs: @@ -574,6 +576,22 @@ SDK](../overview.md#sdk) authors MAY choose to add parameters (e.g. callback, filter, timeout). [OpenTelemetry SDK](../overview.md#sdk) authors MAY choose the return value type, or do not return anything. +### Shutdown + +This method provides a way for the `MetricReader` to do any cleanup required. + +`Shutdown` MUST be called only once for each `MetricReader` instance. After the +call to `Shutdown`, subsequent invocations to `Collect` are not allowed. SDKs +SHOULD return some failure for these calls, if possible. + +`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, +failed or timed out. + +`Shutdown` SHOULD complete or abort within some timeout. `Shutdown` CAN be +implemented as a blocking API or an asynchronous API which notifies the caller +via a callback or an event. [OpenTelemetry SDK](../overview.md#sdk) authors CAN +decide if they want to make the shutdown timeout configurable. + ### Periodic exporting MetricReader This is an implementation of the `MetricReader` which collects metrics based on @@ -752,6 +770,32 @@ modeled to interact with other components in the SDK: +-----------------------------+ ``` -## Defaults and Configuration +## Defaults and configuration + +The SDK MUST provide configuration according to the [SDK environment +variables](../sdk-environment-variables.md) specification. + +## Compatibility requirements + +All the metrics components SHOULD allow new methods to be added to existing +components without introducing breaking changes. + +All the metrics SDK methods SHOULD allow optional parameter(s) to be added to +existing methods without introducing breaking changes, if possible. + +## Concurrency requirements + +For languages which support concurrent execution the Metrics SDKs provide +specific guarantees and safeties. + +**MeterProvider** - Meter creation, `ForceFlush` and `Shutdown` are safe to be +called concurrently. + +**ExemplarFilter** - all methods are safe to be called concurrently. + +**ExemplarReservoir** - all methods are safe to be called concurrently. + +**MetricReader** - `Collect` and `Shutdown` are safe to be called concurrently. -The SDK MUST provide configuration according to the [SDK environment variables](../sdk-environment-variables.md) specification. +**MetricExporter** - `ForceFlush` and `Shutdown` are safe to be called +concurrently. From 13358927bf91aa07ada15fdd2c2ab5c4c83e7628 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Thu, 30 Sep 2021 16:23:42 +0200 Subject: [PATCH 06/15] Release v1.7.0 (#1926) --- CHANGELOG.md | 32 +++++++++++++++++++++++++++++--- schemas/1.7.0 | 7 +++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 schemas/1.7.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 039817421e7..05dd1df8474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,30 @@ release. ### Traces +### Metrics + +### Logs + +### Resource + +### Semantic Conventions + +### Compatibility + +### OpenTelemetry Protocol + +### SDK Configuration + +## v1.7.0 (2021-09-30) + +### Context + +- No changes. + +### Traces + - Prefer global user defined limits over model-sepcific default values. ([#1893](https://github.com/open-telemetry/opentelemetry-specification/pull/1893)) -- Add InstrumentationLibrary to Sampler.ShouldSample. - ([#1850](https://github.com/open-telemetry/opentelemetry-specification/pull/1850)) - Generalize the "message" event to apply to all RPC systems not just gRPC ([#1914](https://github.com/open-telemetry/opentelemetry-specification/pull/1914)) @@ -32,9 +52,14 @@ release. [#1913](https://github.com/open-telemetry/opentelemetry-specification/pull/1913), [#1938](https://github.com/open-telemetry/opentelemetry-specification/pull/1938), [#1958](https://github.com/open-telemetry/opentelemetry-specification/pull/1958)) +- Add FaaS metrics semantic conventions ([#1736](https://github.com/open-telemetry/opentelemetry-specification/pull/1736)) +- Update env variable values to match other env variables + ([#1965](https://github.com/open-telemetry/opentelemetry-specification/pull/1965)) ### Logs +- No changes. + ### Resource - Exempt Resource from attribute limits. @@ -60,6 +85,8 @@ release. ### Compatibility +- No changes. + ### OpenTelemetry Protocol - Add environment variables for configuring the OTLP exporter protocol (`grpc`, `http/protobuf`, `http/json`) ([#1880](https://github.com/open-telemetry/opentelemetry-specification/pull/1880)) @@ -143,7 +170,6 @@ release. - Clarify the limit on the instrument unit. ([#1762](https://github.com/open-telemetry/opentelemetry-specification/pull/1762)) -- Add FaaS metrics semantic conventions ([#1736](https://github.com/open-telemetry/opentelemetry-specification/pull/1736)) ### Logs diff --git a/schemas/1.7.0 b/schemas/1.7.0 new file mode 100644 index 00000000000..df9a9b8e003 --- /dev/null +++ b/schemas/1.7.0 @@ -0,0 +1,7 @@ +file_format: 1.0.0 +schema_url: https://opentelemetry.io/schemas/1.7.0 +versions: + 1.7.0: + 1.6.1: + 1.5.0: + 1.4.0: From a43f2b2c4cdf2f76673b305f2cfbbeae5255ef9c Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Thu, 30 Sep 2021 09:21:37 -0700 Subject: [PATCH 07/15] Add metrics spec supplementary guidelines (#1966) * add metrics spec supplementary guidelines * fix wording * tweak wording * improve readability * fix typo * spellcheck * fix typo * add more examples * try to clarify a bit * improve wording * cover more topics * fix typo * fix typo * layout * fix typo * Update specification/metrics/supplementary-guidelines.md Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> --- .../metrics/supplementary-guidelines.md | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 specification/metrics/supplementary-guidelines.md diff --git a/specification/metrics/supplementary-guidelines.md b/specification/metrics/supplementary-guidelines.md new file mode 100644 index 00000000000..6e528704286 --- /dev/null +++ b/specification/metrics/supplementary-guidelines.md @@ -0,0 +1,251 @@ +# Supplementary Guidelines + +Note: this document is NOT a spec, it is provided to support the Metrics +[API](./api.md) and [SDK](./sdk.md) specifications, it does NOT add any extra +requirements to the existing specifications. + +Table of Contents: + +* [Guidelines for instrumentation library + authors](#guidelines-for-instrumentation-library-authors) +* [Guidelines for SDK authors](#guidelines-for-sdk-authors) + * [Aggregation temporality](#aggregation-temporality) + * [Memory management](#memory-management) + +## Guidelines for instrumentation library authors + +TBD + +## Guidelines for SDK authors + +### Aggregation temporality + +The OpenTelemetry Metrics [Data Model](./datamodel.md) and [SDK](./sdk.md) are +designed to support both Cumulative and Delta +[Temporality](./datamodel.md#temporality). It is important to understand that +temporality will impact how the SDK could manage memory usage. Let's take the +following HTTP requests example: + +* During the time range (T0, T1]: + * verb = `GET`, status = `200`, duration = `50 (ms)` + * verb = `GET`, status = `200`, duration = `100 (ms)` + * verb = `GET`, status = `500`, duration = `1 (ms)` +* During the time range (T1, T2]: + * no HTTP request has been received +* During the time range (T2, T3] + * verb = `GET`, status = `500`, duration = `5 (ms)` + * verb = `GET`, status = `500`, duration = `2 (ms)` +* During the time range (T3, T4]: + * verb = `GET`, status = `200`, duration = `100 (ms)` +* During the time range (T4, T5]: + * verb = `GET`, status = `200`, duration = `100 (ms)` + * verb = `GET`, status = `200`, duration = `30 (ms)` + * verb = `GET`, status = `200`, duration = `50 (ms)` + +Let's imagine we export the metrics as [Histogram](./datamodel.md#histogram), +and to simplify the story we will only have one histogram bucket `(-Inf, +Inf)`: + +If we export the metrics using **Delta Temporality**: + +* (T0, T1] + * dimensions: {verb = `GET`, status = `200`}, count: `2`, min: `50 (ms)`, max: + `100 (ms)` + * dimensions: {verb = `GET`, status = `500`}, count: `1`, min: `1 (ms)`, max: + `1 (ms)` +* (T1, T2] + * nothing since we don't have any Measurement received +* (T2, T3] + * dimensions: {verb = `GET`, status = `500`}, count: `2`, min: `2 (ms)`, max: + `5 (ms)` +* (T3, T4] + * dimensions: {verb = `GET`, status = `200`}, count: `1`, min: `100 (ms)`, + max: `100 (ms)` +* (T4, T5] + * dimensions: {verb = `GET`, status = `200`}, count: `3`, min: `30 (ms)`, max: + `100 (ms)` + +You can see that the SDK **only needs to track what has happened after the +latest collection/export cycle**. For example, when the SDK started to process +measurements in (T1, T2], it can completely forget about +what has happened during (T0, T1]. + +If we export the metrics using **Cumulative Temporality**: + +* (T0, T1] + * dimensions: {verb = `GET`, status = `200`}, count: `2`, min: `50 (ms)`, max: + `100 (ms)` + * dimensions: {verb = `GET`, status = `500`}, count: `1`, min: `1 (ms)`, max: + `1 (ms)` +* (T0, T2] + * dimensions: {verb = `GET`, status = `200`}, count: `2`, min: `50 (ms)`, max: + `100 (ms)` + * dimensions: {verb = `GET`, status = `500`}, count: `1`, min: `1 (ms)`, max: + `1 (ms)` +* (T0, T3] + * dimensions: {verb = `GET`, status = `200`}, count: `2`, min: `50 (ms)`, max: + `100 (ms)` + * dimensions: {verb = `GET`, status = `500`}, count: `3`, min: `1 (ms)`, max: + `5 (ms)` +* (T0, T4] + * dimensions: {verb = `GET`, status = `200`}, count: `3`, min: `50 (ms)`, max: + `100 (ms)` + * dimensions: {verb = `GET`, status = `500`}, count: `3`, min: `1 (ms)`, max: + `5 (ms)` +* (T0, T5] + * dimensions: {verb = `GET`, status = `200`}, count: `6`, min: `30 (ms)`, max: + `100 (ms)` + * dimensions: {verb = `GET`, status = `500`}, count: `3`, min: `1 (ms)`, max: + `5 (ms)` + +You can see that we are performing Delta->Cumulative conversion, and the SDK +**has to track what has happened prior to the latest collection/export cycle**, +in the worst case, the SDK **will have to remember what has happened since the +beginning of the process**. + +Imagine if we have a long running service and we collect metrics with 7 +dimensions and each dimension can have 30 different values. We might eventually +end up having to remember the complete set of all `21,870,000,000` permutations! +This **cardinality explosion** is a well-known challenge in the metrics space. + +Making it even worse, if we export the permutations even if there are no recent +updates, the export batch could become huge and will be very costly. For +example, do we really need/want to export the same thing for (T0, +T2] in the above case? + +So here are some suggestions that we encourage SDK implementers to consider: + +* You want to control the memory usage rather than allow it to grow indefinitely + / unbounded - regardless of what aggregation temporality is being used. +* You want to improve the memory efficiency by being able to **forget about + things that are no longer needed**. +* You probably don't want to keep exporting the same thing over and over again, + if there is no updates. You might want to consider [Resets and + Gaps](./datamodel.md#resets-and-gaps). For example, if a Cumulative metrics + stream hasn't received any updates for a long period of time, would it be okay + to reset the start time? + +In the above case, we have Measurements reported by a [Histogram +Instrument](./api.md#histogram). What if we collect measurements from an +[Asynchronous Counter](./api.md#asynchronous-counter)? + +The following example shows the number of [page +faults](https://en.wikipedia.org/wiki/Page_fault) of each thread since the +thread ever started: + +* During the time range (T0, T1]: + * pid = `1001`, tid = `1`, #PF = `50` + * pid = `1001`, tid = `2`, #PF = `30` +* During the time range (T1, T2]: + * pid = `1001`, tid = `1`, #PF = `53` + * pid = `1001`, tid = `2`, #PF = `38` +* During the time range (T2, T3] + * pid = `1001`, tid = `1`, #PF = `56` + * pid = `1001`, tid = `2`, #PF = `42` +* During the time range (T3, T4]: + * pid = `1001`, tid = `1`, #PF = `60` + * pid = `1001`, tid = `2`, #PF = `47` +* During the time range (T4, T5]: + * thread 1 died, thread 3 started + * pid = `1001`, tid = `2`, #PF = `53` + * pid = `1001`, tid = `3`, #PF = `5` + +If we export the metrics using **Cumulative Temporality**: + +* (T0, T1] + * dimensions: {pid = `1001`, tid = `1`}, sum: `50` + * dimensions: {pid = `1001`, tid = `2`}, sum: `30` +* (T0, T2] + * dimensions: {pid = `1001`, tid = `1`}, sum: `53` + * dimensions: {pid = `1001`, tid = `2`}, sum: `38` +* (T0, T3] + * dimensions: {pid = `1001`, tid = `1`}, sum: `56` + * dimensions: {pid = `1001`, tid = `2`}, sum: `42` +* (T0, T4] + * dimensions: {pid = `1001`, tid = `1`}, sum: `60` + * dimensions: {pid = `1001`, tid = `2`}, sum: `47` +* (T0, T5] + * dimensions: {pid = `1001`, tid = `2`}, sum: `53` + * dimensions: {pid = `1001`, tid = `3`}, sum: `5` + +It is quite straightforward - we just take the data being reported from the +asynchronous instruments and send them. We might want to consider if [Resets and +Gaps](./datamodel.md#resets-and-gaps) should be used to denote the end of a +metric stream - e.g. thread 1 died, the thread ID might be reused by the +operating system, and we probably don't want to confuse the metrics backend. + +If we export the metrics using **Delta Temporality**: + +* (T0, T1] + * dimensions: {pid = `1001`, tid = `1`}, delta: `50` + * dimensions: {pid = `1001`, tid = `2`}, delta: `30` +* (T1, T2] + * dimensions: {pid = `1001`, tid = `1`}, delta: `3` + * dimensions: {pid = `1001`, tid = `2`}, delta: `8` +* (T2, T3] + * dimensions: {pid = `1001`, tid = `1`}, delta: `3` + * dimensions: {pid = `1001`, tid = `2`}, delta: `4` +* (T3, T4] + * dimensions: {pid = `1001`, tid = `1`}, delta: `4` + * dimensions: {pid = `1001`, tid = `2`}, delta: `5` +* (T4, T5] + * dimensions: {pid = `1001`, tid = `2`}, delta: `6` + * dimensions: {pid = `1001`, tid = `3`}, delta: `5` + +You can see that we are performing Cumulative->Delta conversion, and it requires +us to remember the last value of **every single permutation we've encountered so +far**, because if we don't, we won't be able to calculate the delta value using +`current value - last value`. And as you can tell, this is super expensive. + +Making it more interesting, if we have min/max value, it is **mathematically +impossible** to reliably deduce the Delta temporality from Cumulative +temporality. For example: + +* If the maximum value is 10 during (T0, T2] and the + maximum value is 20 during (T0, T3], we know that the + maximum value during (T2, T3] must be 20. +* If the maximum value is 20 during (T0, T2] and the + maximum value is also 20 during (T0, T3], we wouldn't + know what the maximum value is during (T2, T3], unless + we know that there is no value (count = 0). + +So here are some suggestions that we encourage SDK implementers to consider: + +* You probably don't want to encourage your users to do Cumulative->Delta + conversion. Actually, you might want to discourage them from doing this. +* If you have to do Cumulative->Delta conversion, and you encountered min/max, + rather than drop the data on the floor, you might want to convert them to + something useful - e.g. [Gauge](./datamodel.md#gauge). + +### Memory management + +Memory management is a wide topic, here we will only cover some of the most +important things for OpenTelemetry SDK. + +**Choose a better design so the SDK has less things to be memorized**, avoid +keeping things in memory unless there is a must need. One good example is the +[aggregation temporality](#aggregation-temporality). + +**Design a better memory layout**, so the storage is efficient and accessing the +storage can be fast. This is normally specific to the targeting programming +language and platform. For example, aligning the memory to the CPU cache line, +keeping the hot memories close to each other, keeping the memory close to the +hardware (e.g. non-paged pool, +[NUMA](https://en.wikipedia.org/wiki/Non-uniform_memory_access)). + +**Pre-allocate and pool the memory**, so the SDK doesn't have to allocate memory +on-the-fly. This is especially useful to language runtimes that have garbage +collectors, as it ensures the hot path in the code won't trigger garbage +collection. + +**Limit the memory usage, and handle critical memory condition.** The general +expectation is that a telemetry SDK should not fail the application. This can be +done via some dimension-capping algorithm - e.g. start to combine/drop some data +points when the SDK hits the memory limit, and provide a mechanism to report the +data loss. + +**Provide configurations to the application owner.** The answer to _"what is an +efficient memory usage"_ is ultimately depending on the goal of the application +owner. For example, the application owners might want to spend more memory in +order to keep more permutations of metrics dimensions, or they might want to use +memory aggressively for certain dimensions that are important, and keep a +conservative limit for dimensions that are less important. From 4e1f01e5ab9ecdaab8bec8990f312eed9e2a0581 Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Fri, 1 Oct 2021 11:12:37 -0500 Subject: [PATCH 08/15] Add optional min and max fields to histogram data model. (#1915) * Add optional min and max fields to histogram data model. * Fix lint error * Update histogram min and max definition per discussion * Format changelog to comply with line length recommendations * Update delta histogram image with min and max * Fix lint error * Revert "Fix lint error" This reverts commit 90f1c724 * Removing trailing space on line Co-authored-by: Josh Suereth --- CHANGELOG.md | 3 +++ specification/metrics/datamodel.md | 9 +++++++++ .../metrics/img/model-delta-histogram.png | Bin 54345 -> 62753 bytes 3 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05dd1df8474..959aec0a195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ release. ### Metrics +- Add optional min / max fields to histogram data model. + ([#1915](https://github.com/open-telemetry/opentelemetry-specification/pull/1915)) + ### Logs ### Resource diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index ac1c4806b4e..a916909099b 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -386,6 +386,8 @@ Histograms consist of the following: (00:00:00 UTC on 1 January 1970). - A count (`count`) of the total population of points in the histogram. - A sum (`sum`) of all the values in the histogram. + - (optional) The min (`min`) of all values in the histogram. + - (optional) The max (`max`) of all values in the histogram. - (optional) A series of buckets with: - Explicit boundary values. These values denote the lower and upper bounds for buckets and whether not a given observation would be recorded in this @@ -398,6 +400,13 @@ denotes Delta temporality where accumulated event counts are reset to zero after and a new aggregation occurs. Cumulative, on the other hand, continues to aggregate events, resetting with the use of a new start time. +The aggregation temporality also has implications on the min and max fields. Min +and max are more useful for Delta temporality, since the values represented by +Cumulative min and max will stabilize as more events are recorded. Additionally, +it is possible to convert min and max from Delta to Cumulative, but not from +Cumulative to Delta. When converting from Cumulative to Delta, min and max can +be dropped, or captured in an alternative representation such as a gauge. + Bucket counts are optional. A Histogram without buckets conveys a population in terms of only the sum and count, and may be interpreted as a histogram with single bucket covering `(-Inf, +Inf)`. diff --git a/specification/metrics/img/model-delta-histogram.png b/specification/metrics/img/model-delta-histogram.png index f2ec06a270d63d4d1d06fb519afcb896d70616f2..e3cc13e46a711156b84b3544e3680056312bcb40 100644 GIT binary patch literal 62753 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 KX8vv4KmH2<6W8+q literal 54345 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࿌R)^^=S{Bzbm&2LTwOmx&`y{(uAD?%v#KgrJ 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 E024%QSO5S3 From 2d72f9598c1414be66d78e35835659c7cbeacdba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Mon, 4 Oct 2021 10:38:13 +0200 Subject: [PATCH 09/15] Clarify OTEL_EXPORTER_OTLP_ENDPOINT envvar for OTLP/HTTP. (#1975) The current wording of the OTLP endpoint config was confusing, especially the "if not present already" wording. Instead, clarify that we must always append when using the envvar for all signals (it was already clearly specified that the per-signal vars do not get the path appended). This came up in https://github.com/open-telemetry/opentelemetry-java/issues/3650 and again at https://github.com/open-telemetry/opentelemetry-java/pull/3666#discussion_r717347648. Also make it a MUST (not SHOULD) since this kind of thing would be extremely annoying to have differences per-language in. Also, without appending, the variable cannot be used to configure more than one signal which would defeat its sole purpose. --- CHANGELOG.md | 3 ++ specification/protocol/exporter.md | 55 ++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 959aec0a195..52f1a762b1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,8 @@ release. ### OpenTelemetry Protocol - Add environment variables for configuring the OTLP exporter protocol (`grpc`, `http/protobuf`, `http/json`) ([#1880](https://github.com/open-telemetry/opentelemetry-specification/pull/1880)) +- Specify the behavior of the OTLP endpoint variables for OTLP/HTTP more strictly + ([#1975](https://github.com/open-telemetry/opentelemetry-specification/pull/1975)). - Allow implementations to use their own default for OTLP compression, with `none` denotating no compression ([#1923](https://github.com/open-telemetry/opentelemetry-specification/pull/1923)) - Clarify OTLP server components MUST support none/gzip compression @@ -103,6 +105,7 @@ release. - Change default value for OTEL_EXPORTER_JAEGER_AGENT_PORT to 6831. ([#1812](https://github.com/open-telemetry/opentelemetry-specification/pull/1812)) +- See also the changes for OTLP configuration listed under "OpenTelemetry Protocol" above. ## v1.6.0 (2021-08-06) diff --git a/specification/protocol/exporter.md b/specification/protocol/exporter.md index b3076309d6c..c149bb8ba5f 100644 --- a/specification/protocol/exporter.md +++ b/specification/protocol/exporter.md @@ -10,7 +10,7 @@ The following configuration options MUST be available to configure the OTLP expo | Configuration Option | Description | Default | Env variable | | -------------------- | ------------------------------------------------------------ | ----------------- | ------------------------------------------------------------ | -| Endpoint (OTLP/HTTP) | Target to which the exporter is going to send spans or metrics. The endpoint MUST be a valid URL with scheme (http or https) and host, and MAY contain a port and path. A scheme of https indicates a secure connection. When using `OTEL_EXPORTER_OTLP_ENDPOINT`, exporters SHOULD follow the collector convention of appending the version and signal to the path (e.g. `v1/traces` or `v1/metrics`), if not present already. The per-signal endpoint configuration options take precedence and can be used to override this behavior. See the [OTLP Specification][otlphttp-req] for more details. | `https://localhost:4318` | `OTEL_EXPORTER_OTLP_ENDPOINT` `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | +| Endpoint (OTLP/HTTP) | Target URL to which the exporter is going to send spans or metrics. The endpoint MUST be a valid URL with scheme (http or https) and host, MAY contain a port, SHOULD contain a path and MUST NOT contain other parts (such as query string or fragment). A scheme of https indicates a secure connection. When using `OTEL_EXPORTER_OTLP_ENDPOINT`, exporters MUST construct per-signal URLs as [described below](#per-signal-urls). The per-signal endpoint configuration options take precedence and can be used to override this behavior (the URL is used as-is for them, without any modifications). See the [OTLP Specification][otlphttp-req] for more details. | `https://localhost:4318` | `OTEL_EXPORTER_OTLP_ENDPOINT` `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | | Endpoint (OTLP/gRPC) | Target to which the exporter is going to send spans or metrics. The endpoint SHOULD accept any form allowed by the underlying gRPC client implementation. Additionally, the endpoint MUST accept a URL with a scheme of either `http` or `https`. A scheme of `https` indicates a secure connection and takes precedence over the `insecure` configuration setting. If the gRPC client implementation does not support an endpoint with a scheme of `http` or `https` then the endpoint SHOULD be transformed to the most sensible format for that implementation. | `https://localhost:4317` | `OTEL_EXPORTER_OTLP_ENDPOINT` `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | | Insecure | Whether to enable client transport security for the exporter's gRPC connection. This option only applies to OTLP/gRPC - OTLP/HTTP always uses the scheme provided for the `endpoint`. Implementations MAY choose to not implement the `insecure` option if it is not required or supported by the underlying gRPC client implementation. | `false` | `OTEL_EXPORTER_OTLP_INSECURE` `OTEL_EXPORTER_OTLP_SPAN_INSECURE` `OTEL_EXPORTER_OTLP_METRIC_INSECURE` | | Certificate File | The trusted certificate to use when verifying a server's TLS credentials. Should only be used for a secure connection. | n/a | `OTEL_EXPORTER_OTLP_CERTIFICATE` `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE` `OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE` | @@ -28,24 +28,65 @@ Supported values for `OTEL_EXPORTER_OTLP_*COMPRESSION` options: - `none` if compression is disabled. - `gzip` is the only specified compression method for now. -Example 1 + + +### Endpoint URLs for OTLP/HTTP + +Based on the environment variables above, the OTLP/HTTP exporter MUST construct URLs +for each signal as follow: + +1. For the per-signal variables (`OTEL_EXPORTER_OTLP__ENDPOINT`), the URL + MUST be used as-is without any modification. The only exception is that if an + URL contains no path part, the root path `/` MUST be used (see [Example 2](#example-2)). +2. If signals are sent that have no per-signal configuration from the previous point, + `OTEL_EXPORTER_OTLP_ENDPOINT` is used as a base URL and the signals are sent + to these paths relative to that: + + * Traces: `v1/traces` + * Metrics: `v1/metrics`. + + Non-normatively, this could be implemented by ensuring that the base URL ends with + a slash and then appending the relative URLs as strings. + +#### Example 1 The following configuration sends all signals to the same collector: ```bash -export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317 +export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 ``` -Example 2 +Traces are sent to `http://collector:4318/v1/traces` and metrics to +`http://collector:4318/v1/metrics`. -Traces and metrics are sent to different collectors: +#### Example 2 -```bash -export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://collector:4317 +Traces and metrics are sent to different collectors and paths: +```bash +export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://collector:4318 export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://collector.example.com/v1/metrics ``` +This will send traces directly to the root path `http://collector:4318/` +(`/v1/traces` is only automatically added when using the non-signal-specific +environment variable) and metrics +to `https://collector.example.com/v1/metrics`. + +#### Example 3 + +The following configuration sends all signals except for metrics to the same collector: + +```bash +export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318/mycollector/ +export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://collector.example.com/v1/metrics/ +``` + +Traces are sent to `http://collector:4318/mycollector/v1/traces` +and metrics to `https://collector.example.com/v1/metrics/` +(other signals, would they be defined, would be sent to their specific paths +relative to `http://collector:4318/mycollector/`). + ### Specify Protocol The `OTEL_EXPORTER_OTLP_PROTOCOL`, `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`, and `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` environment variables specify the OTLP transport protocol. Supported values: From 9ceb9fa4fc2e742264960da22344a07575a819ce Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Mon, 4 Oct 2021 10:30:30 -0700 Subject: [PATCH 10/15] Add metrics supplementary guideline for instrumentation authors (#1981) * Add metrics supplementary guideline for instrumentation authors * address the review comments * Apply suggestions from code review Co-authored-by: John Watson * Update specification/metrics/supplementary-guidelines.md Co-authored-by: John Watson * rewrap Co-authored-by: John Watson Co-authored-by: Josh Suereth --- .../metrics/supplementary-guidelines.md | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/specification/metrics/supplementary-guidelines.md b/specification/metrics/supplementary-guidelines.md index 6e528704286..6aeaaed7ebb 100644 --- a/specification/metrics/supplementary-guidelines.md +++ b/specification/metrics/supplementary-guidelines.md @@ -8,13 +8,67 @@ Table of Contents: * [Guidelines for instrumentation library authors](#guidelines-for-instrumentation-library-authors) + * [Instrument selection](#instrument-selection) + * [Semantic convention](#semantic-convention) * [Guidelines for SDK authors](#guidelines-for-sdk-authors) * [Aggregation temporality](#aggregation-temporality) * [Memory management](#memory-management) ## Guidelines for instrumentation library authors -TBD +### Instrument selection + +The [Instruments](./api.md#instrument) are part of the [Metrics API](./api.md). +They allow [Measurements](./api.md#measurement) to be recorded +[synchronously](./api.md#synchronous-instrument) or +[asynchronously](./api.md#asynchronous-instrument). + +Choosing the correct instrument is important, because: + +* It helps the library to achieve better efficiency. For example, if we want to + report room temperature to [Prometheus](https://prometheus.io), we want to + consider using an [Asynchronous Gauge](./api.md#asynchronous-gauge) rather + than periodically poll the sensor, so that we only access the sensor when + scraping happened. +* It makes the consumption easier for the user of the library. For example, if + we want to report HTTP server request latency, we want to consider a + [Histogram](./api.md#histogram), so most of the users can get a reasonable + experience (e.g. default buckets, min/max) by simply enabling the metrics + stream, rather than doing extra configurations. +* It generates clarity to the semantic of the metrics stream, so the consumers + have better understanding of the results. For example, if we want to report + the process heap size, by using an [Asynchronous + UpDownCounter](./api.md#asynchronous-updowncounter) rather than an + [Asynchronous Gauge](./api.md#asynchronous-gauge), we've made it explicit that + the consumer can add up the numbers across all processes to get the "total + heap size". + +Here is one way of choosing the correct instrument: + +* I want to **count** something (by recording a delta value): + * If the value is monotonically increasing (the delta value is always + non-negative) - use a [Counter](./api.md#counter). + * If the value is NOT monotonically increasing (the delta value can be + positive, negative or zero) - use an + [UpDownCounter](./api.md#updowncounter). +* I want to **record** or **time** something, and the **statistics** about this + thing are likely to be meaningful - use a [Histogram](./api.md#histogram). +* I want to **measure** something (by reporting an absolute value): + * If it makes NO sense to add up the values across different dimensions, use + an [Asynchronous Gauge](./api.md#asynchronous-gauge). + * If it makes sense to add up the values across different dimensions: + * If the value is monotonically increasing - use an [Asynchronous + Counter](./api.md#asynchronous-counter). + * If the value is NOT monotonically increasing - use an [Asynchronous + UpDownCounter](./api.md#asynchronous-updowncounter). + +### Semantic convention + +Once you decided [which instrument(s) to be used](#instrument-selection), you +will need to decide the names for the instruments and attributes. + +It is highly recommended that you align with the `OpenTelemetry Semantic +Conventions`, rather than inventing your own semantics. ## Guidelines for SDK authors From e30aa7da8f28328adb67b4804c4dcddf4f413c1d Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Mon, 4 Oct 2021 16:00:18 -0700 Subject: [PATCH 11/15] Minor improvements to the Metrics API spec wording (#1986) --- specification/metrics/api.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index 3a86f9a5023..d0305200467 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -410,7 +410,8 @@ function(s) independently. approach. Here are some examples: * Return a list (or tuple, generator, enumerator, etc.) of `Measurement`s. -* Use an observer argument to allow individual `Measurement`s to be reported. +* Use an observer 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, [OpenTelemetry @@ -898,7 +899,8 @@ function(s) independently. approach. Here are some examples: * Return a list (or tuple, generator, enumerator, etc.) of `Measurement`s. -* Use an observer argument to allow individual `Measurement`s to be reported. +* Use an observer 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 From a2f124a62dce27a484c4bc6eafe88249f7faddff Mon Sep 17 00:00:00 2001 From: Zhongyang Wu Date: Tue, 5 Oct 2021 09:06:45 -0400 Subject: [PATCH 12/15] Update Rust support for OTLP/gRPC (#1988) cc @jtescher ## Changes Update Rust's support for OTLP/HTTP binary protocol Related issues #1885 --- spec-compliance-matrix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec-compliance-matrix.md b/spec-compliance-matrix.md index d98236516ed..485d8ff3991 100644 --- a/spec-compliance-matrix.md +++ b/spec-compliance-matrix.md @@ -163,7 +163,7 @@ Note: Support for environment variables is optional. | In-memory (mock exporter) | | + | + | + | + | + | + | - | - | + | + | + | | [OTLP](specification/protocol/otlp.md) | | | | | | | | | | | | | | OTLP/gRPC Exporter | * | + | + | + | + | | + | | + | + | + | + | -| OTLP/HTTP binary Protobuf Exporter | * | + | + | + | + | + | + | | | + | - | - | +| OTLP/HTTP binary Protobuf Exporter | * | + | + | + | + | + | + | | + | + | - | - | | OTLP/HTTP JSON Protobuf Exporter | | + | - | + | [-][py1003] | | - | | | + | - | - | | OTLP/HTTP gzip Content-Encoding support | X | + | + | + | + | + | - | | | - | - | - | | Concurrent sending | | - | + | + | [-][py1108] | | - | | + | - | - | - | From c68128eb13b78184f9d1429119ba1994b8de2e86 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 5 Oct 2021 08:51:33 -0700 Subject: [PATCH 13/15] Update metrics semantic conventions to use the new instrument names (#1976) Signed-off-by: Bogdan Drutu Co-authored-by: Carlos Alberto Cortez --- .../semantic_conventions/http-metrics.md | 14 +-- .../metrics/semantic_conventions/rpc.md | 28 ++--- .../semantic_conventions/system-metrics.md | 110 +++++++++--------- 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/specification/metrics/semantic_conventions/http-metrics.md b/specification/metrics/semantic_conventions/http-metrics.md index 38d05416a93..a24e2bbb5cd 100644 --- a/specification/metrics/semantic_conventions/http-metrics.md +++ b/specification/metrics/semantic_conventions/http-metrics.md @@ -17,18 +17,18 @@ type and units. Below is a table of HTTP server metric instruments. -| Name | Instrument | Units | Description | -|-------------------------------|-------------------|--------------|-------------| -| `http.server.duration` | ValueRecorder | milliseconds | measures the duration of the inbound HTTP request | -| `http.server.active_requests` | UpDownSumObserver | requests | measures the number of concurrent HTTP requests that are currently in-flight | +| Name | Instrument | Units | Description | +|-------------------------------|----------------------------|--------------|-------------| +| `http.server.duration` | Histogram | milliseconds | measures the duration of the inbound HTTP request | +| `http.server.active_requests` | Asynchronous UpDownCounter | requests | measures the number of concurrent HTTP requests that are currently in-flight | ### HTTP Client Below is a table of HTTP client metric instruments. -| Name | Instrument | Units | Description | -|------------------------|---------------|--------------|-------------| -| `http.client.duration` | ValueRecorder | milliseconds | measure the duration of the outbound HTTP request | +| Name | Instrument | Units | Description | +|------------------------|------------|--------------|-------------| +| `http.client.duration` | Histogram | milliseconds | measure the duration of the outbound HTTP request | ## Attributes diff --git a/specification/metrics/semantic_conventions/rpc.md b/specification/metrics/semantic_conventions/rpc.md index 61cd34fc501..12463cbef3f 100644 --- a/specification/metrics/semantic_conventions/rpc.md +++ b/specification/metrics/semantic_conventions/rpc.md @@ -31,26 +31,26 @@ MUST be of the specified type and units. Below is a table of RPC server metric instruments. -| Name | Instrument | Units | Description | Status | Streaming | -|----------------------------|---------------|--------------|-------------|--------|-----------| -| `rpc.server.duration` | ValueRecorder | milliseconds | measures duration of inbound RPC | Recommended | N/A. While streaming RPCs may record this metric as start-of-batch to end-of-batch, it's hard to interpret in practice. | -| `rpc.server.request.size` | ValueRecorder | bytes | measures size of RPC request messages (uncompressed) | Optional | Recorded per message in a streaming batch | -| `rpc.server.response.size` | ValueRecorder | bytes | measures size of RPC response messages (uncompressed) | Optional | Recorded per response in a streaming batch | -| `rpc.server.requests_per_rpc` | ValueRecorder | count | measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | -| `rpc.server.responses_per_rpc` | ValueRecorder | count | measures the number of messages sent per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | +| Name | Instrument | Units | Description | Status | Streaming | +|------|------------|-------|-------------|--------|-----------| +| `rpc.server.duration` | Histogram | milliseconds | measures duration of inbound RPC | Recommended | N/A. While streaming RPCs may record this metric as start-of-batch to end-of-batch, it's hard to interpret in practice. | +| `rpc.server.request.size` | Histogram | bytes | measures size of RPC request messages (uncompressed) | Optional | Recorded per message in a streaming batch | +| `rpc.server.response.size` | Histogram | bytes | measures size of RPC response messages (uncompressed) | Optional | Recorded per response in a streaming batch | +| `rpc.server.requests_per_rpc` | Histogram | count | measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | +| `rpc.server.responses_per_rpc` | Histogram | count | measures the number of messages sent per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | ### RPC Client Below is a table of RPC client metric instruments. These apply to traditional RPC usage, not streaming RPCs. -| Name | Instrument | Units | Description | Status | Streaming | -|----------------------------|---------------|--------------|-------------|--------|-----------| -| `rpc.client.duration` | ValueRecorder | milliseconds | measures duration of outbound RPC | Recommended | N/A. While streaming RPCs may record this metric as start-of-batch to end-of-batch, it's hard to interpret in practice. | -| `rpc.client.request.size` | ValueRecorder | bytes | measures size of RPC request messages (uncompressed) | Optional | Recorded per message in a streaming batch | -| `rpc.client.response.size` | ValueRecorder | bytes | measures size of RPC response messages (uncompressed) | Optional | Recorded per message in a streaming batch | -| `rpc.client.requests_per_rpc` | ValueRecorder | count | measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | -| `rpc.client.responses_per_rpc` | ValueRecorder | count | measures the number of messages sent per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | +| Name | Instrument | Units | Description | Status | Streaming | +|------|------------|-------|-------------|--------|-----------| +| `rpc.client.duration` | Histogram | milliseconds | measures duration of outbound RPC | Recommended | N/A. While streaming RPCs may record this metric as start-of-batch to end-of-batch, it's hard to interpret in practice. | +| `rpc.client.request.size` | Histogram | bytes | measures size of RPC request messages (uncompressed) | Optional | Recorded per message in a streaming batch | +| `rpc.client.response.size` | Histogram | bytes | measures size of RPC response messages (uncompressed) | Optional | Recorded per message in a streaming batch | +| `rpc.client.requests_per_rpc` | Histogram | count | measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | +| `rpc.client.responses_per_rpc` | Histogram | count | measures the number of messages sent per RPC. Should be 1 for all non-streaming RPCs | Optional | Required | ## Attributes diff --git a/specification/metrics/semantic_conventions/system-metrics.md b/specification/metrics/semantic_conventions/system-metrics.md index 02b69ad24e2..11b97442e6d 100644 --- a/specification/metrics/semantic_conventions/system-metrics.md +++ b/specification/metrics/semantic_conventions/system-metrics.md @@ -29,12 +29,12 @@ instruments not explicitly defined in the specification. **Description:** System level processor metrics. -| Name | Description | Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values | -| ---------------------- | ----------- | ----- | --------------- | ---------- | ---------------- | ----------------------------------- | -| system.cpu.time | | s | SumObserver | Double | state | idle, user, system, interrupt, etc. | -| | | | | | cpu | CPU number [0..n-1] | -| system.cpu.utilization | | 1 | ValueObserver | Double | state | idle, user, system, interrupt, etc. | -| | | | | | cpu | CPU number (0..n) | +| Name | Description | Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values | +| ---------------------- | ----------- | ----- | ---------------------| ---------- | ---------------- | ----------------------------------- | +| system.cpu.time | | s | Asynchronous Counter | Double | state | idle, user, system, interrupt, etc. | +| | | | | | cpu | CPU number [0..n-1] | +| system.cpu.utilization | | 1 | Asynchronous Gauge | Double | state | idle, user, system, interrupt, etc. | +| | | | | | cpu | CPU number (0..n) | ### `system.memory.` - Memory metrics @@ -43,34 +43,34 @@ memory](#systempaging---pagingswap-metrics). | Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | | ------------------------- | ----------- | ----- | ----------------- | ---------- | ------------- | ------------------------ | -| system.memory.usage | | By | UpDownSumObserver | Int64 | state | used, free, cached, etc. | -| system.memory.utilization | | 1 | ValueObserver | Double | state | used, free, cached, etc. | +| system.memory.usage | | By | Asynchronous UpDownCounter | Int64 | state | used, free, cached, etc. | +| system.memory.utilization | | 1 | Asynchronous Gauge | Double | state | used, free, cached, etc. | ### `system.paging.` - Paging/swap metrics **Description:** System level paging/swap memory metrics. -| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | -| ------------------------- | ----------------------------------- | ------------ | ----------------- | ---------- | ------------- | ---------------- | -| system.paging.usage | Unix swap or windows pagefile usage | By | UpDownSumObserver | Int64 | state | used, free | -| system.paging.utilization | | 1 | ValueObserver | Double | state | used, free | -| system.paging.faults | | {faults} | SumObserver | Int64 | type | major, minor | -| system.paging.operations | | {operations} | SumObserver | Int64 | type | major, minor | -| | | | | | direction | in, out | +| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | +| ------------------------- | ----------------------------------- | ------------ | -------------------------- | ---------- | ------------- | ---------------- | +| system.paging.usage | Unix swap or windows pagefile usage | By | Asynchronous UpDownCounter | Int64 | state | used, free | +| system.paging.utilization | | 1 | Asynchronous Gauge | Double | state | used, free | +| system.paging.faults | | {faults} | Asynchronous Counter | Int64 | type | major, minor | +| system.paging.operations | | {operations} | Asynchronous Counter | Int64 | type | major, minor | +| | | | | | direction | in, out | ### `system.disk.` - Disk controller metrics **Description:** System level disk performance metrics. -| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | -| --------------------------------------------------------- | ----------------------------------------------- | ------------ | --------------- | ---------- | ------------- | ---------------- | -| system.disk.io | | By | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | read, write | -| system.disk.operations | | {operations} | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | read, write | -| system.disk.io_time[1](#io_time) | Time disk spent activated | s | SumObserver | Double | device | (identifier) | -| system.disk.operation_time[2](#operation_time) | Sum of the time each operation took to complete | s | SumObserver | Double | device | (identifier) | -| | | | | | direction | read, write | -| system.disk.merged | | {operations} | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | read, write | +| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | +| --------------------------------------------------------- | ----------------------------------------------- | ------------ | ------------------------ | ---------- | ------------- | ---------------- | +| system.disk.io | | By | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | read, write | +| system.disk.operations | | {operations} | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | read, write | +| system.disk.io_time[1](#io_time) | Time disk spent activated | s | Asynchronous Counter | Double | device | (identifier) | +| system.disk.operation_time[2](#operation_time) | Sum of the time each operation took to complete | s | Asynchronous Counter | Double | device | (identifier) | +| | | | | | direction | read, write | +| system.disk.merged | | {operations} | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | read, write | 1 The real elapsed time ("wall clock") used in the I/O path (time from operations running in parallel are not @@ -94,35 +94,35 @@ perf counter (similar for Writes) ### `system.filesystem.` - Filesystem metrics **Description:** System level filesystem metrics. -| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | -| ----------------------------- | ----------- | ----- | ----------------- | ---------- | -------------- | -------------------- | -| system.filesystem.usage | | By | UpDownSumObserver | Int64 | device | (identifier) | -| | | | | | state | used, free, reserved | -| | | | | | type | ext4, tmpfs, etc. | -| | | | | | mode | rw, ro, etc. | -| | | | | | mountpoint | (path) | -| system.filesystem.utilization | | 1 | ValueObserver | Double | device | (identifier) | -| | | | | | state | used, free, reserved | -| | | | | | type | ext4, tmpfs, etc. | -| | | | | | mode | rw, ro, etc. | -| | | | | | mountpoint | (path) | +| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | +| ----------------------------- | ----------- | ----- | -------------------------- | ---------- | -------------- | -------------------- | +| system.filesystem.usage | | By | Asynchronous UpDownCounter | Int64 | device | (identifier) | +| | | | | | state | used, free, reserved | +| | | | | | type | ext4, tmpfs, etc. | +| | | | | | mode | rw, ro, etc. | +| | | | | | mountpoint | (path) | +| system.filesystem.utilization | | 1 | Asynchronous Gauge | Double | device | (identifier) | +| | | | | | state | used, free, reserved | +| | | | | | type | ext4, tmpfs, etc. | +| | | | | | mode | rw, ro, etc. | +| | | | | | mountpoint | (path) | ### `system.network.` - Network metrics **Description:** System level network metrics. -| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | -| ---------------------------------------------- | ----------------------------------------------------------------------------- | ------------- | ----------------- | ---------- | ------------- | ---------------------------------------------------------------------------------------------- | -| system.network.dropped[1](#dropped) | Count of packets that are dropped or discarded even though there was no error | {packets} | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | transmit, receive | -| system.network.packets | | {packets} | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | transmit, receive | -| system.network.errors[2](#errors) | Count of network errors detected | {errors} | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | transmit, receive | -| system.network.io | | By | SumObserver | Int64 | device | (identifier) | -| | | | | | direction | transmit, receive | -| system.network.connections | | {connections} | UpDownSumObserver | Int64 | device | (identifier) | -| | | | | | protocol | tcp, udp, [etc.](https://en.wikipedia.org/wiki/Transport_layer#Protocols) | -| | | | | | state | [e.g. for tcp](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Protocol_operation) | +| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | +| ---------------------------------------------- | ----------------------------------------------------------------------------- | ------------- | -------------------------- | ---------- | ------------- | ---------------------------------------------------------------------------------------------- | +| system.network.dropped[1](#dropped) | Count of packets that are dropped or discarded even though there was no error | {packets} | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | transmit, receive | +| system.network.packets | | {packets} | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | transmit, receive | +| system.network.errors[2](#errors) | Count of network errors detected | {errors} | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | transmit, receive | +| system.network.io | | By | Asynchronous Counter | Int64 | device | (identifier) | +| | | | | | direction | transmit, receive | +| system.network.connections | | {connections} | Asynchronous UpDownCounter | Int64 | device | (identifier) | +| | | | | | protocol | tcp, udp, [etc.](https://en.wikipedia.org/wiki/Transport_layer#Protocols) | +| | | | | | state | [e.g. for tcp](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Protocol_operation) | 1 Measured as: @@ -146,10 +146,10 @@ from **Description:** System level aggregate process metrics. For metrics at the individual process level, see [process metrics](process-metrics.md). -| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | -| ------------------------ | --------------------------------------------------------- | ----------- | ----------------- | ---------- | ------------- | ---------------------------------------------------------------------------------------------- | -| system.processes.count | Total number of processes in each state | {processes} | UpDownSumObserver | Int64 | status | running, sleeping, [etc.](https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES) | -| system.processes.created | Total number of processes created over uptime of the host | {processes} | SumObserver | Int64 | - | - | +| Name | Description | Units | Instrument Type | Value Type | Attribute Key | Attribute Values | +| ------------------------ | --------------------------------------------------------- | ----------- | -------------------------- | ---------- | ------------- | ---------------------------------------------------------------------------------------------- | +| system.processes.count | Total number of processes in each state | {processes} | Asynchronous UpDownCounter | Int64 | status | running, sleeping, [etc.](https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES) | +| system.processes.created | Total number of processes created over uptime of the host | {processes} | Asynchronous Counter | Int64 | - | - | ### `system.{os}.` - OS Specific System Metrics From 8ebafd7f679b632c0e1ea5b62fcfa273751b2e6c Mon Sep 17 00:00:00 2001 From: Dmitrii Anoshin Date: Wed, 6 Oct 2021 05:10:27 -0700 Subject: [PATCH 14/15] Add `k8s.container.restart_count` Resource attribute (#1945) This change adds a Resource attribute to represent number of container restarts in kubernetes. This is can be used in k8s logs collection to identify a particular container instance, where the number of container restarts is a part of a log file path. Co-authored-by: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> --- CHANGELOG.md | 2 ++ semantic_conventions/resource/k8s.yaml | 7 +++++++ specification/resource/semantic_conventions/k8s.md | 1 + 3 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f1a762b1f..f14390c8e4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,8 @@ release. ([#1890](https://github.com/open-telemetry/opentelemetry-specification/pull/1890)) - Add HTTP request and response headers semantic conventions. ([#1898](https://github.com/open-telemetry/opentelemetry-specification/pull/1898)) +- Add `k8s.container.restart_count` Resource attribute. + ([#1945](https://github.com/open-telemetry/opentelemetry-specification/pull/1945)) ### Compatibility diff --git a/semantic_conventions/resource/k8s.yaml b/semantic_conventions/resource/k8s.yaml index d25bcda2c10..10cefc05ad4 100644 --- a/semantic_conventions/resource/k8s.yaml +++ b/semantic_conventions/resource/k8s.yaml @@ -63,6 +63,13 @@ groups: brief: > The name of the Container in a Pod template. examples: ['redis'] + - id: restart_count + type: int + brief: > + Number of times the container was restarted. This attribute can be + used to identify a particular container (running or stopped) within a + container spec. + examples: [0, 2] - id: k8s.replicaset prefix: k8s.replicaset diff --git a/specification/resource/semantic_conventions/k8s.md b/specification/resource/semantic_conventions/k8s.md index 0ed9a477b4c..8414fbe2462 100644 --- a/specification/resource/semantic_conventions/k8s.md +++ b/specification/resource/semantic_conventions/k8s.md @@ -88,6 +88,7 @@ to a running container. | Attribute | Type | Description | Examples | Required | |---|---|---|---|---| | `k8s.container.name` | string | The name of the Container in a Pod template. | `redis` | No | +| `k8s.container.restart_count` | int | Number of times the container was restarted. This attribute can be used to identify a particular container (running or stopped) within a container spec. | `0`; `2` | No | ## ReplicaSet From 548915cd8040b0705fad051d9d7a7031fdbd0fff Mon Sep 17 00:00:00 2001 From: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> Date: Wed, 6 Oct 2021 21:07:28 +0400 Subject: [PATCH 15/15] Make OTLP/HTTP the recommended default transport (#1969) Resolves https://github.com/open-telemetry/opentelemetry-specification/issues/1885 - Strongly recommend SDKs to implement both OTLP/gRPC and OTLP/HTTP+Protobuf exporters. - Strongly recommend OTLP/HTTP+Protobuf to be the default protocol but allow language SDKs to choose a different default if they have good reasons. --- CHANGELOG.md | 2 ++ specification/protocol/exporter.md | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f14390c8e4c..da4d750990d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ release. ### OpenTelemetry Protocol +- Make OTLP/HTTP the recommended default transport ([#1969](https://github.com/open-telemetry/opentelemetry-specification/pull/1969)) + ### SDK Configuration ## v1.7.0 (2021-09-30) diff --git a/specification/protocol/exporter.md b/specification/protocol/exporter.md index c149bb8ba5f..429be0af077 100644 --- a/specification/protocol/exporter.md +++ b/specification/protocol/exporter.md @@ -17,7 +17,7 @@ The following configuration options MUST be available to configure the OTLP expo | Headers | Key-value pairs to be used as headers associated with gRPC or HTTP requests. See [Specifying headers](./exporter.md#specifying-headers-via-environment-variables) for more details. | n/a | `OTEL_EXPORTER_OTLP_HEADERS` `OTEL_EXPORTER_OTLP_TRACES_HEADERS` `OTEL_EXPORTER_OTLP_METRICS_HEADERS` | | Compression | Compression key for supported compression types. Supported compression: `gzip`| No value [1] | `OTEL_EXPORTER_OTLP_COMPRESSION` `OTEL_EXPORTER_OTLP_TRACES_COMPRESSION` `OTEL_EXPORTER_OTLP_METRICS_COMPRESSION` | | Timeout | Maximum time the OTLP exporter will wait for each batch export. | 10s | `OTEL_EXPORTER_OTLP_TIMEOUT` `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` | -| Protocol | The transport protocol. Options MAY include `grpc`, `http/protobuf`, and `http/json`. See [Specify Protocol](./exporter.md#specify-protocol) for more details. | n/a | `OTEL_EXPORTER_OTLP_PROTOCOL` `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | +| Protocol | The transport protocol. Options MAY include `grpc`, `http/protobuf`, and `http/json`. See [Specify Protocol](./exporter.md#specify-protocol) for more details. | `http/protobuf` [2] | `OTEL_EXPORTER_OTLP_PROTOCOL` `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | **[1]**: If no compression value is explicitly specified, SIGs can default to the value they deem most useful among the supported options. This is especially important in the presence of technical constraints, @@ -95,9 +95,14 @@ The `OTEL_EXPORTER_OTLP_PROTOCOL`, `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`, and `OT - `http/protobuf` for protobuf-encoded data over HTTP connection - `http/json` for JSON-encoded data over HTTP connection -SDKs MUST support either `grpc` or `http/protobuf` and SHOULD support both. They also MAY support `http/json`. +**[2]**: SDKs SHOULD support both `grpc` and `http/protobuf` transports and MUST +support at least one of them. If they support only one, it SHOULD be +`http/protobuf`. They also MAY support `http/json`. -SDKs have an unspecified default, if no configuration is provided. +If no configuration is provided the default transport SHOULD be `http/protobuf` +unless SDKs have good reasons to choose `grpc` as the default (e.g. for backward +compatibility reasons when `grpc` was already the default in a stable SDK +release). ### Specifying headers via environment variables