From dc018dfc86d71e7ee0b76986749d4066933a2923 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 24 Jan 2023 13:33:16 -0800 Subject: [PATCH 01/15] Add the initial draft of the metric No-Op --- specification/metrics/noop.md | 290 ++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 specification/metrics/noop.md diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md new file mode 100644 index 00000000000..a8b48788583 --- /dev/null +++ b/specification/metrics/noop.md @@ -0,0 +1,290 @@ + + +# Metrics No-Op API Implementation + +**Status**: [Experimental](../document-status.md) + +
+ Table of Contents + + + +- [Metrics No-Op API Implementation](#metrics-no-op-api-implementation) + * [MeterProvider](#meterprovider) + + [Meter Creation](#meter-creation) + * [Meter](#meter) + + [Counter Creation](#counter-creation) + + [UpDownCounter Creation](#updowncounter-creation) + + [Histogram Creation](#histogram-creation) + + [Asynchronous Counter Creation](#asynchronous-counter-creation) + + [Asynchronous UpDownCounter Creation](#asynchronous-updowncounter-creation) + + [Asynchronous Gauge Creation](#asynchronous-gauge-creation) + * [Instruments](#instruments) + + [Counter](#counter) + - [Counter Add](#counter-add) + + [UpDownCounter](#updowncounter) + - [UpDownCounter Add](#updowncounter-add) + + [Histogram](#histogram) + - [Histogram Record](#histogram-record) + + [Asynchronous Counter](#asynchronous-counter) + - [Asynchronous Counter Observations](#asynchronous-counter-observations) + + [Asynchronous UpDownCounter](#asynchronous-updowncounter) + - [Asynchronous UpDownCounter Observations](#asynchronous-updowncounter-observations) + + [Asynchronous Gauge](#asynchronous-gauge) + - [Asynchronous Gauge Observations](#asynchronous-gauge-observations) + + + +
+ +Users of OpenTelemetry need a way to disable the API from actually +performing any operations. The No-Op OpenTelemetry API implementation +(henceforth referred to as the No-Op) provides users with this +functionally. It implements the OpenTelemetry API so that no telemetry +is produced and computation resources are minimized. + +All language implementations of OpenTelemetry SHOULD provide a No-Op. + +## MeterProvider + +The No-Op MUST allow the creation of multiple MeterProviders. + +The MeterProviders created by the No-Op needs to hold as small a memory +footprint as possible. Therefore, all MeterProviders created MUST NOT +hold configuration or operational state. + +Since all MeterProviders a will hold the same empty state, a No-Op MAY +provided the same MeterProvider instances to all creation requests. + +The No-Op is used by OpenTelemetry users to disable OpenTelemetry +computation overhead and eliminate OpenTelemetry related output. For +this reason, the MeterProvider MUST NOT return a non-empty error or log +any message for any operations it performs. + +All operations a MeterProvider provides MUST be safe to be run +concurrently. + +### Meter Creation + +[New Meter instances are always created with a +MeterProvider](./api.md#meterprovider). Therefore, MeterProviders MUST +allow for the creation of Meters. All Meters created MUST be implemented +by the No-Op. + +Since all Meters will hold the same empty state, a MeterProvider MAY +return the same Meter instances to all creation requests. + +[The API specifies multiple parameters](./api.md#meterprovider) that +need to be accepted by the creation operation. The MeterProvider MUST +accept these parameters. However, the MeterProvider MUST NOT validate +any argument it receives. + +## Meter + +A Meter is always created by a MeterProvider, the No-Op MUST NOT provide +a way for a user to create a Meter other than by a No-Op MeterProvider. + +The Meters created by the No-Op needs to hold as small a memory +footprint as possible. Therefore, all Meters created MUST NOT hold +configuration or operational state. + +The Meter MUST NOT return a non-empty error or log any message for any +operations it performs. + +All operations a Meter provides MUST be safe to be run concurrently. + +### Counter Creation + +The No-Op Meter MUST allow for the creation of a [Counter +instrument](#counter). + +Since all Counters hold the same empty state, a Meter MAY return the +same Counter instance to all creation requests. + +[The API specifies multiple +parameters](./api.md#synchronous-instrument-api) that need to be +accepted by the creation operation. The Meter MUST accept these +parameters. However, the Meter MUST NOT validate any argument it +receives. + +### UpDownCounter Creation + +The No-Op Meter MUST allow for the creation of a [UpDownCounter +instrument](#updowncounter). + +Since all UpDownCounters hold the same empty state, a Meter MAY return +the same UpDownCounter instance to all creation requests. + +[The API specifies multiple +parameters](./api.md#synchronous-instrument-api) that need to be +accepted by the creation operation. The Meter MUST accept these +parameters. However, the Meter MUST NOT validate any argument it +receives. + +### Histogram Creation + +The No-Op Meter MUST allow for the creation of a [Histogram +instrument](#histogram). + +Since all Histograms hold the same empty state, a Meter MAY return the +same Histogram instance to all creation requests. + +[The API specifies multiple +parameters](./api.md#synchronous-instrument-api) that need to be +accepted by the creation operation. The Meter MUST accept these +parameters. However, the Meter MUST NOT validate any argument it +receives. + +### Asynchronous Counter Creation + +The No-Op Meter MUST allow for the creation of an [Asynchronous Counter +instrument](#asynchronous-counter). + +Since all Asynchronous Counters hold the same empty state, a Meter MAY +return the same Asynchronous Counter instance to all creation requests. + +[The API specifies multiple +parameters](./api.md#asynchronous-instrument-api) that need to be +accepted by the creation operation. The Meter MUST accept these +parameters. However, the Meter MUST NOT validate any argument it +receives and it MUST NOT hold any reference to the passed callbacks. + +### Asynchronous UpDownCounter Creation + +The No-Op Meter MUST allow for the creation of an [Asynchronous +UpDownCounter instrument](#asynchronous-updowncounter). + +Since all Asynchronous UpDownCounters hold the same empty state, a Meter +MAY return the same Asynchronous UpDownCounter instance to all creation +requests. + +[The API specifies multiple +parameters](./api.md#asynchronous-instrument-api) that need to be +accepted by the creation operation. The Meter MUST accept these +parameters. However, the Meter MUST NOT validate any argument it +receives and it MUST NOT hold any reference to the passed callbacks. + +### Asynchronous Gauge Creation + +The No-Op Meter MUST allow for the creation of an [Asynchronous Gauge +instrument](#asynchronous-gauge). + +Since all Asynchronous Gauges hold the same empty state, a Meter MAY +return the same Asynchronous UpDownCounter instance to all creation +requests. + +[The API specifies multiple +parameters](./api.md#asynchronous-instrument-api) that need to be +accepted by the creation operation. The Meter MUST accept these +parameters. However, the Meter MUST NOT validate any argument it +receives and it MUST NOT hold any reference to the passed callbacks. + +## Instruments + +Instruments are used to make measurements and report telemetry for a +system. However, the No-Op is used to disable this production of +telemetry. Because of this, all instruments the No-Op provides MUST NOT +hold any configuration or operational state including the aggregation of +telemetry. + +### Counter + +Counters are always created by a Meter, the No-Op MUST NOT provide a way +for a user to create a Counter other than by a No-Op Meter. + +Counters MUST NOT return a non-empty error or log any message for any +operations they perform. + +All operations a Counter provides MUST be safe to be run concurrently. + +#### Counter Add + +The No-Op Counter MUST provide the user an interface to Add that +implements the [API](./api.md#add). It MUST NOT validate or retain any +state about the arguments it receives. + +### UpDownCounter + +UpDownCounters are always created by a Meter, the No-Op MUST NOT provide +a way for a user to create a UpDownCounter other than by a No-Op Meter. + +UpDownCounters MUST NOT return a non-empty error or log any message for +any operations they perform. + +All operations an UpDownCounter provides MUST be safe to be run +concurrently. + +#### UpDownCounter Add + +The No-Op UpDownCounter MUST provide the user an interface to Add that +implements the [API](./api.md#add-1). It MUST NOT validate or retain any +state about the arguments it receives. + +### Histogram + +Histograms are always created by a Meter, the No-Op MUST NOT provide a +way for a user to create a Histogram other than by a No-Op Meter. + +Histograms MUST NOT return a non-empty error or log any message for any +operations they perform. + +All operations a Histogram provides MUST be safe to be run concurrently. + +#### Histogram Record + +The No-Op Histogram MUST provide the user an interface to Record that +implements the [API](./api.md#record). It MUST NOT validate or retain +any state about the arguments it receives. + +### Asynchronous Counter + +Asynchronous Counters are always created by a Meter, the No-Op MUST NOT +provide a way for a user to create a Asynchronous Counter other than by +a No-Op Meter. + +Asynchronous Counters MUST NOT return a non-empty error or log any +message for any operations they perform. + +All operations an Asynchronous Counter provides MUST be safe to be run +concurrently. + +### Asynchronous Counter Observations + +The No-Op Asynchronous Counter MUST NOT validate or retain any state +about observations made for the instrument. + +### Asynchronous UpDownCounter + +Asynchronous UpDownCounters are always created by a Meter, the No-Op +MUST NOT provide a way for a user to create a Asynchronous UpDownCounter +other than by a No-Op Meter. + +Asynchronous UpDownCounters MUST NOT return a non-empty error or log any +message for any operations they perform. + +All operations an Asynchronous UpDownCounter provides MUST be safe to be +run concurrently. + +### Asynchronous UpDownCounter Observations + +The No-Op Asynchronous UpDownCounter MUST NOT validate or retain any +state about observations made for the instrument. + +### Asynchronous Gauge + +Asynchronous Gauges are always created by a Meter, the No-Op MUST NOT +provide a way for a user to create a Asynchronous Gauge other than by a +No-Op Meter. + +Asynchronous Gauges MUST NOT return a non-empty error or log any message +for any operations they perform. + +All operations an Asynchronous Gauge provides MUST be safe to be run +concurrently. + +### Asynchronous Gauge Observations + +The No-Op Asynchronous Gauge MUST NOT validate or retain any state about +observations made for the instrument. From bdd82fb2a3bf4d7f05f43e05a203688c6c57ee53 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 24 Jan 2023 14:02:02 -0800 Subject: [PATCH 02/15] Give overview of SDK --- specification/metrics/sdk.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index f11de6258ea..a8b3cee671a 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -64,6 +64,13 @@ linkTitle: SDK +Users of OpenTelemetry need a way for instrumentation interactions with the +OpenTelemetry API to actually produce telemetry. The OpenTelemetry SDK +(henceforth referred to as the SDK) is an implementation of the OpenTelemetry +API that provides users with this functionally. + +All language implementations of OpenTelemetry MUST provide an SDK. + ## MeterProvider **Status**: [Stable](../document-status.md) From e2b62b6af5c00b031e5dc49de5826ad5cbcf79ae Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 24 Jan 2023 14:05:37 -0800 Subject: [PATCH 03/15] Move API spec of MeterProvider creation to SDK --- specification/metrics/api.md | 6 ------ specification/metrics/sdk.md | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index b9257ce530f..2e14cb515ef 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -105,12 +105,6 @@ Normally, the `MeterProvider` is expected to be accessed from a central place. Thus, the API SHOULD provide a way to set/register and access a global default `MeterProvider`. -Notwithstanding any global `MeterProvider`, some applications may want to or -have to use multiple `MeterProvider` instances, e.g. to have different -configuration for each, or because its easier with dependency injection -frameworks. Thus, implementations of `MeterProvider` SHOULD allow creating an -arbitrary number of `MeterProvider` instances. - ### MeterProvider operations The `MeterProvider` MUST provide the following functions: diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index a8b3cee671a..e1fb0e96d67 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -81,6 +81,8 @@ metrics produced by any `Meter` from the `MeterProvider`. The [tracing SDK specification](../trace/sdk.md#additional-span-interfaces) has provided some suggestions regarding how to implement this efficiently. +The SDK SHOULD allow the creation of multiple independent `MeterProvider`s. + ### Meter Creation New `Meter` instances are always created through a `MeterProvider` From 343eabe2e0cf6aef7ff0799db0e9d4bc3d7232f9 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 2 Feb 2023 09:05:57 -0800 Subject: [PATCH 04/15] Move SDK spec for meter out of API --- specification/metrics/api.md | 108 +++++++---------------------------- specification/metrics/sdk.md | 85 +++++++++++++++++++++------ 2 files changed, 86 insertions(+), 107 deletions(-) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index 663e4d46a17..e93b5233ec1 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -19,9 +19,7 @@ linkTitle: API * [Meter operations](#meter-operations) - [Instrument](#instrument) * [General characteristics](#general-characteristics) - + [Instrument type conflict detection](#instrument-type-conflict-detection) - + [Instrument namespace](#instrument-namespace) - + [Instrument naming rule](#instrument-naming-rule) + + [Instrument name syntax](#instrument-name-syntax) + [Instrument unit](#instrument-unit) + [Instrument description](#instrument-description) + [Synchronous and Asynchronous instruments](#synchronous-and-asynchronous-instruments) @@ -115,30 +113,16 @@ The `MeterProvider` MUST provide the following functions: This API MUST accept the following parameters: -* `name`: This name SHOULD uniquely identify the [instrumentation +* `name`: This name uniquely identifies the [instrumentation scope](../glossary.md#instrumentation-scope), such as the [instrumentation library](../glossary.md#instrumentation-library) (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. If an application or library has built-in OpenTelemetry instrumentation, both [Instrumented library](../glossary.md#instrumented-library) and [Instrumentation - library](../glossary.md#instrumentation-library) may refer to the same + library](../glossary.md#instrumentation-library) can refer to the same library. In that scenario, the `name` denotes a module name or component name - within that library or application. In case an invalid name (null or empty - string) is specified, a working Meter implementation MUST be returned as a - fallback rather than returning null or throwing an exception, its `name` - property SHOULD keep the original invalid value, and a message reporting that - the specified value is invalid SHOULD be logged. A library, implementing the - OpenTelemetry API *may* also ignore this name and return a default instance - for all calls, if it does not support "named" functionality (e.g. an - implementation which is not even observability-related). A MeterProvider could - also return a no-op Meter here if application owners configure the SDK to - suppress telemetry produced by this library. - - The `name` needs to be provided by a user. If possible, the API SHOULD be - structured so a user is obligated to provide this parameter. If it is not - possible to structurally enforce this obligation, the API MUST be documented - in a way to communicate to users that this parameter is needed. + within that library or application. * `version`: Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: `1.0.0`. @@ -168,23 +152,6 @@ The term *identical* applied to Meters describes instances where all identifying fields are equal. The term *distinct* applied to Meters describes instances where at least one identifying field has a different value. -Implementations MUST NOT require users to repeatedly obtain a `Meter` with -the same identity to pick up configuration changes. This can be -achieved either by allowing to work with an outdated configuration or by -ensuring that new configuration applies also to previously returned `Meter`s. - -Note: This could, for example, be implemented by storing any mutable -configuration in the `MeterProvider` and having `Meter` implementation objects -have a reference to the `MeterProvider` from which they were obtained. If -configuration must be stored per-meter (such as disabling a certain meter), the -meter could, for example, do a look-up with its identity in a map -in the `MeterProvider`, or the `MeterProvider` could maintain a registry of all -returned `Meter`s and actively update their configuration if it changes. - -The effect of associating a Schema URL with a `Meter` MUST be that the telemetry -emitted using the `Meter` will be associated with the Schema URL, provided that -the emitted data format is capable of representing such association. - ## Meter The meter is responsible for creating [Instruments](#instrument). @@ -224,42 +191,10 @@ floating point numbers SHOULD be considered as identifying. ### General characteristics -#### Instrument type conflict detection +#### Instrument name syntax -When more than one Instrument of the same `name` is created for -identical Meters, denoted *duplicate instrument registration*, the -implementation MUST create a valid Instrument in every case. Here, -"valid" means an instrument that is functional and can be expected to -export data, despite potentially creating a [semantic error in the -data -model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations). - -It is unspecified whether or under which conditions the same or -different Instrument instance will be returned as a result of -duplicate instrument registration. The term *identical* applied to -Instruments describes instances where all identifying fields are -equal. The term *distinct* applied to Instruments describes instances -where at least one field value is different. - -When more than one distinct Instrument is registered with the same -`name` for identical Meters, the implementation SHOULD emit a warning -to the user informing them of duplicate registration conflict(s). -The warning helps to avoid the semantic error state described in the -[OpenTelemetry Metrics data -model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations) -when more than one `Metric` is written for a given instrument `name` -and Meter identity by the same MeterProvider. - -#### Instrument namespace - -Distinct Meters MUST be treated as separate namespaces for the -purposes of detecting [duplicate instrument registration -conflicts](#instrument-type-conflict-detection). - -#### Instrument naming rule - -Instrument names MUST conform to the following syntax (described using the -[Augmented Backus-Naur Form](https://tools.ietf.org/html/rfc5234)): +The instrument name syntax is defined below using the [Augmented Backus-Naur +Form](https://tools.ietf.org/html/rfc5234): ```abnf instrument-name = ALPHA 0*62 ("_" / "." / "-" / ALPHA / DIGIT) @@ -278,11 +213,10 @@ DIGIT = %x30-39 ; 0-9 #### Instrument unit The `unit` is an optional string provided by the author of the Instrument. It -SHOULD be treated as an opaque string from the API and SDK (e.g. the SDK is not -expected to validate the unit of measurement, or perform the unit conversion). +SHOULD be treated as an opaque string from the API and SDK. -* If the `unit` is not provided or the `unit` is null, the API and SDK MUST make - sure that the behavior is the same as an empty `unit` string. +* If the `unit` is not provided or the `unit` is null, the API MUST make sure + that the behavior is the same as an empty `unit` string. * It MUST be case-sensitive (e.g. `kb` and `kB` are different units), ASCII string. * It can have a maximum length of 63 characters. The number 63 is chosen to @@ -295,8 +229,8 @@ expected to validate the unit of measurement, or perform the unit conversion). The `description` is an optional free-form text provided by the author of the instrument. It MUST be treated as an opaque string from the API and SDK. -* If the `description` is not provided or the `description` is null, the API and - SDK MUST make sure that the behavior is the same as an empty `description` +* If the `description` is not provided or the `description` is null, the API + MUST make sure that the behavior is the same as an empty `description` string. * It MUST support [BMP (Unicode Plane 0)](https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane), @@ -340,11 +274,10 @@ The API to construct synchronous instruments MUST accept the following parameter possible to structurally enforce this obligation, the API MUST be documented in a way to communicate to users that this parameter is needed. - The `name` needs to follow the [instrument naming - rule](#instrument-naming-rule). The API SHOULD be documented in a way to - communicate to users that this parameter needs to conform to the linked - syntax. The API SHOULD NOT validate the `name`, that is left to - implementations of the API. + The API SHOULD be documented in a way to communicate to users that the `name` + parameter needs to conform to the [instrument name + syntax](#instrument-name-syntax). The API SHOULD NOT validate the `name`, + that is left to implementations of the API. * A `unit` of measure. Users can provide a `unit`, but it is up to their discretion. Therefore, this @@ -383,11 +316,10 @@ The API to construct asynchronous instruments MUST accept the following paramete possible to structurally enforce this obligation, the API MUST be documented in a way to communicate to users that this parameter is needed. - The `name` needs to follow the [instrument naming - rule](#instrument-naming-rule). The API SHOULD be documented in a way to - communicate to users that this parameter needs to conform to the linked - syntax. The API SHOULD NOT validate the `name`, that is left to - implementations of the API. + The API SHOULD be documented in a way to communicate to users that the `name` + parameter needs to conform to the [instrument name + syntax](#instrument-name-syntax). The API SHOULD NOT validate the `name`, + that is left to implementations of the API. * A `unit` of measure. Users can provide a `unit`, but it is up to their discretion. Therefore, this diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index e1fb0e96d67..df860317f85 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -13,6 +13,7 @@ linkTitle: SDK - [MeterProvider](#meterprovider) * [Meter Creation](#meter-creation) + + [Instrument type conflict detection](#instrument-type-conflict-detection) * [Shutdown](#shutdown) * [ForceFlush](#forceflush) * [View](#view) @@ -29,7 +30,11 @@ linkTitle: SDK * [Use the maximum scale for single measurements](#use-the-maximum-scale-for-single-measurements) * [Maintain the ideal scale](#maintain-the-ideal-scale) * [Observations inside asynchronous callbacks](#observations-inside-asynchronous-callbacks) - * [Resolving duplicate instrument registration conflicts](#resolving-duplicate-instrument-registration-conflicts) +- [Meter](#meter) + * [Duplicate instrument registration](#duplicate-instrument-registration) + * [Instrument name](#instrument-name) + * [Instrument unit](#instrument-unit) + * [Instrument description](#instrument-description) - [Attribute limits](#attribute-limits) - [Exemplar](#exemplar) * [ExemplarFilter](#exemplarfilter) @@ -92,6 +97,15 @@ the `MeterProvider` MUST be used to create an [`InstrumentationScope`](../glossary.md#instrumentation-scope) instance which is stored on the created `Meter`. +In the case where an invalid `name` (null or empty string) is specified, a +working Meter MUST be returned as a fallback rather than returning null or +throwing an exception, its `name` SHOULD keep the original invalid value, and a +message reporting that the specified value is invalid SHOULD be logged. + +When a Schema URL is passed as an argument when creating a `Meter` the emitted +telemetry for that `Meter` MUST be associated with the Schema URL, provided +that the emitted data format is capable of representing such association. + Configuration (i.e., [MetricExporters](#metricexporter), [MetricReaders](#metricreader) and [Views](#view)) MUST be managed solely by the `MeterProvider` and the SDK MUST provide a way to configure all options that are @@ -564,33 +578,66 @@ execution. The implementation MUST complete the execution of all callbacks for a given instrument before starting a subsequent round of collection. -### Resolving duplicate instrument registration conflicts +## Meter + +Meters MUST be treated as separate namespaces for the purposes of detecting +[duplicate instrument registrations](#duplicate-instrument-registration). -As [stated in the API -specification](api.md#instrument-type-conflict-detection), -implementations are REQUIRED to create valid instruments in case of -duplicate instrument registration, and the [data model includes -RECOMMENDATIONS on how to treat the consequent duplicate -conflicting](data-model.md#opentelemetry-protocol-data-model-producer-recommendations) -`Metric` definitions. +### Duplicate instrument registration -The implementation MUST aggregate data from identical Instruments -together in its export pipeline. +When more than one Instrument of the same `name` is created for identical +Meters, denoted *duplicate instrument registration*, the Meter MUST create a +valid Instrument in every case. Here, "valid" means an instrument that is +functional and can be expected to export data, despite potentially creating a +[semantic error in the data +model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations). -The implementation SHOULD assist the user in managing conflicts by -reporting each duplicate-conflicting instrument registration that was -not corrected by a View as follows. When a potential conflict arises -between two non-identical `Metric` instances having the same `name`: +It is unspecified whether or under which conditions the same or +different Instrument instance will be returned as a result of +duplicate instrument registration. The term *identical* applied to +Instruments describes instances where all identifying fields are +equal. The term *distinct* applied to Instruments describes instances +where at least one field value is different. + +Based on [the recommendations from the data +model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations), +the SDK MUST aggregate data from identical Instruments together in its export +pipeline. + +When a duplicate instrument registration occurs, and it is not corrected with a +View, a warning SHOULD be emitted. The emitted warning SHOULD include +information for the user on how to resolve the conflict, if possible. 1. If the potential conflict involves multiple `description` properties, setting the `description` through a configured View SHOULD avoid the warning. 2. If the potential conflict involves instruments that can be distinguished by a supported View selector (e.g., instrument type) - a View recipe SHOULD be printed advising the user how to avoid the - warning by renaming one of the conflicting instruments. -3. Otherwise (e.g., use of multiple units), the implementation SHOULD - pass through the data by reporting both `Metric` objects. + a renaming View recipe SHOULD be included in the warning. +3. Otherwise (e.g., use of multiple units), the SDK SHOULD pass through the + data by reporting both `Metric` objects and emit a generic warning + describing the duplicate instrument registration. + +### Instrument name + +When a Meter creates an instrument, it SHOULD validate the instrument name +conforms to the [instrument name syntax](./api.md#instrument-name-syntax) + +If the instrument name does not conform to this syntax, the Meter SHOULD emit +an error notifying the user about the invalid name. It is left unspecified if a +valid instrument is also returned. + +### Instrument unit + +When a Meter creates an instrument, it SHOULD NOT validate the instrument unit. +If a unit is not provided or the unit is null, the Meter MUST treat it the same +as an empty unit string. + +### Instrument description + +When a Meter creates an instrument, it SHOULD NOT validate the instrument +description. If a description is not provided or the description is null, the +Meter MUST treat it the same as an empty description string. ## Attribute limits From c356980b1e935b456abf2ea88fc59f51dd9cd14e Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 2 Feb 2023 09:30:15 -0800 Subject: [PATCH 05/15] Use consistent emphasis style --- specification/metrics/sdk.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 4ea9b7794e8..ffd0c11eaff 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -589,7 +589,7 @@ Meters MUST be treated as separate namespaces for the purposes of detecting ### Duplicate instrument registration When more than one Instrument of the same `name` is created for identical -Meters, denoted *duplicate instrument registration*, the Meter MUST create a +Meters, denoted _duplicate instrument registration_, the Meter MUST create a valid Instrument in every case. Here, "valid" means an instrument that is functional and can be expected to export data, despite potentially creating a [semantic error in the data @@ -597,9 +597,9 @@ model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations) It is unspecified whether or under which conditions the same or different Instrument instance will be returned as a result of -duplicate instrument registration. The term *identical* applied to +duplicate instrument registration. The term _identical_ applied to Instruments describes instances where all identifying fields are -equal. The term *distinct* applied to Instruments describes instances +equal. The term _distinct_ applied to Instruments describes instances where at least one field value is different. Based on [the recommendations from the data From 6c83c87b96c8e6a58fc91898cf815e1ac1356ee7 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 2 Feb 2023 09:31:53 -0800 Subject: [PATCH 06/15] Fix toc addition from merge --- specification/metrics/sdk.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index ffd0c11eaff..dc48df539f3 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -14,7 +14,6 @@ linkTitle: SDK - [MeterProvider](#meterprovider) * [MeterProvider Creation](#meterprovider-creation) * [Meter Creation](#meter-creation) - + [Instrument type conflict detection](#instrument-type-conflict-detection) * [Shutdown](#shutdown) * [ForceFlush](#forceflush) * [View](#view) From 3213e5ab78709dcdf845fd74c52e7fcb5849de11 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 2 Feb 2023 09:35:12 -0800 Subject: [PATCH 07/15] Generate toc for noop.md --- specification/metrics/noop.md | 45 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md index a8b48788583..721bb185d02 100644 --- a/specification/metrics/noop.md +++ b/specification/metrics/noop.md @@ -11,29 +11,28 @@ linkTitle: SDK -- [Metrics No-Op API Implementation](#metrics-no-op-api-implementation) - * [MeterProvider](#meterprovider) - + [Meter Creation](#meter-creation) - * [Meter](#meter) - + [Counter Creation](#counter-creation) - + [UpDownCounter Creation](#updowncounter-creation) - + [Histogram Creation](#histogram-creation) - + [Asynchronous Counter Creation](#asynchronous-counter-creation) - + [Asynchronous UpDownCounter Creation](#asynchronous-updowncounter-creation) - + [Asynchronous Gauge Creation](#asynchronous-gauge-creation) - * [Instruments](#instruments) - + [Counter](#counter) - - [Counter Add](#counter-add) - + [UpDownCounter](#updowncounter) - - [UpDownCounter Add](#updowncounter-add) - + [Histogram](#histogram) - - [Histogram Record](#histogram-record) - + [Asynchronous Counter](#asynchronous-counter) - - [Asynchronous Counter Observations](#asynchronous-counter-observations) - + [Asynchronous UpDownCounter](#asynchronous-updowncounter) - - [Asynchronous UpDownCounter Observations](#asynchronous-updowncounter-observations) - + [Asynchronous Gauge](#asynchronous-gauge) - - [Asynchronous Gauge Observations](#asynchronous-gauge-observations) +- [MeterProvider](#meterprovider) + * [Meter Creation](#meter-creation) +- [Meter](#meter) + * [Counter Creation](#counter-creation) + * [UpDownCounter Creation](#updowncounter-creation) + * [Histogram Creation](#histogram-creation) + * [Asynchronous Counter Creation](#asynchronous-counter-creation) + * [Asynchronous UpDownCounter Creation](#asynchronous-updowncounter-creation) + * [Asynchronous Gauge Creation](#asynchronous-gauge-creation) +- [Instruments](#instruments) + * [Counter](#counter) + + [Counter Add](#counter-add) + * [UpDownCounter](#updowncounter) + + [UpDownCounter Add](#updowncounter-add) + * [Histogram](#histogram) + + [Histogram Record](#histogram-record) + * [Asynchronous Counter](#asynchronous-counter) + * [Asynchronous Counter Observations](#asynchronous-counter-observations) + * [Asynchronous UpDownCounter](#asynchronous-updowncounter) + * [Asynchronous UpDownCounter Observations](#asynchronous-updowncounter-observations) + * [Asynchronous Gauge](#asynchronous-gauge) + * [Asynchronous Gauge Observations](#asynchronous-gauge-observations) From fb27024855ca1ac326a9b88217a60aed4e18ced5 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 2 Feb 2023 11:02:51 -0800 Subject: [PATCH 08/15] Remove API req to treat empty unit/desc as "" --- specification/metrics/api.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index e93b5233ec1..1d4511b0bed 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -215,8 +215,6 @@ DIGIT = %x30-39 ; 0-9 The `unit` is an optional string provided by the author of the Instrument. It SHOULD be treated as an opaque string from the API and SDK. -* If the `unit` is not provided or the `unit` is null, the API MUST make sure - that the behavior is the same as an empty `unit` string. * It MUST be case-sensitive (e.g. `kb` and `kB` are different units), ASCII string. * It can have a maximum length of 63 characters. The number 63 is chosen to @@ -229,9 +227,6 @@ SHOULD be treated as an opaque string from the API and SDK. The `description` is an optional free-form text provided by the author of the instrument. It MUST be treated as an opaque string from the API and SDK. -* If the `description` is not provided or the `description` is null, the API - MUST make sure that the behavior is the same as an empty `description` - string. * It MUST support [BMP (Unicode Plane 0)](https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane), which is basically only the first three bytes of UTF-8 (or `utf8mb3`). From 71e52f21e0714d9dd301e802755cabce91cc4a8e Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 9 Feb 2023 13:28:47 -0800 Subject: [PATCH 09/15] Apply suggestions from code review Co-authored-by: David Ashpole --- specification/metrics/api.md | 2 +- specification/metrics/noop.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index 1d4511b0bed..b7f4fea07a0 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -271,7 +271,7 @@ The API to construct synchronous instruments MUST accept the following parameter The API SHOULD be documented in a way to communicate to users that the `name` parameter needs to conform to the [instrument name - syntax](#instrument-name-syntax). The API SHOULD NOT validate the `name`, + syntax](#instrument-name-syntax). The API SHOULD NOT validate the `name`; that is left to implementations of the API. * A `unit` of measure. diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md index 721bb185d02..86b21be3217 100644 --- a/specification/metrics/noop.md +++ b/specification/metrics/noop.md @@ -55,7 +55,7 @@ footprint as possible. Therefore, all MeterProviders created MUST NOT hold configuration or operational state. Since all MeterProviders a will hold the same empty state, a No-Op MAY -provided the same MeterProvider instances to all creation requests. +provide the same MeterProvider instances to all creation requests. The No-Op is used by OpenTelemetry users to disable OpenTelemetry computation overhead and eliminate OpenTelemetry related output. For @@ -82,7 +82,7 @@ any argument it receives. ## Meter -A Meter is always created by a MeterProvider, the No-Op MUST NOT provide +A Meter is always created by a MeterProvider. The No-Op MUST NOT provide a way for a user to create a Meter other than by a No-Op MeterProvider. The Meters created by the No-Op needs to hold as small a memory From a04838a522e3d4b5b880bcd4eae108a1bcc86361 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 9 Feb 2023 13:39:33 -0800 Subject: [PATCH 10/15] Update Meter Creation from code review --- specification/metrics/noop.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md index 86b21be3217..728746fff61 100644 --- a/specification/metrics/noop.md +++ b/specification/metrics/noop.md @@ -69,8 +69,8 @@ concurrently. [New Meter instances are always created with a MeterProvider](./api.md#meterprovider). Therefore, MeterProviders MUST -allow for the creation of Meters. All Meters created MUST be implemented -by the No-Op. +allow for the creation of Meters. All Meters created MUST be an instance of the +[No-Op Meter](#meter). Since all Meters will hold the same empty state, a MeterProvider MAY return the same Meter instances to all creation requests. From aee8049a9adb5f47f0c25037c2197b155fd1cc3b Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 9 Feb 2023 13:44:58 -0800 Subject: [PATCH 11/15] Link info on instrument identifying fields --- specification/metrics/sdk.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index dc48df539f3..01030701a12 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -597,9 +597,10 @@ model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations) It is unspecified whether or under which conditions the same or different Instrument instance will be returned as a result of duplicate instrument registration. The term _identical_ applied to -Instruments describes instances where all identifying fields are -equal. The term _distinct_ applied to Instruments describes instances -where at least one field value is different. +Instruments describes instances where all [identifying +fields](./api.md#instrument) are equal. The term _distinct_ applied +to Instruments describes instances where at least one field value is +different. Based on [the recommendations from the data model](data-model.md#opentelemetry-protocol-data-model-producer-recommendations), From ff3968f74b982e98cbe4c3639eafb581850cd77c Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 9 Feb 2023 13:48:30 -0800 Subject: [PATCH 12/15] Fix singular possessive --- specification/metrics/noop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md index 728746fff61..fe06ce7b724 100644 --- a/specification/metrics/noop.md +++ b/specification/metrics/noop.md @@ -85,7 +85,7 @@ any argument it receives. A Meter is always created by a MeterProvider. The No-Op MUST NOT provide a way for a user to create a Meter other than by a No-Op MeterProvider. -The Meters created by the No-Op needs to hold as small a memory +The Meters created by the No-Op need to hold as small a memory footprint as possible. Therefore, all Meters created MUST NOT hold configuration or operational state. From e17384dd5b692af251e2b329002ff571753ec19a Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 13 Feb 2023 09:02:05 -0800 Subject: [PATCH 13/15] Apply suggestions from code review Co-authored-by: Anthony Mirabella --- specification/metrics/noop.md | 4 ++-- specification/metrics/sdk.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md index fe06ce7b724..5db31edd0cf 100644 --- a/specification/metrics/noop.md +++ b/specification/metrics/noop.md @@ -1,5 +1,5 @@ # Metrics No-Op API Implementation @@ -54,7 +54,7 @@ The MeterProviders created by the No-Op needs to hold as small a memory footprint as possible. Therefore, all MeterProviders created MUST NOT hold configuration or operational state. -Since all MeterProviders a will hold the same empty state, a No-Op MAY +Since all MeterProviders hold the same empty state, a No-Op MAY provide the same MeterProvider instances to all creation requests. The No-Op is used by OpenTelemetry users to disable OpenTelemetry diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 01030701a12..092c17e1969 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -582,7 +582,7 @@ given instrument before starting a subsequent round of collection. ## Meter -Meters MUST be treated as separate namespaces for the purposes of detecting +Distinct meters MUST be treated as separate namespaces for the purposes of detecting [duplicate instrument registrations](#duplicate-instrument-registration). ### Duplicate instrument registration From cb73f45c708ff7aea14e3b30c925e44685f950c1 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 13 Feb 2023 09:24:39 -0800 Subject: [PATCH 14/15] Require all language impls to provide a No-Op --- specification/metrics/noop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/metrics/noop.md b/specification/metrics/noop.md index 5db31edd0cf..94e72b70325 100644 --- a/specification/metrics/noop.md +++ b/specification/metrics/noop.md @@ -44,7 +44,7 @@ performing any operations. The No-Op OpenTelemetry API implementation functionally. It implements the OpenTelemetry API so that no telemetry is produced and computation resources are minimized. -All language implementations of OpenTelemetry SHOULD provide a No-Op. +All language implementations of OpenTelemetry MUST provide a No-Op. ## MeterProvider From befae3264d7ca4a1dcea0e0acd92c598d3699fb9 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 13 Feb 2023 17:06:10 -0800 Subject: [PATCH 15/15] Remove SDK mention from unit/desc treatment --- specification/metrics/api.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/metrics/api.md b/specification/metrics/api.md index b7f4fea07a0..5bac1968ec0 100644 --- a/specification/metrics/api.md +++ b/specification/metrics/api.md @@ -212,8 +212,8 @@ DIGIT = %x30-39 ; 0-9 #### Instrument unit -The `unit` is an optional string provided by the author of the Instrument. It -SHOULD be treated as an opaque string from the API and SDK. +The `unit` is an optional string provided by the author of the Instrument. The +API SHOULD treat it as an opaque string. * It MUST be case-sensitive (e.g. `kb` and `kB` are different units), ASCII string. @@ -225,7 +225,7 @@ SHOULD be treated as an opaque string from the API and SDK. #### Instrument description The `description` is an optional free-form text provided by the author of the -instrument. It MUST be treated as an opaque string from the API and SDK. +instrument. The API MUST treat it as an opaque string. * It MUST support [BMP (Unicode Plane 0)](https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane),