{"specVersion":"1.61.0","protoVersion":"1.11.1","count":1907,"requirements":[{"id":"ce35056a7770","level":"MUST","text":"To avoid sending any name/value pairs to an untrusted process, the Baggage API MUST provide a way to remove all baggage entries from a context.","section":"specification/baggage/api.md#clear-baggage-in-the-context","sectionTitle":"Clear Baggage in the Context","status":"Stable","source":"spec"},{"id":"309f5bd55ce1","level":"MUST","text":"If a new name/value pair is added and its name is the same as an existing name, then the new pair MUST take precedence.","section":"specification/baggage/api.md#conflict-resolution","sectionTitle":"Conflict Resolution","status":"Stable","source":"spec"},{"id":"1ff4b88d6bf9","level":"MUST","text":"If an implementation of this API does not operate directly on the `Context`, it MUST provide the following functionality to interact with a `Context` instance:","section":"specification/baggage/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"2cc1a191b3df","level":"SHOULD NOT","text":"The functionality listed above is necessary because API users SHOULD NOT have access to the Context Key used by the Baggage API implementation.","section":"specification/baggage/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"b56065f58caa","level":"SHOULD","text":"If the language has support for implicitly propagated `Context` (see here), the API SHOULD also provide the following functionality:","section":"specification/baggage/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"698139eb16c8","level":"MAY","text":"All the above functionalities operate solely on the context API, and they MAY be exposed as static methods on the baggage module, as static methods on a class inside the baggage module (it MAY be named `BaggageUtilities`), or on the `Baggage` class.","section":"specification/baggage/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"e4684864f485","level":"SHOULD","text":"This functionality SHOULD be fully implemented in the API when possible.","section":"specification/baggage/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"52a0b9fc19c2","level":"MUST NOT","text":"The order of name/value pairs MUST NOT be significant.","section":"specification/baggage/api.md#get-all-values","sectionTitle":"Get All Values","status":"Stable","source":"spec"},{"id":"50dbdec29989","level":"MUST","text":"To access the value for a name/value pair set by a prior event, the Baggage API MUST provide a function that takes the name as input, and returns a value associated with the given name, or null if the given name is not present.","section":"specification/baggage/api.md#get-value","sectionTitle":"Get Value","status":"Stable","source":"spec"},{"id":"1f2156dd63dc","level":"REQUIRED","text":"REQUIRED parameters:","section":"specification/baggage/api.md#get-value","sectionTitle":"Get Value","status":"Stable","source":"spec"},{"id":"296f2b4b1112","level":"MUST","text":"Each name in `Baggage` MUST be associated with exactly one value.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"87e6cf9194c8","level":"SHOULD NOT","text":"Language API SHOULD NOT restrict which strings are used as baggage names.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"bcd7fb6d79ac","level":"MUST","text":"Language API MUST accept any valid UTF-8 string as baggage value in `Set` and return the same value from `Get`.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"c6f8368f5df7","level":"MUST","text":"Language API MUST treat both baggage names and values as case sensitive.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"a0daf2ad246d","level":"MAY","text":"Depending on language idioms, a language API MAY implement these functions by interacting with the baggage via the `Context` directly.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"3455298d7fc7","level":"MUST","text":"The Baggage API MUST be fully functional in the absence of an installed SDK.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"64af004e1e4e","level":"MUST","text":"The `Baggage` container MUST be immutable, so that the containing `Context` also remains immutable.","section":"specification/baggage/api.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"4b08bd1426a8","level":"MAY","text":"`Baggage` MAY be propagated across process boundaries or across any arbitrary boundaries (process, $OTHERBOUNDARY1, $OTHERBOUNDARY2, etc) for various reasons.","section":"specification/baggage/api.md#propagation","sectionTitle":"Propagation","status":"Stable","source":"spec"},{"id":"7820e98faedd","level":"MUST","text":"The API layer or an extension package MUST include the following `Propagator`s:","section":"specification/baggage/api.md#propagation","sectionTitle":"Propagation","status":"Stable","source":"spec"},{"id":"79089073818a","level":"MUST","text":"To delete a name/value pair, the Baggage API MUST provide a function which takes a name as input.","section":"specification/baggage/api.md#remove-value","sectionTitle":"Remove Value","status":"Stable","source":"spec"},{"id":"71d1bd970d72","level":"MAY","text":"Depending on language idioms, a language API MAY implement these functions by using a `Builder` pattern and exposing a way to construct a `Builder` from a `Baggage`.","section":"specification/baggage/api.md#remove-value","sectionTitle":"Remove Value","status":"Stable","source":"spec"},{"id":"2d3fc0697846","level":"REQUIRED","text":"REQUIRED parameters:","section":"specification/baggage/api.md#remove-value","sectionTitle":"Remove Value","status":"Stable","source":"spec"},{"id":"ce4a6eabea76","level":"MUST","text":"To record the value for a name/value pair, the Baggage API MUST provide a function which takes a name, and a value as input.","section":"specification/baggage/api.md#set-value","sectionTitle":"Set Value","status":"Stable","source":"spec"},{"id":"e26cfaf644b7","level":"MAY","text":"Depending on language idioms, a language API MAY implement these functions by using a `Builder` pattern and exposing a way to construct a `Builder` from a `Baggage`.","section":"specification/baggage/api.md#set-value","sectionTitle":"Set Value","status":"Stable","source":"spec"},{"id":"80171f345c35","level":"REQUIRED","text":"REQUIRED parameters:","section":"specification/baggage/api.md#set-value","sectionTitle":"Set Value","status":"Stable","source":"spec"},{"id":"d4403dd35f89","level":"OPTIONAL","text":"OPTIONAL parameters:","section":"specification/baggage/api.md#set-value","sectionTitle":"Set Value","status":"Stable","source":"spec"},{"id":"92828485b0c2","level":"SHOULD","text":"Values that represent ordered sequences of other values (such as arrays, vectors, ordered lists, slices) SHOULD be converted to AnyValue's array_value field.","section":"specification/common/attribute-type-mapping.md#array-values","sectionTitle":"Array Values","status":"Development","source":"spec"},{"id":"1bdc5744f543","level":"SHOULD","text":"Values that represent an associative arrays with non-unique keys where multiple values may be associated with the same key (also sometimes known as multimaps, multidicts) SHOULD be converted to AnyValue's kvlist_value field.","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-non-unique-keys","sectionTitle":"Associative Arrays With Non-Unique Keys","status":"Development","source":"spec"},{"id":"29ec8746cb99","level":"MUST","text":"The resulting kvlistvalue field MUST list each key only once and the value of each element of kvlistvalue field MUST be an array represented using AnyValue's arrayvalue field, each element of the arrayvalue representing one value of source array associated with the given key.","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-non-unique-keys","sectionTitle":"Associative Arrays With Non-Unique Keys","status":"Development","source":"spec"},{"id":"73e467666f6a","level":"SHOULD","text":"SHOULD be converted to:","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-non-unique-keys","sectionTitle":"Associative Arrays With Non-Unique Keys","status":"Development","source":"spec"},{"id":"7be19acee89c","level":"SHOULD","text":"Values that represent associative arrays with unique keys (also often known as maps, dictionaries or key-value stores) SHOULD be converted to AnyValue's kvlist_value field.","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-unique-keys","sectionTitle":"Associative Arrays With Unique Keys","status":"Development","source":"spec"},{"id":"0e67d9ce4853","level":"MUST","text":"If the keys of the source array are not strings, they MUST be converted to strings by any means available, often via a toString() or stringify functions available in programming languages.","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-unique-keys","sectionTitle":"Associative Arrays With Unique Keys","status":"Development","source":"spec"},{"id":"9d65931c2aae","level":"MUST","text":"The conversion function MUST be chosen in a way that ensures that the resulting string keys are unique in the target array.","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-unique-keys","sectionTitle":"Associative Arrays With Unique Keys","status":"Development","source":"spec"},{"id":"b68cbe572778","level":"SHOULD","text":"The value part of each element of the source array SHOULD be converted to AnyValue recursively.","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-unique-keys","sectionTitle":"Associative Arrays With Unique Keys","status":"Development","source":"spec"},{"id":"05551ab24141","level":"SHOULD","text":"For example a JSON object `{\"a\": 123, \"b\": \"def\"}` SHOULD be converted to","section":"specification/common/attribute-type-mapping.md#associative-arrays-with-unique-keys","sectionTitle":"Associative Arrays With Unique Keys","status":"Development","source":"spec"},{"id":"d34b318dab5a","level":"SHOULD","text":"Byte sequences (e.g. Go's `[]byte` slice or raw byte content of a file) SHOULD be converted to AnyValue's bytes_value field.","section":"specification/common/attribute-type-mapping.md#byte-sequences","sectionTitle":"Byte Sequences","status":"Development","source":"spec"},{"id":"d47de3fdd32a","level":"SHOULD","text":"Implementations that have source data in any form, such as in-memory objects or data coming from other formats that needs to be converted to AnyValue SHOULD follow the rules described below.","section":"specification/common/attribute-type-mapping.md#converting-to-anyvalue","sectionTitle":"Converting to AnyValue","status":"Development","source":"spec"},{"id":"740fb7399b77","level":"SHOULD","text":"If the source data has no type associated with it and is empty, null, nil or otherwise indicates absence of data it SHOULD be converted to an empty AnyValue, where all the fields are unset.","section":"specification/common/attribute-type-mapping.md#empty-values","sectionTitle":"Empty Values","status":"Development","source":"spec"},{"id":"7e3811063b67","level":"SHOULD","text":"Empty values which has a type associated with them (e.g. empty associative array) SHOULD be converted using the corresponding rules defined for the types above.","section":"specification/common/attribute-type-mapping.md#empty-values","sectionTitle":"Empty Values","status":"Development","source":"spec"},{"id":"2faa4c5e36bb","level":"SHOULD","text":"Values, which belong to a limited enumerated set (e.g. a Java enum), SHOULD be converted to AnyValue's string_value field with the value of the string set to the symbolic name of the enumeration.","section":"specification/common/attribute-type-mapping.md#enumerations","sectionTitle":"Enumerations","status":"Development","source":"spec"},{"id":"61077bea7fd1","level":"SHOULD","text":"If it is not possible to obtain the symbolic name of the enumeration, the implementation SHOULD map enumeration values to AnyValue's int_value field set to the enum's ordinal value, when such an ordinal number is naturally obtainable.","section":"specification/common/attribute-type-mapping.md#enumerations","sectionTitle":"Enumerations","status":"Development","source":"spec"},{"id":"1631b2e2dbd7","level":"SHOULD","text":"If it is also not possible to obtain the ordinal value, the enumeration SHOULD be converted to AnyValue's bytes_value field in any manner that the implementation deems reasonable.","section":"specification/common/attribute-type-mapping.md#enumerations","sectionTitle":"Enumerations","status":"Development","source":"spec"},{"id":"a577b6eeb8ca","level":"SHOULD","text":"Floating point values which are within the range and precision of IEEE 754 64-bit floating point numbers (including IEEE 32-bit floating point values) SHOULD be converted to AnyValue's double_value field.","section":"specification/common/attribute-type-mapping.md#floating-point-values","sectionTitle":"Floating Point Values","status":"Development","source":"spec"},{"id":"803e1b68381d","level":"SHOULD","text":"Floating point values which are outside the range or precision of IEEE 754 64-bit floating point numbers (e.g. IEEE 128-bit floating bit values) SHOULD be converted to AnyValue's string_value field using decimal floating point representation.","section":"specification/common/attribute-type-mapping.md#floating-point-values","sectionTitle":"Floating Point Values","status":"Development","source":"spec"},{"id":"a1de736b3045","level":"SHOULD","text":"Integer values which are within the range of 64 bit signed numbers [-2^63..2^63-1] SHOULD be converted to AnyValue's int_value field.","section":"specification/common/attribute-type-mapping.md#integer-values","sectionTitle":"Integer Values","status":"Development","source":"spec"},{"id":"7f1181579a0b","level":"SHOULD","text":"Integer values which are outside the range of 64 bit signed numbers SHOULD be converted to AnyValue's string_value field using decimal representation.","section":"specification/common/attribute-type-mapping.md#integer-values","sectionTitle":"Integer Values","status":"Development","source":"spec"},{"id":"b9e1115e6a17","level":"SHOULD","text":"Any other values not listed above SHOULD be converted to AnyValue's string_value field if the source data can be serialized to a string (can be stringified) using toString() or stringify functions available in programming languages.","section":"specification/common/attribute-type-mapping.md#other-values","sectionTitle":"Other Values","status":"Development","source":"spec"},{"id":"76e362315069","level":"SHOULD","text":"If the source data cannot be serialized to a string then the value SHOULD be converted AnyValue's bytes_value field by serializing it into a byte sequence by any means available.","section":"specification/common/attribute-type-mapping.md#other-values","sectionTitle":"Other Values","status":"Development","source":"spec"},{"id":"b8d26c490a9f","level":"SHOULD","text":"If the source data cannot be serialized neither to a string nor to a byte sequence then it SHOULD by converted to an empty AnyValue.","section":"specification/common/attribute-type-mapping.md#other-values","sectionTitle":"Other Values","status":"Development","source":"spec"},{"id":"4ae3570a7bcf","level":"SHOULD","text":"Unordered collections of unique values (such as Java Sets, C++ sets, Python Sets) SHOULD be converted to AnyValue's array_value field, where each element of the set becomes an element of the array.","section":"specification/common/attribute-type-mapping.md#sets","sectionTitle":"Sets","status":"Development","source":"spec"},{"id":"e8a1096d1581","level":"SHOULD","text":"String values which are valid UTF-8 sequences SHOULD be converted to AnyValue's string_value field.","section":"specification/common/attribute-type-mapping.md#string-values","sectionTitle":"String Values","status":"Development","source":"spec"},{"id":"3ddaedad8e81","level":"SHOULD","text":"String values which are not valid Unicode sequences SHOULD be converted to AnyValue's bytes_value with the bytes representing the string in the original order and format of the source string.","section":"specification/common/attribute-type-mapping.md#string-values","sectionTitle":"String Values","status":"Development","source":"spec"},{"id":"6757e3de09c0","level":"SHOULD","text":"This tuple SHOULD uniquely identify the logical unit of software that emits the telemetry.","section":"specification/common/instrumentation-scope.md#instrumentation-scope","sectionTitle":"Instrumentation Scope","status":"Stable","source":"spec"},{"id":"d0f0c48888a9","level":"SHOULD","text":"The instrumentation scope's name SHOULD be specified to identify the `InstrumentationScope` name.","section":"specification/common/instrumentation-scope.md#instrumentation-scope","sectionTitle":"Instrumentation Scope","status":"Stable","source":"spec"},{"id":"8288dec31530","level":"SHOULD","text":"The instrumentation scope's optional Schema URL SHOULD identify the Telemetry Schema that the instrumentation's emitted telemetry conforms to.","section":"specification/common/instrumentation-scope.md#instrumentation-scope","sectionTitle":"Instrumentation Scope","status":"Stable","source":"spec"},{"id":"b18a94e5eb15","level":"MUST","text":"OpenTelemetry dropped attributes count MUST be reported as a key-value pair associated with the corresponding data entity (e.g. Span, Span Link, Span Event, Metric data point, LogRecord, etc).","section":"specification/common/mapping-to-non-otlp.md#dropped-attributes-count","sectionTitle":"Dropped Attributes Count","status":"Stable","source":"spec"},{"id":"52bc5f9df0f9","level":"MUST","text":"The key name MUST be `otel.droppedattributescount`.","section":"specification/common/mapping-to-non-otlp.md#dropped-attributes-count","sectionTitle":"Dropped Attributes Count","status":"Stable","source":"spec"},{"id":"a59cb5e3968f","level":"MUST","text":"OpenTelemetry Span's dropped events count MUST be reported as a key-value pair associated with the Span.","section":"specification/common/mapping-to-non-otlp.md#dropped-events-count","sectionTitle":"Dropped Events Count","status":"Stable","source":"spec"},{"id":"27e6d6401243","level":"MUST","text":"The key name MUST be `otel.droppedeventscount`.","section":"specification/common/mapping-to-non-otlp.md#dropped-events-count","sectionTitle":"Dropped Events Count","status":"Stable","source":"spec"},{"id":"7f809c12aa70","level":"MUST","text":"OpenTelemetry Span's dropped links count MUST be reported as a key-value pair associated with the Span.","section":"specification/common/mapping-to-non-otlp.md#dropped-links-count","sectionTitle":"Dropped Links Count","status":"Stable","source":"spec"},{"id":"b90f3fd96ab2","level":"MUST","text":"The key name MUST be `otel.droppedlinkscount`.","section":"specification/common/mapping-to-non-otlp.md#dropped-links-count","sectionTitle":"Dropped Links Count","status":"Stable","source":"spec"},{"id":"fc8ee81dc99d","level":"SHOULD","text":"Exporters to formats that don't have a concept that is equivalent to the Scope SHOULD record the attributes at the most suitable place in their corresponding format, typically at the Span, Metric or LogRecord equivalent.","section":"specification/common/mapping-to-non-otlp.md#instrumentation-scope-attributes","sectionTitle":"Instrumentation Scope Attributes","status":"Stable","source":"spec"},{"id":"b50e835638dc","level":"MUST","text":"OpenTelemetry `InstrumentationScope`'s fields MUST be reported as key-value pairs associated with the Span, Metric Data Point or LogRecord using the following mapping:","section":"specification/common/mapping-to-non-otlp.md#instrumentationscope","sectionTitle":"InstrumentationScope","status":"Stable","source":"spec"},{"id":"75f5bea44861","level":"MUST","text":"The following deprecated aliases MUST also be reported with exact same values for backward compatibility reasons:","section":"specification/common/mapping-to-non-otlp.md#instrumentationscope","sectionTitle":"InstrumentationScope","status":"Stable","source":"spec"},{"id":"d5853b23ffe0","level":"MUST","text":"Note: when a format has a direct semantic equivalent for a particular field or concept then the recommendation in this document MUST be ignored.","section":"specification/common/mapping-to-non-otlp.md#opentelemetry-transformation-to-non-otlp-formats","sectionTitle":"OpenTelemetry Transformation to non-OTLP Formats","status":"Stable","source":"spec"},{"id":"29d269a6b943","level":"MUST","text":"Span `Status` MUST be reported as key-value pairs associated with the Span, unless the `Status` is `UNSET`.","section":"specification/common/mapping-to-non-otlp.md#span-status","sectionTitle":"Span Status","status":"Stable","source":"spec"},{"id":"5249ede498de","level":"MUST NOT","text":"In the latter case it MUST NOT be reported.","section":"specification/common/mapping-to-non-otlp.md#span-status","sectionTitle":"Span Status","status":"Stable","source":"spec"},{"id":"73bd79f7b6f5","level":"MUST NOT","text":"MUST NOT be set if the status code is UNSET. | `OK` | Recommended | | `otel.statusdescription` | string | Description of the Status if it has a value, otherwise not set. | `resource not found` | Recommended |","section":"specification/common/mapping-to-non-otlp.md#span-status","sectionTitle":"Span Status","status":"Stable","source":"spec"},{"id":"465d0a21ffe2","level":"MUST","text":"`otel.status_code` MUST be one of the following:","section":"specification/common/mapping-to-non-otlp.md#span-status","sectionTitle":"Span Status","status":"Stable","source":"spec"},{"id":"ac08017b1597","level":"MUST NOT","text":"A homogeneous array MUST NOT contain values of different types.","section":"specification/common/README.md#anyvalue","sectionTitle":"AnyValue","status":"Stable","source":"spec"},{"id":"6af70abdbca6","level":"SHOULD","text":"APIs SHOULD be documented in a way to communicate to users that using array and map values may carry higher performance overhead compared to primitive values.","section":"specification/common/README.md#anyvalue","sectionTitle":"AnyValue","status":"Stable","source":"spec"},{"id":"a70b80918fb7","level":"MUST","text":"AnyValues expressing an empty value, a numerical value of zero, an empty string, or an empty array are considered meaningful and MUST be stored and passed on to processors / exporters.","section":"specification/common/README.md#anyvalue","sectionTitle":"AnyValue","status":"Stable","source":"spec"},{"id":"85e932af5591","level":"SHOULD","text":"While `null` is a valid attribute value, its use within homogeneous arrays SHOULD generally be avoided unless language constraints make this impossible.","section":"specification/common/README.md#anyvalue","sectionTitle":"AnyValue","status":"Stable","source":"spec"},{"id":"b4ca635e4837","level":"MUST","text":"However, if it is impossible to make sure that no `null` values are accepted (e.g. in languages that do not have appropriate compile-time type checking), `null` values within arrays MUST be preserved as-is (i.e., passed on to processors / exporters as `null`).","section":"specification/common/README.md#anyvalue","sectionTitle":"AnyValue","status":"Stable","source":"spec"},{"id":"9df150123a95","level":"MAY","text":"If exporters do not support exporting `null` values, they MAY replace those values by 0, `false`, or empty strings.","section":"specification/common/README.md#anyvalue","sectionTitle":"AnyValue","status":"Stable","source":"spec"},{"id":"73987e39ff32","level":"SHOULD","text":"For protocols that do not natively support some of the AnyValue types, those values SHOULD be represented as strings following the encoding rules below.","section":"specification/common/README.md#anyvalue-representation-for-non-otlp-protocols","sectionTitle":"AnyValue representation for non-OTLP protocols","status":"Stable","source":"spec"},{"id":"5ed897f928e7","level":"SHOULD","text":"Arrays, except for byte arrays, SHOULD be represented as JSON arrays.","section":"specification/common/README.md#arrays","sectionTitle":"Arrays","status":"Stable","source":"spec"},{"id":"ee489d4575a3","level":"SHOULD","text":"Array elements SHOULD be represented as JSON values using the following rules:","section":"specification/common/README.md#arrays","sectionTitle":"Arrays","status":"Stable","source":"spec"},{"id":"cba2eef6cb44","level":"SHOULD","text":"Integers and floating point numbers as JSON numbers, except that the special floating point values NaN and Infinity SHOULD be represented as JSON strings `\"NaN\"`, `\"Infinity\"`, and `\"-Infinity\"`,","section":"specification/common/README.md#arrays","sectionTitle":"Arrays","status":"Stable","source":"spec"},{"id":"9685674bfb07","level":"MUST","text":"An `Attribute` is a key-value pair, which MUST have the following properties:","section":"specification/common/README.md#attribute","sectionTitle":"Attribute","status":"Stable","source":"spec"},{"id":"10920fbaa130","level":"MUST","text":"The attribute key MUST be a non-`null` and non-empty string.","section":"specification/common/README.md#attribute","sectionTitle":"Attribute","status":"Stable","source":"spec"},{"id":"43ee20b423d3","level":"MUST","text":"The attribute value MUST be one of types defined in AnyValue.","section":"specification/common/README.md#attribute","sectionTitle":"Attribute","status":"Stable","source":"spec"},{"id":"d94ae1200f21","level":"RECOMMENDED","text":"For non-OTLP protocols that need to represent an Attribute Collection as a string, the RECOMMENDED form is a JSON object.","section":"specification/common/README.md#attribute-collection-representation-for-non-otlp","sectionTitle":"Attribute Collection representation for non-OTLP","status":"Stable","source":"spec"},{"id":"532ae37913db","level":"SHOULD","text":"Each attribute key SHOULD be represented as a JSON object member name.","section":"specification/common/README.md#attribute-collection-representation-for-non-otlp","sectionTitle":"Attribute Collection representation for non-OTLP","status":"Stable","source":"spec"},{"id":"6aa2654f8556","level":"SHOULD","text":"Each attribute value SHOULD be represented as the corresponding JSON object member value and follow the encoding rules defined in AnyValue representation for non-OTLP protocols, as it would be represented as an element in an array and a value in a map.","section":"specification/common/README.md#attribute-collection-representation-for-non-otlp","sectionTitle":"Attribute Collection representation for non-OTLP","status":"Stable","source":"spec"},{"id":"ee869c584e80","level":"MUST","text":"Implementation MUST by default enforce that the exported attribute collections contain only unique keys.","section":"specification/common/README.md#attribute-collections","sectionTitle":"Attribute Collections","status":"Stable","source":"spec"},{"id":"9ce0fa0c30ea","level":"SHOULD","text":"Setting an attribute with the same key as an existing attribute SHOULD overwrite the existing attribute's value.","section":"specification/common/README.md#attribute-collections","sectionTitle":"Attribute Collections","status":"Stable","source":"spec"},{"id":"f49586be6193","level":"MAY","text":"Implementations MAY have an option to allow exporting attribute collections with duplicate keys (e.g. for better performance).","section":"specification/common/README.md#attribute-collections","sectionTitle":"Attribute Collections","status":"Stable","source":"spec"},{"id":"d03c558b664c","level":"MUST","text":"If such option is provided, it MUST be documented that for many receivers, handling of maps with duplicate keys is unpredictable and it is the users' responsibility to ensure keys are not duplicate.","section":"specification/common/README.md#attribute-collections","sectionTitle":"Attribute Collections","status":"Stable","source":"spec"},{"id":"28ace25bc550","level":"SHOULD","text":"By default an SDK SHOULD apply truncation as per the list of configurable parameters below.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"a7347336d495","level":"MUST","text":"if it is a string, if it exceeds that limit (counting any character in it as 1), SDKs MUST truncate that value, so that its length is at most equal to the limit,","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"f54d0071d845","level":"MUST","text":"if it is a byte array, if its length exceeds that limit (counting each byte as 1), SDKs MUST truncate that value, so that its length is at most equal to the limit,","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"3c5f4627386c","level":"MUST NOT","text":"otherwise a value MUST NOT be truncated;","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"fdda1e50f724","level":"MUST","text":"if adding an attribute to an attribute collection would result in exceeding the limit (counting each attribute in the collection as 1), the SDK MUST discard that attribute, so that the total number of attributes in an attribute collection is at most equal to the limit;","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"1d8b5974e7ed","level":"MUST NOT","text":"otherwise an attribute MUST NOT be discarded.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"41f7854aacb5","level":"MUST","text":"the SDK MUST start counting depth at 1 for the top-level attribute value, and increment depth when descending into arrays (both homogeneous and heterogeneous) or maps;","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"0da2de34eae2","level":"MUST","text":"arrays or map at a depth greater than the limit MUST be replaced with an empty value;","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"6501454b1256","level":"MUST NOT","text":"otherwise a value MUST NOT be changed due to the depth limit.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"eff4f0a12f28","level":"MAY","text":"There MAY be a log emitted to indicate to the user that an attribute was truncated, discarded, or replaced due to a limit.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"5307f4bf8e8f","level":"MUST NOT","text":"To prevent excessive logging, the log MUST NOT be emitted more than once per record on which an attribute is set.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"3b649e8b823f","level":"MUST","text":"If the SDK implements the limits above, it MUST provide a way to change these limits programmatically.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"1475011d88eb","level":"SHOULD","text":"Names of the configuration options SHOULD be the same as in the list below.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"700d54670537","level":"MAY","text":"An SDK MAY implement model-specific limits, for example `SpanAttributeCountLimit` or `LogRecordAttributeCountLimit`.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"cc7f3f7f8b21","level":"MUST","text":"If both a general and a model-specific limit are implemented, then the SDK MUST first attempt to use the model-specific limit, if it isn't set, then the SDK MUST attempt to use the general limit.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"3329a78d0977","level":"MUST","text":"If neither are defined, then the SDK MUST try to use the model-specific limit default value, followed by the global limit default value.","section":"specification/common/README.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"69c47ccce37e","level":"RECOMMENDED","text":"For non-OTLP protocols that need to represent a single `Attribute` as a string, the RECOMMENDED form is a JSON object containing a single name/value pair (member).","section":"specification/common/README.md#attribute-representation-for-non-otlp","sectionTitle":"Attribute representation for non-OTLP","status":"Stable","source":"spec"},{"id":"549992aefff7","level":"SHOULD","text":"The attribute key SHOULD be represented as a JSON object member name.","section":"specification/common/README.md#attribute-representation-for-non-otlp","sectionTitle":"Attribute representation for non-OTLP","status":"Stable","source":"spec"},{"id":"baee65d7796b","level":"SHOULD","text":"The attribute value SHOULD be represented as a JSON object member value and follow the encoding rules defined in AnyValue representation for non-OTLP protocols, as it would be represented as an element in an array and a value in a map.","section":"specification/common/README.md#attribute-representation-for-non-otlp","sectionTitle":"Attribute representation for non-OTLP","status":"Stable","source":"spec"},{"id":"a86e022be3eb","level":"SHOULD","text":"Booleans SHOULD be represented as JSON booleans.","section":"specification/common/README.md#booleans","sectionTitle":"Booleans","status":"Stable","source":"spec"},{"id":"281db7124ae9","level":"SHOULD","text":"Byte arrays SHOULD be Base64-encoded.","section":"specification/common/README.md#byte-arrays","sectionTitle":"Byte Arrays","status":"Stable","source":"spec"},{"id":"5331b146e9e0","level":"SHOULD NOT","text":"They SHOULD NOT be encoded as JSON strings (with explicit surrounding quotes).","section":"specification/common/README.md#byte-arrays","sectionTitle":"Byte Arrays","status":"Stable","source":"spec"},{"id":"23920dc1e508","level":"SHOULD","text":"Empty values SHOULD be represented as the empty string.","section":"specification/common/README.md#empty-values","sectionTitle":"Empty Values","status":"Stable","source":"spec"},{"id":"5c620e110f7c","level":"SHOULD NOT","text":"They SHOULD NOT be encoded as a JSON string (with explicit surrounding quotes).","section":"specification/common/README.md#empty-values","sectionTitle":"Empty Values","status":"Stable","source":"spec"},{"id":"bf19d22575ba","level":"SHOULD","text":"Resource attributes SHOULD be exempt from the limits described above as resources are not susceptible to the scenarios (auto-instrumentation) that result in excessive attributes count or size.","section":"specification/common/README.md#exempt-entities","sectionTitle":"Exempt Entities","status":"Stable","source":"spec"},{"id":"74f8da10ebe1","level":"SHOULD","text":"Floating point numbers SHOULD be represented as JSON numbers.","section":"specification/common/README.md#floating-point-numbers","sectionTitle":"Floating Point Numbers","status":"Stable","source":"spec"},{"id":"4b16cb24d21e","level":"SHOULD","text":"The special floating point values NaN and Infinity SHOULD be represented as `NaN`, `Infinity`, and `-Infinity`.","section":"specification/common/README.md#floating-point-numbers","sectionTitle":"Floating Point Numbers","status":"Stable","source":"spec"},{"id":"7f6de8534d5e","level":"SHOULD NOT","text":"They SHOULD NOT be encoded as JSON strings (with explicit surrounding quotes).","section":"specification/common/README.md#floating-point-numbers","sectionTitle":"Floating Point Numbers","status":"Stable","source":"spec"},{"id":"a8aabb4e5b14","level":"SHOULD","text":"Integers SHOULD be represented as JSON numbers.","section":"specification/common/README.md#integers","sectionTitle":"Integers","status":"Stable","source":"spec"},{"id":"27ea1fdbea2a","level":"SHOULD","text":"Maps SHOULD be represented as JSON objects.","section":"specification/common/README.md#maps","sectionTitle":"Maps","status":"Stable","source":"spec"},{"id":"b8e3541558c6","level":"SHOULD","text":"Map keys SHOULD be represented as JSON string member names.","section":"specification/common/README.md#maps","sectionTitle":"Maps","status":"Stable","source":"spec"},{"id":"55af68400275","level":"SHOULD","text":"Map values SHOULD be represented using the same rules as array elements.","section":"specification/common/README.md#maps","sectionTitle":"Maps","status":"Stable","source":"spec"},{"id":"aa0e7aa9d154","level":"MUST","text":"Case sensitivity of keys MUST be preserved.","section":"specification/common/README.md#mapstring-anyvalue","sectionTitle":"map<string, AnyValue>","status":"Stable","source":"spec"},{"id":"81a5827b4ad4","level":"MUST","text":"The implementation MUST by default enforce that the exported maps contain only unique keys.","section":"specification/common/README.md#mapstring-anyvalue","sectionTitle":"map<string, AnyValue>","status":"Stable","source":"spec"},{"id":"264e24723db2","level":"MAY","text":"The implementation MAY have an option to allow exporting maps with duplicate keys (e.g. for better performance).","section":"specification/common/README.md#mapstring-anyvalue","sectionTitle":"map<string, AnyValue>","status":"Stable","source":"spec"},{"id":"c0033f490dac","level":"MUST","text":"If such option is provided, it MUST be documented that for many receivers, handling of maps with duplicate keys is unpredictable and it is the users' responsibility to ensure keys are not duplicate.","section":"specification/common/README.md#mapstring-anyvalue","sectionTitle":"map<string, AnyValue>","status":"Stable","source":"spec"},{"id":"57ffea899d29","level":"SHOULD","text":"Strings SHOULD be represented as-is without any additional encoding.","section":"specification/common/README.md#strings","sectionTitle":"Strings","status":"Stable","source":"spec"},{"id":"c4b416c82ea2","level":"SHOULD NOT","text":"They SHOULD NOT be encoded as JSON strings (with explicit surrounding quotes).","section":"specification/common/README.md#strings","sectionTitle":"Strings","status":"Stable","source":"spec"},{"id":"7e8eabecde6a","level":"SHOULD","text":"The fields SHOULD be recorded as top-level fields in the JSON structure.","section":"specification/compatibility/logging_trace_context.md#json-formats","sectionTitle":"JSON Formats","status":"Stable","source":"spec"},{"id":"a6ac68886c76","level":"SHOULD","text":"The fields SHOULD be recorded as top-level structured attributes of the log record as it is customary for the particular format.","section":"specification/compatibility/logging_trace_context.md#other-structured-formats","sectionTitle":"Other Structured Formats","status":"Stable","source":"spec"},{"id":"5b834d8540fc","level":"SHOULD","text":"The fields SHOULD be recorded according to the customary approach used for a particular format (e.g. field:value format for LTSV).","section":"specification/compatibility/logging_trace_context.md#plain-text-formats","sectionTitle":"Plain Text Formats","status":"Stable","source":"spec"},{"id":"0933496a3ac7","level":"SHOULD","text":"Trace ID, span ID and traceflags SHOULD be recorded via SD-ID \"OpenTelemetry\".","section":"specification/compatibility/logging_trace_context.md#syslog-rfc5424","sectionTitle":"Syslog RFC5424","status":"Stable","source":"spec"},{"id":"0e46ecb1de50","level":"MUST","text":"When the shim is in place, all OpenCensus Spans MUST be sent through an OpenTelemetry `Tracer` as specified for the OpenTelemetry API.","section":"specification/compatibility/opencensus.md#creating-spans-in-opencensus","sectionTitle":"Creating Spans in OpenCensus","status":"Deprecated","source":"spec"},{"id":"7b2dd73df506","level":"SHOULD","text":"This mechanism SHOULD be seamless to the user in languages that allow discovery and auto injection of dependencies.","section":"specification/compatibility/opencensus.md#creating-spans-in-opencensus","sectionTitle":"Creating Spans in OpenCensus","status":"Deprecated","source":"spec"},{"id":"860a5fda3212","level":"MUST","text":"The shim MUST add an instrumentation scope name and version which identifies the shim.","section":"specification/compatibility/opencensus.md#instrumentation-scope","sectionTitle":"Instrumentation Scope","status":"Deprecated","source":"spec"},{"id":"0451b4c0ee11","level":"MUST","text":"OpenTelemetry does not support OpenCensus' GaugeHistogram type; these metrics MUST be dropped when using the bridge.","section":"specification/compatibility/opencensus.md#known-incompatibilities-1","sectionTitle":"Known Incompatibilities","status":"Deprecated","source":"spec"},{"id":"67d995638760","level":"MUST","text":"This adapter MUST provide an implementation of OpenCensus `BinaryPropagator` to write OpenCensus binary format using OpenTelemetry's context.","section":"specification/compatibility/opencensus.md#opencensus-binary-context-propagation","sectionTitle":"OpenCensus Binary Context Propagation","status":"Deprecated","source":"spec"},{"id":"a4575588a68e","level":"MUST","text":"The `BinaryPropagator` MUST be a TextMapPropagator if possible in the language.","section":"specification/compatibility/opencensus.md#opencensus-binary-context-propagation","sectionTitle":"OpenCensus Binary Context Propagation","status":"Deprecated","source":"spec"},{"id":"7f3e9652087d","level":"SHOULD NOT","text":"Otherwise, the `BinaryPropagator` MUST be a library, which is expected to be used by OpenTelemetry gRPC instrumentation. gRPC instrumentation in those languages SHOULD NOT enable the `BinaryPropagator` by default, but SHOULD provide configuration to allow users to enable it.","section":"specification/compatibility/opencensus.md#opencensus-binary-context-propagation","sectionTitle":"OpenCensus Binary Context Propagation","status":"Deprecated","source":"spec"},{"id":"62c750dd0b15","level":"MAY","text":"> [!NOTE] > OpenCensus compatibility requirements are deprecated. > Existing OpenCensus shims MAY continue to be supported for backwards > compatibility, but implementing new OpenCensus compatibility is not required > by this specification. > > OpenCensus compatibility requirements are deprecated as of June 2026. > OpenCensus compatibility requirements in this specification will be removed > no earlier than June 2027.","section":"specification/compatibility/opencensus.md#opencensus-compatibility","sectionTitle":"OpenCensus Compatibility","status":"Deprecated","source":"spec"},{"id":"5ffee98c631e","level":"MUST","text":"This component MUST be an optional dependency.","section":"specification/compatibility/opencensus.md#requirements","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"eb50a4deee92","level":"MUST","text":"This component MUST be an optional dependency","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"2b906ff55004","level":"MUST NOT","text":"MUST NOT require OpenTelemetry to be included in OpenCensus API distributions","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"5afd9e205f24","level":"SHOULD NOT","text":"SHOULD NOT require OpenCensus to depend on OpenTelemetry at runtime","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"cb144e9a962a","level":"MUST","text":"MUST require few or no changes to OpenCensus","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"10bd34614873","level":"MUST","text":"MUST be compatible with push and pull exporters","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"2d710f5e1efe","level":"MUST","text":"MUST support Gauges, Counters, Cumulative Histograms, and Summaries","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"76ac832d17e6","level":"REQUIRED","text":"Is NOT REQUIRED to support Gauge Histograms","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"0396f54fa53a","level":"MUST","text":"MUST support exemplar span context in language that provide utilities for recording span context in exemplars","section":"specification/compatibility/opencensus.md#requirements-1","sectionTitle":"Requirements","status":"Deprecated","source":"spec"},{"id":"5f583eba0d1e","level":"MUST","text":"The shim MUST discard the resource attached to OpenCensus metrics, and insert the resource provided during initialization, or fall back to the the default OpenTelemetry resource.","section":"specification/compatibility/opencensus.md#resource","sectionTitle":"Resource","status":"Deprecated","source":"spec"},{"id":"82b5258d7d57","level":"MUST NOT","text":"This layer MUST NOT rely on implementation specific details of the OpenTelemetry SDK.","section":"specification/compatibility/opencensus.md#trace-bridge","sectionTitle":"Trace Bridge","status":"Deprecated","source":"spec"},{"id":"3b108423a987","level":"MUST NOT","text":"This Shim Layer MUST NOT publicly expose any upstream OpenTelemetry API.","section":"specification/compatibility/opencensus.md#trace-bridge","sectionTitle":"Trace Bridge","status":"Deprecated","source":"spec"},{"id":"31ca288d1fdd","level":"MUST NOT","text":"This layer MUST NOT rely on implementation specific details of any SDK.","section":"specification/compatibility/opentracing.md#abstract","sectionTitle":"Abstract","status":"Deprecated","source":"spec"},{"id":"79fe2e45bd73","level":"MUST NOT","text":"This Shim Layer MUST NOT publicly expose any upstream OpenTelemetry API.","section":"specification/compatibility/opentracing.md#abstract","sectionTitle":"Abstract","status":"Deprecated","source":"spec"},{"id":"3fcbb455bf23","level":"SHOULD NOT","text":"Semantic convention mapping SHOULD NOT be performed, with the exception of error mapping, as described in the Set Tag and Log sections.","section":"specification/compatibility/opentracing.md#abstract","sectionTitle":"Abstract","status":"Deprecated","source":"spec"},{"id":"76d902add24a","level":"MUST","text":"If the specified `Span` is null, it MUST be set to a NonRecordableSpan wrapping an invalid `SpanContext`, to signal there is no active `Span` nor `Baggage`.","section":"specification/compatibility/opentracing.md#activate-a-span","sectionTitle":"Activate a Span","status":"Deprecated","source":"spec"},{"id":"09d74ebd1ca0","level":"OPTIONAL","text":"OPTIONAL operation.","section":"specification/compatibility/opentracing.md#close","sectionTitle":"Close","status":"Deprecated","source":"spec"},{"id":"14cfaedffdd8","level":"MUST","text":"If this operation is implemented for a specific OpenTracing language, it MUST close the underlying `TracerProvider` if it implements a \"closeable\" interface or method; otherwise it MUST be defined as a no-op operation.","section":"specification/compatibility/opentracing.md#close","sectionTitle":"Close","status":"Deprecated","source":"spec"},{"id":"7a6e6398a2ad","level":"MUST","text":"The Shim layer MUST protect against errors or exceptions raised while closing the underlying `TracerProvider`.","section":"specification/compatibility/opentracing.md#close","sectionTitle":"Close","status":"Deprecated","source":"spec"},{"id":"e4398d95ccd0","level":"MUST","text":"This operation MUST accept the following parameters:","section":"specification/compatibility/opentracing.md#create-an-opentracing-tracer-shim","sectionTitle":"Create an OpenTracing Tracer Shim","status":"Deprecated","source":"spec"},{"id":"b54324511d7b","level":"MUST","text":"This operation MUST use this `TracerProvider` to obtain a `Tracer` with the name `opentracing-shim` along with the current shim library version.","section":"specification/compatibility/opentracing.md#create-an-opentracing-tracer-shim","sectionTitle":"Create an OpenTracing Tracer Shim","status":"Deprecated","source":"spec"},{"id":"6efb245da1b9","level":"MUST","text":"The API MUST return an OpenTracing `Tracer`.","section":"specification/compatibility/opentracing.md#create-an-opentracing-tracer-shim","sectionTitle":"Create an OpenTracing Tracer Shim","status":"Deprecated","source":"spec"},{"id":"209af1e57cfd","level":"MUST","text":"`TextMap` and `HttpHeaders` formats MUST use their explicitly specified `TextMapPropagator`, if any, or else use the global `TextMapPropagator`.","section":"specification/compatibility/opentracing.md#extract","sectionTitle":"Extract","status":"Deprecated","source":"spec"},{"id":"9faaaa05143f","level":"MUST","text":"The operation MUST return a `SpanContext` Shim instance with the extracted values if any of these conditions are met:","section":"specification/compatibility/opentracing.md#extract","sectionTitle":"Extract","status":"Deprecated","source":"spec"},{"id":"f8ef77925299","level":"MUST","text":"Otherwise, the operation MUST return null or empty value.","section":"specification/compatibility/opentracing.md#extract","sectionTitle":"Extract","status":"Deprecated","source":"spec"},{"id":"7486d5fa96e5","level":"MAY","text":"Errors MAY be raised if either the `Format` is not recognized or no value could be extracted, depending on the specific OpenTracing Language API (e.g. Go and Python do, but Java may not).","section":"specification/compatibility/opentracing.md#extract","sectionTitle":"Extract","status":"Deprecated","source":"spec"},{"id":"0fda19b0e5a2","level":"MUST","text":"If an explicit timestamp is specified, a conversion MUST be done to match the OpenTracing and OpenTelemetry units.","section":"specification/compatibility/opentracing.md#finish","sectionTitle":"Finish","status":"Deprecated","source":"spec"},{"id":"b6e40b2be981","level":"MUST","text":"This operation MUST be safe to be called concurrently.","section":"specification/compatibility/opentracing.md#get-baggage-item","sectionTitle":"Get Baggage Item","status":"Deprecated","source":"spec"},{"id":"572502850f28","level":"MUST","text":"This operation MUST be safe to be called concurrently.","section":"specification/compatibility/opentracing.md#get-context","sectionTitle":"Get Context","status":"Deprecated","source":"spec"},{"id":"997c1dd06346","level":"MUST","text":"This operation MUST immediately return null if the current OpenTelemetry `Span`'s `SpanContext` is invalid and the current `Baggage` is empty, to signal there is no active `Span` nor `Baggage`.","section":"specification/compatibility/opentracing.md#get-the-active-span","sectionTitle":"Get the active Span","status":"Deprecated","source":"spec"},{"id":"666db37928d7","level":"MUST","text":"If the current OpenTelemetry `Span`'s `SpanContext` is invalid but the current `Baggage` is not empty, this operation MUST return a new `Span` Shim containing a no-op OpenTelemetry `Span` and the non-empty `Baggage`.","section":"specification/compatibility/opentracing.md#get-the-active-span","sectionTitle":"Get the active Span","status":"Deprecated","source":"spec"},{"id":"b1dc23c28149","level":"MUST","text":"If there are matching OpenTelemetry `Span` and `Span` Shim objects in the current `Context`, the `Span` Shim MUST be returned.","section":"specification/compatibility/opentracing.md#get-the-active-span","sectionTitle":"Get the active Span","status":"Deprecated","source":"spec"},{"id":"44268fee753c","level":"MUST","text":"Else, a new `Span` Shim containing the current OpenTelemetry `Span` and `Baggage` MUST be returned.","section":"specification/compatibility/opentracing.md#get-the-active-span","sectionTitle":"Get the active Span","status":"Deprecated","source":"spec"},{"id":"7518f583feae","level":"MUST","text":"For languages with implicit in-process propagation support in OpenTelemetry and none in OpenTracing (i.e. no ScopeManager support), the Shim MUST only use explicit context propagation in its operations (e.g. when starting a new `Span`).","section":"specification/compatibility/opentracing.md#implicit-and-explicit-support-mismatch","sectionTitle":"Implicit and Explicit support mismatch","status":"Deprecated","source":"spec"},{"id":"766a30c6cbe0","level":"MAY","text":"For this case, the Shim MAY offer in-Development integration with the OpenTelemetry implicit in-process propagation via an explicit setting, warning the user incorrect parent values may be consumed:","section":"specification/compatibility/opentracing.md#implicit-and-explicit-support-mismatch","sectionTitle":"Implicit and Explicit support mismatch","status":"Deprecated","source":"spec"},{"id":"4f34aa4c4e39","level":"MUST","text":"`TextMap` and `HttpHeaders` formats MUST use their explicitly specified `TextMapPropagator`, if any, or else use the global `TextMapPropagator`.","section":"specification/compatibility/opentracing.md#inject","sectionTitle":"Inject","status":"Deprecated","source":"spec"},{"id":"8be6f3c30b17","level":"MUST","text":"It MUST inject any non-empty `Baggage` even amidst no valid `SpanContext`.","section":"specification/compatibility/opentracing.md#inject","sectionTitle":"Inject","status":"Deprecated","source":"spec"},{"id":"11b9f64b18f4","level":"MAY","text":"Errors MAY be raised if the specified `Format` is not recognized, depending on the specific OpenTracing Language API (e.g. Go and Python do, but Java may not).","section":"specification/compatibility/opentracing.md#inject","sectionTitle":"Inject","status":"Deprecated","source":"spec"},{"id":"529f0077f74b","level":"MUST","text":"The `Add Event`'s `name` parameter MUST be the value with the `event` key in the pair set, or else fallback to use the `log` literal string.","section":"specification/compatibility/opentracing.md#log","sectionTitle":"Log","status":"Deprecated","source":"spec"},{"id":"ec6633bbc5a4","level":"MUST","text":"If pair set contains an `event=error` entry, the values MUST be mapped to an `Event` with the conventions outlined in the Exception semantic conventions document:","section":"specification/compatibility/opentracing.md#log","sectionTitle":"Log","status":"Deprecated","source":"spec"},{"id":"434c4d89cc92","level":"MUST","text":"If an explicit timestamp is specified, a conversion MUST be done to match the OpenTracing and OpenTelemetry units.","section":"specification/compatibility/opentracing.md#log","sectionTitle":"Log","status":"Deprecated","source":"spec"},{"id":"d2c8d3e2e1a9","level":"MAY","text":"> [!NOTE] > OpenTracing compatibility requirements are deprecated. > Existing OpenTracing shims MAY continue to be supported for backwards > compatibility, but implementing new OpenTracing compatibility is not required > by this specification. > > OpenTracing compatibility requirements are deprecated as of March 2026. > OpenTracing compatibility requirements in this specification will be removed > no earlier than March 2027.","section":"specification/compatibility/opentracing.md#opentracing-compatibility","sectionTitle":"OpenTracing Compatibility","status":"Deprecated","source":"spec"},{"id":"5712b2cb6213","level":"MUST","text":"For OpenTracing languages implementing the `ScopeManager` interface, its operations MUST be implemented using the OpenTelemetry Context Propagation API in order to get and set active `Context` instances.","section":"specification/compatibility/opentracing.md#scopemanager-shim","sectionTitle":"ScopeManager Shim","status":"Deprecated","source":"spec"},{"id":"60b57dff0425","level":"MUST","text":"This operation MUST be safe to be called concurrently.","section":"specification/compatibility/opentracing.md#set-baggage-item","sectionTitle":"Set Baggage Item","status":"Deprecated","source":"spec"},{"id":"ebf527cb9e8e","level":"MUST","text":"The `error` tag MUST be mapped to StatusCode:","section":"specification/compatibility/opentracing.md#set-tag","sectionTitle":"Set Tag","status":"Deprecated","source":"spec"},{"id":"e804351c3a61","level":"MUST","text":"If the type of the specified value is not supported by the OTel API, the value MUST be converted to a string.","section":"specification/compatibility/opentracing.md#set-tag","sectionTitle":"Set Tag","status":"Deprecated","source":"spec"},{"id":"786e2005b00b","level":"MUST","text":"The OpenTracing `Span` operations MUST be implemented using the underlying OpenTelemetry `Span` and `Baggage` values with the help of a `SpanContext` Shim object.","section":"specification/compatibility/opentracing.md#span-shim","sectionTitle":"Span Shim","status":"Deprecated","source":"spec"},{"id":"cc06b5116cb9","level":"MUST","text":"The `Log` operations MUST be implemented using the OpenTelemetry `Span`'s `Add Events` operations.","section":"specification/compatibility/opentracing.md#span-shim","sectionTitle":"Span Shim","status":"Deprecated","source":"spec"},{"id":"c0a10237a433","level":"MUST","text":"The `Set Tag` operations MUST be implemented using the OpenTelemetry `Span`'s `Set Attributes` operations.","section":"specification/compatibility/opentracing.md#span-shim","sectionTitle":"Span Shim","status":"Deprecated","source":"spec"},{"id":"bee50c422078","level":"MUST","text":"As per the OpenTracing Specification, the OpenTracing `SpanContext` Shim MUST contain `Baggage` data and it MUST be immutable.","section":"specification/compatibility/opentracing.md#span-shim-and-spancontext-shim-relationship","sectionTitle":"Span Shim and SpanContext Shim relationship","status":"Deprecated","source":"spec"},{"id":"06b4f06edbf8","level":"MUST","text":"In turn, the OpenTracing `Span` Shim MUST contain a `SpanContext` Shim.","section":"specification/compatibility/opentracing.md#span-shim-and-spancontext-shim-relationship","sectionTitle":"Span Shim and SpanContext Shim relationship","status":"Deprecated","source":"spec"},{"id":"9044cbe40b24","level":"MUST","text":"When updating its associated baggage, the OpenTracing `Span` MUST set its OpenTracing `SpanContext` Shim to a new instance containing the updated `Baggage`.","section":"specification/compatibility/opentracing.md#span-shim-and-spancontext-shim-relationship","sectionTitle":"Span Shim and SpanContext Shim relationship","status":"Deprecated","source":"spec"},{"id":"be4ede9aa7ed","level":"MUST","text":"Operations accessing the associated `Baggage` MUST be safe to be called concurrently.","section":"specification/compatibility/opentracing.md#span-shim-and-spancontext-shim-relationship","sectionTitle":"Span Shim and SpanContext Shim relationship","status":"Deprecated","source":"spec"},{"id":"4e06a8018aeb","level":"MUST","text":"`SpanContext` Shim MUST be immutable and MUST contain the associated `SpanContext` and `Baggage` values.","section":"specification/compatibility/opentracing.md#spancontext-shim","sectionTitle":"SpanContext Shim","status":"Deprecated","source":"spec"},{"id":"a866326ceaca","level":"MUST","text":"All values in the list MUST be added as Links with the reference type value as a `Link` attribute, i.e. opentracing.reftype set to `followsfrom` or `child_of`.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"724b25c26d26","level":"MUST","text":"If a list of `Span` references is specified, the union of their `Baggage` values MUST be used as the initial `Baggage` of the newly created `Span`.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"a711ba0aee24","level":"MUST","text":"If no such list of references is specified, the current `Baggage` MUST be used as the initial value of the newly created `Span`.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"74262166316b","level":"MUST","text":"If an initial set of tags is specified, the values MUST be set at the creation time of the OpenTelemetry `Span`, as opposed to setting them after the `Span` is already created.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"c843c9b45b5a","level":"MUST","text":"If an initial set of tags is specified and the OpenTracing `error` tag is included, after the OpenTelemetry `Span` was created the Shim layer MUST perform the same error handling as described in the Set Tag operation.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"9386617c68c1","level":"MUST","text":"If an explicit start timestamp is specified, a conversion MUST be done to match the OpenTracing and OpenTelemetry units.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"637af136008c","level":"MUST","text":"The API MUST return an OpenTracing `Span`.","section":"specification/compatibility/opentracing.md#start-a-new-span","sectionTitle":"Start a new Span","status":"Deprecated","source":"spec"},{"id":"2dc4d54f33a6","level":"MUST","text":"A Prometheus Counter MUST be converted to an OTLP Sum with `is_monotonic` equal to `true`.","section":"specification/compatibility/prometheus_and_openmetrics.md#counters","sectionTitle":"Counters","status":"Mixed","source":"spec"},{"id":"3605af8a49a3","level":"MUST","text":"Exemplars on the Prometheus Counter Sample MUST be converted to OpenTelemetry Exemplars on the OpenTelemetry Sum data point following the rules in Exemplars.","section":"specification/compatibility/prometheus_and_openmetrics.md#counters","sectionTitle":"Counters","status":"Mixed","source":"spec"},{"id":"23abccc24cc5","level":"MUST","text":"Exemplars MUST be dropped if they are not supported.","section":"specification/compatibility/prometheus_and_openmetrics.md#differences-between-prometheus-formats","sectionTitle":"Differences between Prometheus formats","status":"Mixed","source":"spec"},{"id":"c1fa4c92eee1","level":"MUST","text":"If the specification below requires producing a Prometheus Info-typed metric, a Prometheus Gauge with an additional `_info` name suffix MUST be produced if Info-typed metrics are not supported.","section":"specification/compatibility/prometheus_and_openmetrics.md#differences-between-prometheus-formats","sectionTitle":"Differences between Prometheus formats","status":"Mixed","source":"spec"},{"id":"591487d8e835","level":"MUST","text":"If the specification below requires producing a Prometheus StateSet-typed metric, a Prometheus Gauge MUST be produced instead if StateSet-typed metrics are not supported.","section":"specification/compatibility/prometheus_and_openmetrics.md#differences-between-prometheus-formats","sectionTitle":"Differences between Prometheus formats","status":"Mixed","source":"spec"},{"id":"0a927e092d73","level":"SHOULD","text":"Exponential (Native) Histograms SHOULD be dropped if they are not supported, or MAY be converted to fixed-bucket histograms.","section":"specification/compatibility/prometheus_and_openmetrics.md#differences-between-prometheus-formats","sectionTitle":"Differences between Prometheus formats","status":"Mixed","source":"spec"},{"id":"037fb99c17ca","level":"MUST","text":"The following Prometheus types MUST be dropped:","section":"specification/compatibility/prometheus_and_openmetrics.md#dropped-types","sectionTitle":"Dropped Types","status":"Mixed","source":"spec"},{"id":"62ea450f7048","level":"MUST","text":"When an exemplar is converted per the metric-type-specific sections above, the OpenTelemetry Exemplar MUST be converted to a Prometheus exemplar if the Prometheus (push or pull) protocol being used supports them, as follows:","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplar-conversion","sectionTitle":"Exemplar Conversion","status":"Mixed","source":"spec"},{"id":"1b67000a3d07","level":"MUST","text":"If present, the OpenTelemetry Exemplar's Trace ID and Span ID MUST be added as Exemplar labels using the `traceid` and `spanid` keys, respectively.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplar-conversion","sectionTitle":"Exemplar Conversion","status":"Mixed","source":"spec"},{"id":"b12f32346164","level":"MUST","text":"These labels MUST take precedence over labels from `filtered_attributes` in cases where there is a key collision.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplar-conversion","sectionTitle":"Exemplar Conversion","status":"Mixed","source":"spec"},{"id":"869e3eb628e2","level":"MUST","text":"Timestamps MUST be added as timestamps on the Prometheus exemplar.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplar-conversion","sectionTitle":"Exemplar Conversion","status":"Mixed","source":"spec"},{"id":"2e13541a557d","level":"MUST","text":"`filtered_attributes` MUST be added as labels on the Prometheus exemplar, unless they would exceed the Prometheus protocol's exemplar limits.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplar-conversion","sectionTitle":"Exemplar Conversion","status":"Mixed","source":"spec"},{"id":"c9e700e7ef8b","level":"MUST","text":"Prometheus Exemplars MUST be converted to OpenTelemetry Exemplars as follows:","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplars","sectionTitle":"Exemplars","status":"Mixed","source":"spec"},{"id":"ba16d72f7931","level":"MUST","text":"If present, the timestamp MUST be used as the OpenTelemetry exemplar's timestamp.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplars","sectionTitle":"Exemplars","status":"Mixed","source":"spec"},{"id":"38604a93760c","level":"MUST","text":"If present, and if the values are valid Trace and Span IDs, the `traceid` and `spanid` labels MUST be converted to the OpenTelemetry Exemplar's Trace ID and Span ID, respectively.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplars","sectionTitle":"Exemplars","status":"Mixed","source":"spec"},{"id":"a2e1128fefc7","level":"MUST","text":"All labels other than `traceid` and `spanid` MUST be added to the OpenTelemetry exemplar as filtered attributes.","section":"specification/compatibility/prometheus_and_openmetrics.md#exemplars","sectionTitle":"Exemplars","status":"Mixed","source":"spec"},{"id":"b907ad867011","level":"MUST","text":"An OpenTelemetry Exponential Histogram with a cumulative aggregation temporality MUST be converted to a Prometheus Native Histogram with standard (exponential) schema as follows:","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"81cdc9764bf3","level":"MUST","text":"The flavor of the Native Histogram MUST be of the integer and counter flavor.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"2a28fc7ca812","level":"MUST","text":"The `ResetHint` (or `CounterResetHint`) in the Native Histogram MUST be set to `UNKNOWN`.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"48834b6abcac","level":"SHOULD","text":"If `Scale` is > 8 then Exponential Histogram data points SHOULD be downscaled to a scale accepted by Prometheus.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"8a4845d88674","level":"MUST","text":"If `Scale` is < -4, the data point MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"91ada6bb5ba9","level":"MUST","text":"Any data point unable to be rescaled to an acceptable range MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"1d35e3ecd615","level":"SHOULD","text":"If set, `StartTimeUnixNano` SHOULD be transformed into Prometheus `StartTime`, following the appropriate format used by each Prometheus protocol.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"e28a1390c4a5","level":"MUST","text":"All fields of the Native Histogram that are not explicitly referenced here MUST be set to their zero value, such as custom values.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"6e1d330b5ee4","level":"MUST","text":"If the `NoRecordedValue` flag is set to `true`, the Native Histogram MUST be marked as stale:","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"43c7e91ed015","level":"MUST","text":"The Native Histogram `Sum` MUST be set to the Stale NaN value.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"ebe44b861a6c","level":"MUST","text":"The Native Histogram `Count` MUST be set to zero.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"08f0546513e3","level":"MUST","text":"`ZeroCount`, `PositiveSpans`, `PositiveDeltas`, `NegativeSpans`, and `NegativeDeltas` MUST be left empty.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"b344f6e627b1","level":"MUST","text":"`Sum`, if set, is converted to the Native Histogram `Sum`; otherwise, the metric point MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"1e4e4c5e00a3","level":"MUST","text":"Non-zero bucket counts MUST be converted into `PositiveDeltas` (or `NegativeDeltas`).","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"88d5bb6d697e","level":"MAY","text":"Zero-count buckets MAY also be included to extend an enclosing span (rather than creating a gap between spans) and reduce the number of `PositiveSpans` (or `NegativeSpans`).","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"1fd47361de78","level":"MUST","text":"OpenTelemetry Exponential Histograms with a delta aggregation temporality MAY be aggregated into a cumulative aggregation temporality and follow the logic above, or MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#exponential-histograms","sectionTitle":"Exponential Histograms","status":"Mixed","source":"spec"},{"id":"9feb9d423330","level":"MUST","text":"A Prometheus Gauge MUST be converted to an OTLP Gauge.","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"572cf330a023","level":"MUST","text":"An OpenTelemetry Gauge MUST be converted following a hint present in [metric.metadata][metricMetadata]:","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges-1","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"861f8766d6ff","level":"MUST","text":"If the `prometheus.type` key is absent, or its value is equal to `gauge`, the datapoint MUST be transformed to a Prometheus Gauge.","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges-1","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"29573a1b0166","level":"MUST","text":"If the `prometheus.type` key has value equal to `unkown`, the datapoint MUST be transformed to a Prometheus Unknown.","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges-1","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"aa05f8240f7b","level":"SHOULD","text":"If the `prometheus.type` key has value equal to `info`, the datapoint SHOULD be transformed to a Prometheus Info.","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges-1","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"e7379c87117e","level":"SHOULD","text":"If the `prometheus.type` key has value equal to `stateset`, the datapoint SHOULD be transformed to a Prometheus Stateset.","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges-1","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"6440abb9175f","level":"SHOULD","text":"Exemplars on OpenTelemetry Gauges SHOULD be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#gauges-1","sectionTitle":"Gauges","status":"Mixed","source":"spec"},{"id":"01fc410c2a62","level":"MUST","text":"A Prometheus Histogram MUST be converted to an OTLP Histogram.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"7a57154a13b8","level":"MUST","text":"In the text format, Prometheus histograms buckets, count and sum are sent as separate samples and they MUST be merged together when forming an OTLP Histogram.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"4884299c134c","level":"MUST","text":"If `_count` is not present, the metric MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"4c8db1d16e9a","level":"MUST","text":"If `_sum` is not present, the histogram's sum MUST be unset.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"4fcf34139fc4","level":"MUST","text":"Exemplars on the Prometheus Histogram Sample MUST be converted to OpenTelemetry Exemplars on the OpenTelemetry Histogram data point following the rules in Exemplars.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"d60c2bd4a898","level":"MUST","text":"An OpenTelemetry Histogram with a cumulative aggregation temporality MUST be converted to a Prometheus Histogram by default.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-1","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"0d2cf7034b65","level":"MUST","text":"OpenTelemetry Histograms with Delta aggregation temporality MAY be aggregated into a Cumulative aggregation temporality and follow the logic below, or MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-1","sectionTitle":"Histograms","status":"Mixed","source":"spec"},{"id":"4035f25b6b30","level":"MUST","text":"When converting to a Prometheus Histogram, an OpenTelemetry Histogram MUST be converted following the rules below:","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-histograms","sectionTitle":"Histograms as Prometheus Histograms","status":"Mixed","source":"spec"},{"id":"e0634ad582d9","level":"SHOULD","text":"If set, `StartTimeUnixNano` SHOULD be transformed into Prometheus `StartTime`, following the appropriate format used by each Prometheus protocol.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-histograms","sectionTitle":"Histograms as Prometheus Histograms","status":"Mixed","source":"spec"},{"id":"650f2f6358c0","level":"SHOULD","text":"If the Prometheus protocol only supports a single exemplar per-bucket, the latest exemplar that falls into each bucket SHOULD be converted.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-histograms","sectionTitle":"Histograms as Prometheus Histograms","status":"Mixed","source":"spec"},{"id":"a149d2d8e31a","level":"MUST","text":"When converting to a Prometheus NHCB, only a single NHCB metric MUST be created:","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"0b894f401e0b","level":"MUST","text":"The flavor of the NHCB MUST be integer counter.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"6c0196199b4e","level":"MUST","text":"The `ResetHint` in the NHCB MUST be set to `UNKNOWN`.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"268f28ea91f4","level":"MUST","text":"The `Schema` in the NHCB MUST be set to -53.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"10b1191aaaa2","level":"SHOULD","text":"If set, `StartTimeUnixNano` SHOULD be transformed into Prometheus `StartTime`, following the appropriate format used by each Prometheus protocol.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"2cb2b4ba1e29","level":"MUST NOT","text":"The implicit `+Inf` upper bound MUST NOT be written into `CustomValues`; it is represented by the overflow bucket at index `len(CustomValues)`.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"c666214080f0","level":"MUST","text":"All fields of the NHCB that are not explicitly referenced here MUST be set to their zero value, such as zero threshold, zero count, negative spans, negative deltas, etc.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"03ee504c3546","level":"MUST","text":"If the `NoRecordedValue` flag is set to `true`, the NHCB MUST be marked as stale:","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"f40588d75612","level":"MUST","text":"The Native Histogram `Sum` MUST be set to the Stale NaN value.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"c400e5825bd3","level":"MUST","text":"The Native Histogram `Count` MUST be set to zero.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"c8ae4d6b9069","level":"MUST","text":"`PositiveSpans` and `PositiveDeltas` MUST be left empty.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"e710db48d905","level":"MUST","text":"Non-zero bucket counts MUST be converted into `PositiveDeltas`.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"514a4c8b15ae","level":"MAY","text":"Zero-count buckets MAY also be included in `PositiveDeltas` to extend an enclosing span (rather than creating a gap between spans) and reduce the number of `PositiveSpans`.","section":"specification/compatibility/prometheus_and_openmetrics.md#histograms-as-prometheus-nhcb","sectionTitle":"Histograms as Prometheus NHCB","status":"Mixed","source":"spec"},{"id":"774fb9e1e656","level":"MUST","text":"A Prometheus Info metric MUST be converted to an OTLP Non-Monotonic Sum unless it is the `target` info metric, which is used to populate resource attributes.","section":"specification/compatibility/prometheus_and_openmetrics.md#info","sectionTitle":"Info","status":"Mixed","source":"spec"},{"id":"ef34784ae01b","level":"MUST","text":"Labels with `otelscope` prefix MUST be dropped from all metric points and used as the Instrumentation Scope name (`otelscopename`), version (`otelscopeversion`), schema URL (`otelscopeschemaurl`), attributes (`otelscope_[attribute]`).","section":"specification/compatibility/prometheus_and_openmetrics.md#instrumentation-scope","sectionTitle":"Instrumentation Scope","status":"Mixed","source":"spec"},{"id":"7bd8029341f9","level":"MUST","text":"Metrics which do not have any label with `otelscope` prefix MUST be assigned an instrumentation scope identifying the entity performing the translation from Prometheus to OpenTelemetry (e.g. the collector's Prometheus receiver).","section":"specification/compatibility/prometheus_and_openmetrics.md#instrumentation-scope","sectionTitle":"Instrumentation Scope","status":"Mixed","source":"spec"},{"id":"58767fdc992b","level":"MUST","text":"Prometheus exporters MUST by default add the scope name as the `otelscopename` label, the scope version as the `otelscopeversion` label, the scope schema URL as the `otelscopeschemaurl` label, the scope attributes as labels with `otelscope` prefix and following the rules described in the `Metric Attributes` section below, on all metric points, based on the scope the original data point was nested in.","section":"specification/compatibility/prometheus_and_openmetrics.md#instrumentation-scope-1","sectionTitle":"Instrumentation Scope","status":"Mixed","source":"spec"},{"id":"979bb3b83f97","level":"MUST","text":"Scope attributes that, after adding the `otelscope` prefix and applying the label-name conversion described in `Metric Attributes`, would conflict with `otelscopename`, `otelscopeversion`, or `otelscopeschemaurl` MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#instrumentation-scope-1","sectionTitle":"Instrumentation Scope","status":"Mixed","source":"spec"},{"id":"b0aedb1fdd2d","level":"MUST","text":"OpenTelemetry Metric Attributes MUST be converted to Prometheus labels.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-attributes","sectionTitle":"Metric Attributes","status":"Mixed","source":"spec"},{"id":"d3c3ade1de92","level":"MUST","text":"String Attribute values are converted directly to Metric Attributes, and non-string Attribute values MUST be converted to string attributes following the attribute specification.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-attributes","sectionTitle":"Metric Attributes","status":"Mixed","source":"spec"},{"id":"32143832ae35","level":"SHOULD","text":"Discouraged characters SHOULD be replaced with the `` character.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-attributes","sectionTitle":"Metric Attributes","status":"Mixed","source":"spec"},{"id":"f9abe5203ac9","level":"SHOULD","text":"Multiple consecutive `` characters SHOULD be replaced with a single `` character.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-attributes","sectionTitle":"Metric Attributes","status":"Mixed","source":"spec"},{"id":"abccfd60bdb9","level":"MUST","text":"In such cases, the values MUST be concatenated together, separated by `;`, and ordered by the lexicographical order of the original keys.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-attributes","sectionTitle":"Metric Attributes","status":"Mixed","source":"spec"},{"id":"e79c4ba0f59d","level":"MUST","text":"The Prometheus Metric Name MUST be added as the Name of the OTLP metric.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"e32456adbb6f","level":"SHOULD NOT","text":"The name SHOULD NOT be altered.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"475df1679b99","level":"MUST","text":"Prometheus UNIT metadata, if present, MUST be converted to the unit of the OTLP metric.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"189577f747d8","level":"MUST","text":"The unit MUST be translated from words to the UCUM abbreviation if it is in the following set of commonly-used units:","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"2b84cb14513e","level":"MUST","text":"Prometheus HELP metadata, if present, MUST be added as the description of the OTLP metric.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"6358346c31d6","level":"MUST","text":"Prometheus TYPE metadata, if present, MUST be used to determine the OTLP data type, and dictates type-specific conversion rules listed below.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"1f2a9d837c5f","level":"MUST","text":"The TYPE metadata MUST also be added to the OTLP [metric.metadata][metricMetadata] under the `prometheus.type` key (e.g. `prometheus.type=\"unknown\"`).","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"431554475263","level":"MUST NOT","text":"Prometheus Pull exporters for OpenTelemetry metric data MUST NOT allow duplicate UNIT, HELP, or TYPE comments for the same metric name to be returned in a single scrape of the Prometheus endpoint.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"a54e9a0dd2e9","level":"SHOULD NOT","text":"Exporters MUST drop entire metrics to prevent conflicting TYPE comments, but SHOULD NOT drop metric points as a result of conflicting UNIT or HELP comments.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"aed001f0c2dc","level":"SHOULD","text":"Instead, all but one of the conflicting UNIT and HELP comments (but not metric points) SHOULD be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"648fed04e969","level":"SHOULD","text":"If dropping a comment or metric points, the exporter SHOULD warn the user through error logging.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"eb9897d7c6ed","level":"MUST","text":"The Name of an OTLP metric MUST be added as the Prometheus Metric Name.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"f27395dce660","level":"SHOULD","text":"Discouraged characters in the metric name SHOULD be replaced with the `` character by default, aiming for compatibility with Prometheus conventions.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"a6bf83948c4c","level":"SHOULD","text":"Multiple consecutive `` characters SHOULD be replaced with a single `_` character.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"7b3cb282595b","level":"MUST","text":"The Unit of an OTLP metric point MUST be converted from the UCUM unit to the equivalent unit word in Prometheus if it is included in the table in Metric Metadata above.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"a2a5d5ae17b5","level":"MUST","text":"Portions of the Unit within brackets (e.g. {packet}) MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"23750a8c140f","level":"MUST","text":"Units defined as rates over time (e.g. \"m/s\") MUST be converted to words (e.g. \"meterspersecond\").","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"4e4de287d429","level":"SHOULD","text":"The resulting unit SHOULD be added to the metric as UNIT metadata.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"77f6792b2739","level":"SHOULD","text":"A suffix to the metric name SHOULD be added unless the metric name already ends with the unit (before type-specific suffixes).","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"1f0215addc9f","level":"MUST","text":"The description of an OTLP metrics point MUST be added as HELP metadata.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"80ef07d04015","level":"MUST","text":"The data point type of an OTLP metric MUST be added as TYPE metadata.","section":"specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1","sectionTitle":"Metric Metadata","status":"Mixed","source":"spec"},{"id":"59c3a9e5a35c","level":"MUST","text":"A Prometheus Native Histogram with standard (exponential) schema (i.e. schemas -4 to 8) and which are of the integer and counter flavor MUST be converted to an OTLP Exponential Histogram as follows:","section":"specification/compatibility/prometheus_and_openmetrics.md#native-histograms","sectionTitle":"Native Histograms","status":"Mixed","source":"spec"},{"id":"134719384c69","level":"MUST","text":"Overflow buckets MUST be dropped and not counted in the overall `Count`.","section":"specification/compatibility/prometheus_and_openmetrics.md#native-histograms","sectionTitle":"Native Histograms","status":"Mixed","source":"spec"},{"id":"3f697b855602","level":"MUST","text":"A Native histogram with custom buckets (NHCB) schema (i.e. schema -53) and which are of the integer and counter flavor MUST be converted to an OTLP Histogram as follows:","section":"specification/compatibility/prometheus_and_openmetrics.md#native-histograms","sectionTitle":"Native Histograms","status":"Mixed","source":"spec"},{"id":"4378f1f786e1","level":"MUST","text":"Native histograms of the float or gauge flavors MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#native-histograms","sectionTitle":"Native Histograms","status":"Mixed","source":"spec"},{"id":"99a83b8f8004","level":"MUST","text":"Native Histograms with `Schema` outside of the range [-4, 8] and not equal to -53 MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#native-histograms","sectionTitle":"Native Histograms","status":"Mixed","source":"spec"},{"id":"675201cf6b3f","level":"MUST","text":"Exemplars on the Prometheus Native Histogram Sample MUST be converted to OpenTelemetry Exemplars on the OpenTelemetry Exponential Histogram data point following the rules in Exemplars.","section":"specification/compatibility/prometheus_and_openmetrics.md#native-histograms","sectionTitle":"Native Histograms","status":"Mixed","source":"spec"},{"id":"3a9e84fcc5e5","level":"MUST","text":"When scraping a Prometheus endpoint, resource attributes MUST be added to the scraped metrics to distinguish them from metrics from other Prometheus endpoints.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"1f7c1ecaa53e","level":"MUST NOT","text":"The following attributes MUST be associated with scraped metrics as resource attributes, and MUST NOT be added as metric attributes:","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"da18d20b6174","level":"MUST NOT","text":"The following attributes SHOULD be associated with scraped metrics as resource attributes, and MUST NOT be added as metric attributes:","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"52e6f85842cb","level":"MUST","text":"If present, the `target` info metric MUST be dropped from the batch of metrics, and all labels from the `target` info metric MUST be converted to resource attributes attached to all other metrics which are part of the scrape.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"432d4abae463","level":"MUST NOT","text":"By default, label keys and values MUST NOT be altered (such as replacing `_` with `.` characters in keys).","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"57c5ff4da7ca","level":"SHOULD","text":"In Prometheus exporters, an OpenTelemetry Resource SHOULD be converted to a `target` info metric if the resource is not empty.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"66d0b2f627a5","level":"MUST","text":"The Resource attributes MAY be copied to labels of exported metric families if required by the exporter configuration, or MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"58420c6fd758","level":"MUST NOT","text":"The `target` info metric MUST be an info-typed metric whose labels MUST include the resource attributes, and MUST NOT include any other labels.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"4bd49a938368","level":"MUST","text":"In the collector Prometheus exporters, the `service.name` and `service.namespace` attributes MUST be combined as `<service.namespace>/<service.name>`, or `<service.name>` if namespace is empty, to form the `job` metric label.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"8eb44e247688","level":"MUST","text":"The `service.instance.id` attribute, if present, MUST be converted to the `instance` label; otherwise, `instance` should be added with an empty value.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"8d916e36ea9f","level":"MUST","text":"Other resource attributes SHOULD be converted to a target info metric, or MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"708871dbf4a0","level":"MUST NOT","text":"The `target` metric is an info-typed metric whose labels MUST include the resource attributes, and MUST NOT include any other labels other than `job` and `instance`.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"a6c9ec137a8f","level":"MUST","text":"There MUST be at most one `target` info metric exported for each unique combination of `job` and `instance`.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"5bc4443549de","level":"MUST","text":"If info-typed metric families are not yet supported by the language Prometheus client library, a gauge-typed metric family named `target_info` with a constant value of 1 MUST be used instead.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"c9ef84d18ad0","level":"MUST","text":"To convert OTLP resource attributes to Prometheus labels, string Attribute values are converted directly to labels, and non-string Attribute values MUST be converted to string attributes following the attribute specification.","section":"specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1","sectionTitle":"Resource Attributes","status":"Mixed","source":"spec"},{"id":"cd5b697233c4","level":"MUST","text":"A Prometheus StateSet metric MUST be converted to an OTLP Non-Monotonic Sum.","section":"specification/compatibility/prometheus_and_openmetrics.md#stateset","sectionTitle":"StateSet","status":"Mixed","source":"spec"},{"id":"d6f8d23db2ca","level":"MUST","text":"Prometheus Summary MUST be converted to an OTLP Summary.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"60ca34b376a8","level":"MUST","text":"In text formats where Prometheus Summaries are represented by multiple samples, samples with same metric family name MUST be merged together into a single OTLP Summary.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"4ea1c34da774","level":"MUST","text":"If `_count` is not present, the metric MUST be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"76dfa7cb0f2c","level":"MUST","text":"If `_sum` is not present, the summary's sum MUST be set to zero.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"4f8c332d54ec","level":"MUST","text":"An OpenTelemetry Summary MUST be converted to a Prometheus Summary as follows:","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries-1","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"32466da52e72","level":"MUST","text":"The `quantile` label value MUST be the stringified floating point value of each quantile (between 0.0 and 1.0), starting from lowest to highest, and all being non-negative.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries-1","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"d751b8ab0849","level":"SHOULD NOT","text":"Explicit timestamps SHOULD NOT be used for pull protocols, such as the Prometheus text exposition format, where Prometheus assigns the scrape timestamp.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries-1","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"ec6694ab849f","level":"SHOULD","text":"Exemplars on OpenTelemetry Summaries SHOULD be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#summaries-1","sectionTitle":"Summaries","status":"Mixed","source":"spec"},{"id":"873de294b02f","level":"MUST","text":"An OpenTelemetry Sum MUST be converted following the rules below:","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"9a3ac524a108","level":"MUST","text":"If the aggregation temporality is cumulative and the sum is monotonic, it MUST be converted to a Prometheus Counter.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"bc1525da9bad","level":"MAY","text":"If the aggregation temporality is delta and the sum is monotonic, it MAY be converted to a cumulative temporality and become a Prometheus Counter.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"5c8995d053be","level":"MUST","text":"If the metric name for monotonic Sum metric points does not end in a suffix of `total` a suffix of `total` SHOULD be added by default, otherwise the name MUST remain unchanged.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"fe94e58ed3cd","level":"SHOULD","text":"Monotonic Sum metric points with `StartTimeUnixNano` SHOULD transform `StartTimeUnixNano` into Prometheus `StartTime`, following the appropriate format used by each Prometheus protocol.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"06155afd1ee5","level":"MUST","text":"If Sum is converted to a Prometheus Counter, then `Exemplars` MUST be converted as described in the Exemplar Conversion section.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"82211c187dc2","level":"SHOULD","text":"Otherwise, `Exemplars` SHOULD be dropped.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"c11fb9a45775","level":"SHOULD","text":"If the Prometheus protocol only supports a single exemplar on the Counter sample, the latest exemplar SHOULD be converted.","section":"specification/compatibility/prometheus_and_openmetrics.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"2437bf40ab24","level":"MUST","text":"If present, the Prometheus Metric Sample's Start timestamp (also referred to as the Created timestamp) MUST be converted to the Start timestamp of the OTLP data point.","section":"specification/compatibility/prometheus_and_openmetrics.md#timestamps","sectionTitle":"Timestamps","status":"Mixed","source":"spec"},{"id":"a4a98199e4ab","level":"SHOULD","text":"If no start timestamp is present, the start time of the OTLP data point SHOULD be left unset.","section":"specification/compatibility/prometheus_and_openmetrics.md#timestamps","sectionTitle":"Timestamps","status":"Mixed","source":"spec"},{"id":"f3b6e37b097c","level":"MUST","text":"If present, the Prometheus Metric Sample's Timestamp MUST be converted to the Timestamp of the OTLP data point.","section":"specification/compatibility/prometheus_and_openmetrics.md#timestamps","sectionTitle":"Timestamps","status":"Mixed","source":"spec"},{"id":"c970ac00d1ee","level":"MUST","text":"For metrics scraped from a Prometheus endpoint without an explicit timestamp, the timestamp of the OTLP data point MUST be set to the time of the scrape.","section":"specification/compatibility/prometheus_and_openmetrics.md#timestamps","sectionTitle":"Timestamps","status":"Mixed","source":"spec"},{"id":"b9d8e78f6192","level":"MUST","text":"A Prometheus Unknown MUST be converted to an OTLP Gauge.","section":"specification/compatibility/prometheus_and_openmetrics.md#unknown-typed","sectionTitle":"Unknown-typed","status":"Mixed","source":"spec"},{"id":"02c21766a2b9","level":"MUST","text":"`ConfigProperties` MUST provide accessors for reading all properties from the mapping node it represents, including:","section":"specification/configuration/api.md#configproperties","sectionTitle":"ConfigProperties","status":"Mixed","source":"spec"},{"id":"5cf8b93d0f2a","level":"SHOULD","text":"mappings, which SHOULD be represented as `ConfigProperties`","section":"specification/configuration/api.md#configproperties","sectionTitle":"ConfigProperties","status":"Mixed","source":"spec"},{"id":"1e3520a7bdae","level":"SHOULD","text":"sequences of mappings, which SHOULD be represented as `ConfigProperties`","section":"specification/configuration/api.md#configproperties","sectionTitle":"ConfigProperties","status":"Mixed","source":"spec"},{"id":"3594aef5c17d","level":"SHOULD","text":"`ConfigProperties` SHOULD provide access to properties in a type safe manner, based on what is idiomatic in the language.","section":"specification/configuration/api.md#configproperties","sectionTitle":"ConfigProperties","status":"Mixed","source":"spec"},{"id":"bc8812771811","level":"SHOULD","text":"`ConfigProperties` SHOULD allow a caller to determine if a property is present with a null value, versus not set.","section":"specification/configuration/api.md#configproperties","sectionTitle":"ConfigProperties","status":"Mixed","source":"spec"},{"id":"5ec0c3d034f5","level":"SHOULD","text":"Thus, the API SHOULD provide a way to access a global default `ConfigProvider`, and set/register it.","section":"specification/configuration/api.md#configprovider","sectionTitle":"ConfigProvider","status":"Mixed","source":"spec"},{"id":"8c1f9f1d6a52","level":"MUST","text":"The `ConfigProvider` MUST provide the following functions:","section":"specification/configuration/api.md#configprovider-operations","sectionTitle":"ConfigProvider operations","status":"Mixed","source":"spec"},{"id":"9a65608e8b79","level":"SHOULD","text":"If the `.instrumentation` node is not set, get instrumentation config SHOULD return an empty `ConfigProperties` (as if `.instrumentation: {}` was set).","section":"specification/configuration/api.md#get-instrumentation-config","sectionTitle":"Get instrumentation config","status":"Mixed","source":"spec"},{"id":"a7977755ca55","level":"MUST","text":"Any value that represents a duration MUST be an integer representing a number of milliseconds.","section":"specification/configuration/common.md#duration","sectionTitle":"Duration","status":"Stable","source":"spec"},{"id":"9e0f060b138b","level":"MUST","text":"The value is non-negative - if a negative value is provided, the implementation MUST generate a warning, gracefully ignore the setting and use the default value if it is defined.","section":"specification/configuration/common.md#duration","sectionTitle":"Duration","status":"Stable","source":"spec"},{"id":"1d243c5aa6b1","level":"MAY","text":"For configuration sources which accept a known value out of a set, i.e., an enum value, implementations MAY support additional values not listed here.","section":"specification/configuration/common.md#enum","sectionTitle":"Enum","status":"Stable","source":"spec"},{"id":"b9fdbcc61a70","level":"SHOULD","text":"When reporting configuration errors, implementations SHOULD display the original user-provided value to aid debugging.","section":"specification/configuration/common.md#enum","sectionTitle":"Enum","status":"Stable","source":"spec"},{"id":"48176047ed61","level":"MUST","text":"If a null object (empty, no-op) value is acceptable, then the enum value representing it MUST be `\"none\"`.","section":"specification/configuration/common.md#enum","sectionTitle":"Enum","status":"Stable","source":"spec"},{"id":"542b8b3ec00b","level":"SHOULD","text":"If an implementation chooses to support an integer-valued configuration source, it SHOULD support non-negative values between 0 and 2³¹ − 1 (inclusive).","section":"specification/configuration/common.md#integer","sectionTitle":"Integer","status":"Stable","source":"spec"},{"id":"d469ac3cc12a","level":"MAY","text":"Individual SDKs MAY choose to support a larger range of values.","section":"specification/configuration/common.md#integer","sectionTitle":"Integer","status":"Stable","source":"spec"},{"id":"73e9fa4b1824","level":"MUST","text":"> The following paragraph was added after stabilization and the requirements are > thus qualified as \"SHOULD\" to allow implementations to avoid breaking changes. > For new > implementations, these should be treated as MUST requirements.","section":"specification/configuration/common.md#numeric","sectionTitle":"Numeric","status":"Stable","source":"spec"},{"id":"6b6a17a9e334","level":"SHOULD","text":"For sources accepting a numeric value, if the user provides a value which is outside the valid range for the configuration item, the implementation SHOULD generate a warning and gracefully ignore the setting, i.e., treat them as not set.","section":"specification/configuration/common.md#numeric","sectionTitle":"Numeric","status":"Stable","source":"spec"},{"id":"7212f39bff73","level":"SHOULD NOT","text":"In particular, implementations SHOULD NOT assign a custom interpretation e.g. to negative values if a negative value does not naturally apply to a configuration and does not have an explicitly specified meaning, but treat it like any other invalid value.","section":"specification/configuration/common.md#numeric","sectionTitle":"Numeric","status":"Stable","source":"spec"},{"id":"20647ccb4fa1","level":"MAY","text":"Implementations MAY choose to allow configuration via any configuration source in this specification, but are not required to.","section":"specification/configuration/common.md#opentelemetry-common-configuration-specification","sectionTitle":"OpenTelemetry Common Configuration Specification","status":"Stable","source":"spec"},{"id":"e9cae82323e6","level":"SHOULD","text":"If they do, they SHOULD follow the guidance listed in this document.","section":"specification/configuration/common.md#opentelemetry-common-configuration-specification","sectionTitle":"OpenTelemetry Common Configuration Specification","status":"Stable","source":"spec"},{"id":"caf2fb8fa679","level":"MUST","text":"Any value that represents a timeout MUST be an integer representing a number of milliseconds.","section":"specification/configuration/common.md#timeout","sectionTitle":"Timeout","status":"Stable","source":"spec"},{"id":"8cd8e84ce775","level":"MUST","text":"The value is non-negative - if a negative value is provided, the implementation MUST generate a warning, gracefully ignore the setting and use the default value if it is defined.","section":"specification/configuration/common.md#timeout","sectionTitle":"Timeout","status":"Stable","source":"spec"},{"id":"d8395265e204","level":"SHOULD","text":"Implementations SHOULD interpret timeout zero values (i.e. `0` indicating 0 milliseconds) as no limit (i.e. infinite).","section":"specification/configuration/common.md#timeout","sectionTitle":"Timeout","status":"Stable","source":"spec"},{"id":"2eb51e586b30","level":"MAY","text":"In practice, implementations MAY treat no limit as \"a very long time\" and substitute a very large duration ( e.g. the maximum milliseconds representable by a 32-bit integer).","section":"specification/configuration/common.md#timeout","sectionTitle":"Timeout","status":"Stable","source":"spec"},{"id":"7b1efb7836de","level":"MUST","text":"When `PREFIX` is absent or `env`, `GENERIC-SUBSTITUTION` MUST conform to `ENV-SUBSTITUTION`:","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"4327b52e26a5","level":"MAY","text":"Language implementations MAY support additional prefixes beyond `env:` to access language-specific configuration sources.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"fe5a4676bf08","level":"SHOULD","text":"Language implementations SHOULD document any additional prefixes they support.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"bc507affab93","level":"MUST","text":"Environment variable substitution MUST only apply to scalar values.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"54d9f94fc9e9","level":"MUST","text":"If a referenced environment variable is not defined and does not have a `DEFAULT-VALUE`, it MUST be replaced with an empty value.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"b51412b4740a","level":"MUST NOT","text":"The resolved `$` from an escape sequence MUST NOT be considered when matching input against the environment variable substitution regular expression.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"03aaf2d42175","level":"MUST","text":"Node types MUST be interpreted after environment variable substitution takes place.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"d630794f740c","level":"MUST NOT","text":"It MUST NOT be possible to inject YAML structures by environment variables.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"1106a591ad47","level":"MUST NOT","text":"It MUST NOT be possible to inject environment variable by environment variables.","section":"specification/configuration/data-model.md#environment-variable-substitution","sectionTitle":"Environment variable substitution","status":"Stable","source":"spec"},{"id":"2e876acab4f9","level":"SHOULD","text":"Configuration files SHOULD use one the following serialization formats:","section":"specification/configuration/data-model.md#file-based-configuration-model","sectionTitle":"File-based configuration model","status":"Stable","source":"spec"},{"id":"5c043fb814fe","level":"SHOULD","text":"YAML configuration files SHOULD follow YAML spec revision >= 1.2.","section":"specification/configuration/data-model.md#yaml-file-format","sectionTitle":"YAML file format","status":"Stable","source":"spec"},{"id":"f050f0288cc0","level":"SHOULD","text":"YAML configuration files SHOULD be parsed using v1.2 YAML core schema.","section":"specification/configuration/data-model.md#yaml-file-format","sectionTitle":"YAML file format","status":"Stable","source":"spec"},{"id":"df07007106ca","level":"MUST","text":"YAML configuration files MUST use file extensions `.yaml` or `.yml`.","section":"specification/configuration/data-model.md#yaml-file-format","sectionTitle":"YAML file format","status":"Stable","source":"spec"},{"id":"2b83d72eebc3","level":"SHOULD","text":"Additional configuration mechanisms SHOULD be provided in whatever language/format/style is idiomatic for the language of the SDK.","section":"specification/configuration/README.md#other-mechanisms","sectionTitle":"Other Mechanisms","status":"Unspecified","source":"spec"},{"id":"a5aa7cb4653e","level":"MUST","text":"The SDK MUST provide a programmatic interface for all configuration.","section":"specification/configuration/README.md#programmatic","sectionTitle":"Programmatic","status":"Unspecified","source":"spec"},{"id":"db83c109212b","level":"SHOULD","text":"This interface SHOULD be written in the language of the SDK itself.","section":"specification/configuration/README.md#programmatic","sectionTitle":"Programmatic","status":"Unspecified","source":"spec"},{"id":"c1d018eada58","level":"SHOULD","text":"All other configuration mechanisms SHOULD be built on top of this interface.","section":"specification/configuration/README.md#programmatic","sectionTitle":"Programmatic","status":"Unspecified","source":"spec"},{"id":"6f69a0ebb554","level":"SHOULD","text":"Implementations SHOULD only offer environment variables for the types of attributes, for which that SDK implements truncation mechanism.","section":"specification/configuration/sdk-environment-variables.md#attribute-limits","sectionTitle":"Attribute Limits","status":"Stable","source":"spec"},{"id":"cbd2d0c8d7ec","level":"MUST","text":"Any value that represents a Boolean MUST be set to true only by the case-insensitive string `\"true\"`, meaning `\"True\"` or `\"TRUE\"` are also accepted, as true.","section":"specification/configuration/sdk-environment-variables.md#boolean","sectionTitle":"Boolean","status":"Stable","source":"spec"},{"id":"948ff925bbad","level":"MUST NOT","text":"An implementation MUST NOT extend this definition and define additional values that are interpreted as true.","section":"specification/configuration/sdk-environment-variables.md#boolean","sectionTitle":"Boolean","status":"Stable","source":"spec"},{"id":"0ae5047ffd5d","level":"MUST","text":"Any value not explicitly defined here as a true value, including unset and empty values, MUST be interpreted as false.","section":"specification/configuration/sdk-environment-variables.md#boolean","sectionTitle":"Boolean","status":"Stable","source":"spec"},{"id":"f678608a8011","level":"SHOULD","text":"If any value other than a true value, case-insensitive string `\"false\"`, empty, or unset is used, a warning SHOULD be logged to inform users about the fallback to false being applied.","section":"specification/configuration/sdk-environment-variables.md#boolean","sectionTitle":"Boolean","status":"Stable","source":"spec"},{"id":"1426d1b6837f","level":"SHOULD","text":"All Boolean environment variables SHOULD be named and defined such that false is the expected safe default behavior.","section":"specification/configuration/sdk-environment-variables.md#boolean","sectionTitle":"Boolean","status":"Stable","source":"spec"},{"id":"75bbaa4d05fd","level":"MUST NOT","text":"Renaming or changing the default value MUST NOT happen without a major version upgrade.","section":"specification/configuration/sdk-environment-variables.md#boolean","sectionTitle":"Boolean","status":"Stable","source":"spec"},{"id":"2ed932f4c68e","level":"MUST","text":"When `OTELCONFIGFILE` is set, all other environment variables besides those referenced in the configuration file for environment variable substitution MUST be ignored.","section":"specification/configuration/sdk-environment-variables.md#declarative-configuration","sectionTitle":"Declarative configuration","status":"Stable","source":"spec"},{"id":"7610f6ae77e2","level":"MAY","text":"Implementations MAY provide a mechanism to customize the configuration model parsed from `OTELCONFIGFILE`.","section":"specification/configuration/sdk-environment-variables.md#declarative-configuration","sectionTitle":"Declarative configuration","status":"Stable","source":"spec"},{"id":"5db17d155b23","level":"SHOULD","text":"Enum values SHOULD be interpreted in a case-insensitive manner.","section":"specification/configuration/sdk-environment-variables.md#enum","sectionTitle":"Enum","status":"Stable","source":"spec"},{"id":"19461bf3db26","level":"MUST","text":"For sources accepting an enum value, if the user provides a value the implementation does not recognize, the implementation MUST generate a warning and gracefully ignore the setting.","section":"specification/configuration/sdk-environment-variables.md#enum","sectionTitle":"Enum","status":"Stable","source":"spec"},{"id":"c1167bfb6ddc","level":"MAY","text":"The implementation MAY accept a comma-separated list to enable setting multiple exporters.","section":"specification/configuration/sdk-environment-variables.md#exporter-selection","sectionTitle":"Exporter Selection","status":"Stable","source":"spec"},{"id":"1a0639a687f6","level":"SHOULD NOT","text":"It SHOULD NOT be supported by new implementations.","section":"specification/configuration/sdk-environment-variables.md#exporter-selection","sectionTitle":"Exporter Selection","status":"Stable","source":"spec"},{"id":"9af91e7dd56b","level":"MUST","text":"This setting has no effect on propagators configured through the OTELPROPAGATORS variable. | | OTELENTITIES | Entity information to be associated with the resource | | [String][] | See Entities SDK for more details. | | OTELRESOURCEATTRIBUTES | Key-value pairs to be used as resource attributes | See Resource semantic conventions for details. | [String][] | See Resource SDK for more details. | | OTELSERVICENAME | Sets the value of the `service.name` resource attribute | | [String][] | If `service.name` is also provided in `OTELRESOURCEATTRIBUTES`, then `OTELSERVICENAME` takes precedence. | | O...","section":"specification/configuration/sdk-environment-variables.md#general-sdk-configuration","sectionTitle":"General SDK Configuration","status":"Stable","source":"spec"},{"id":"fc5e7c9f8574","level":"MUST","text":"Invalid or unrecognized input MUST be logged and MUST be otherwise ignored, i.e. the implementation MUST behave as if OTELTRACESSAMPLER_ARG is not set. |","section":"specification/configuration/sdk-environment-variables.md#general-sdk-configuration","sectionTitle":"General SDK Configuration","status":"Stable","source":"spec"},{"id":"f1b58d5bf28e","level":"MAY","text":"Environment variables MAY be handled (implemented) directly by a component, in the SDK, or in a separate component (e.g. environment-based autoconfiguration component).","section":"specification/configuration/sdk-environment-variables.md#implementation-guidelines","sectionTitle":"Implementation guidelines","status":"Stable","source":"spec"},{"id":"2234eef942a5","level":"MUST","text":"The environment-based configuration MUST have a direct code configuration equivalent.","section":"specification/configuration/sdk-environment-variables.md#implementation-guidelines","sectionTitle":"Implementation guidelines","status":"Stable","source":"spec"},{"id":"463b5d595a03","level":"MUST","text":"> The following paragraph was added after stabilization and the requirements are > thus qualified as \"SHOULD\" to allow implementations to avoid breaking changes. > For new > implementations, these should be treated as MUST requirements.","section":"specification/configuration/sdk-environment-variables.md#numeric","sectionTitle":"Numeric","status":"Stable","source":"spec"},{"id":"67bcc5806b90","level":"SHOULD","text":"For variables accepting a numeric value, if the user provides a value the implementation cannot parse, the implementation SHOULD generate a warning and gracefully ignore the setting, i.e., treat them as not set.","section":"specification/configuration/sdk-environment-variables.md#numeric","sectionTitle":"Numeric","status":"Stable","source":"spec"},{"id":"41ad56be9e5e","level":"MAY","text":"Implementations MAY choose to allow configuration via the environment variables in this specification, but are not required to.","section":"specification/configuration/sdk-environment-variables.md#opentelemetry-environment-variable-specification","sectionTitle":"OpenTelemetry Environment Variable Specification","status":"Stable","source":"spec"},{"id":"a45fe92c3a2f","level":"SHOULD","text":"If they do, they SHOULD use the names and value parsing behavior specified in this document.","section":"specification/configuration/sdk-environment-variables.md#opentelemetry-environment-variable-specification","sectionTitle":"OpenTelemetry Environment Variable Specification","status":"Stable","source":"spec"},{"id":"dab8b6e91a6c","level":"SHOULD","text":"They SHOULD also follow the common configuration specification.","section":"specification/configuration/sdk-environment-variables.md#opentelemetry-environment-variable-specification","sectionTitle":"OpenTelemetry Environment Variable Specification","status":"Stable","source":"spec"},{"id":"cac5efb9964e","level":"MUST","text":"The SDK MUST interpret an empty value of an environment variable the same way as when the variable is unset.","section":"specification/configuration/sdk-environment-variables.md#parsing-empty-value","sectionTitle":"Parsing empty value","status":"Stable","source":"spec"},{"id":"7603cb1dc52e","level":"MUST","text":"The SDK implementation of `ConfigProvider` MUST be created using a `ConfigProperties` representing the `.instrumentation` mapping node of the configuration model.","section":"specification/configuration/sdk.md#configprovider","sectionTitle":"ConfigProvider","status":"Stable","source":"spec"},{"id":"733850574a29","level":"MAY","text":"The multiple responses MAY be returned using a tuple, or some other data structure encapsulating the components.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"718a6ef6dfa1","level":"MUST","text":"If a property is present and the value is null, Create MUST use the `nullBehavior`, or `defaultBehavior` if `nullBehavior` is not set.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"317cd8d0d1e3","level":"MUST","text":"If a property is required, and not present, Create MUST return an error.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"0c3bc1cd6060","level":"SHOULD","text":"Create SHOULD return an error if it encounters a value which is invalid according to the property `description`.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"314b912f2944","level":"MUST","text":"When encountering a reference to an SDK plugin component which is not built-in to the SDK, Create MUST resolve the component using Create Component of the `PluginComponentProvider` of the corresponding `type` and `name` used to register, including the configuration `properties` as an argument.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"53fbd8fbd6c8","level":"SHOULD","text":"If no `PluginComponentProvider` is registered with the `type` and `name`, Create SHOULD return an error.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"858a8f8c4cde","level":"SHOULD","text":"If Create Component returns an error, Create SHOULD propagate the error.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"7819f1ddb79d","level":"SHOULD","text":"This SHOULD return an error if it encounters an error in `configuration` (i.e. fail fast) in accordance with initialization error handling principles.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"475ccc94158f","level":"MAY","text":"Status: Development SDK implementations MAY provide options to allow programmatic customization of the components initialized by `Create`.","section":"specification/configuration/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"68a51f31f050","level":"MAY","text":"The plugin component MAY have properties which are optional or required, and have specific requirements around type or format.","section":"specification/configuration/sdk.md#create-component","sectionTitle":"Create Component","status":"Stable","source":"spec"},{"id":"c043c3c697e5","level":"SHOULD","text":"A `PluginComponentProvider` SHOULD document its configuration schema and include examples.","section":"specification/configuration/sdk.md#create-component","sectionTitle":"Create Component","status":"Stable","source":"spec"},{"id":"a2370bea0939","level":"SHOULD","text":"If this fails (e.g. a required property is not present, a type is mismatches, etc.), Create Component SHOULD return an error.","section":"specification/configuration/sdk.md#create-component","sectionTitle":"Create Component","status":"Stable","source":"spec"},{"id":"b56b91429475","level":"SHOULD","text":"SDKs SHOULD provide an in-memory representation of the configuration model.","section":"specification/configuration/sdk.md#in-memory-configuration-model","sectionTitle":"In-Memory configuration model","status":"Stable","source":"spec"},{"id":"cdc9281f7ef5","level":"SHOULD","text":"Whereas `ConfigProperties` is a schemaless representation of any mapping node, the in-memory configuration model SHOULD reflect the schema of the configuration model.","section":"specification/configuration/sdk.md#in-memory-configuration-model","sectionTitle":"In-Memory configuration model","status":"Stable","source":"spec"},{"id":"635b9096ed89","level":"RECOMMENDED","text":"If an SDK needs to expose a class or interface, the name `Configuration` is RECOMMENDED.","section":"specification/configuration/sdk.md#in-memory-configuration-model","sectionTitle":"In-Memory configuration model","status":"Stable","source":"spec"},{"id":"1c266d0265b4","level":"MAY","text":"This MAY be a file path, or language specific file data structure, or a stream of a file's content.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"23986082c2e7","level":"MAY","text":"Implementations MAY accept a `fileformat` parameter, or infer it from the `file` extension, or include file format specific overloads of `parse`, e.g. `parseYaml(file)`.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"aa10378afe55","level":"SHOULD","text":"If `parse` accepts `file_format`, the API SHOULD be structured so a user is obligated to provide it.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"0e0310a3c61c","level":"MUST","text":"Parse MUST perform environment variable substitution.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"82354c5e51a9","level":"MUST","text":"Parse MUST differentiate between properties that are missing and properties that are present but null.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"6ecdef19830e","level":"MUST","text":"The user MUST not be required to specify an empty object (i.e. `drop: {}`) in these cases.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"8cbd2c4678d1","level":"MUST","text":"When encountering a reference to a SDK extension component which is not built-in to the SDK, Parse MUST resolve corresponding configuration to a generic ConfigProperties representation as described in Create Component.","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"b671ee8f1fbe","level":"SHOULD","text":"Parse SHOULD return an error if:","section":"specification/configuration/sdk.md#parse","sectionTitle":"Parse","status":"Stable","source":"spec"},{"id":"7116ae1ed378","level":"MAY","text":"This MAY be done automatically or require manual intervention by the user based on what is possible and idiomatic in the language ecosystem.","section":"specification/configuration/sdk.md#plugincomponentprovider","sectionTitle":"PluginComponentProvider","status":"Stable","source":"spec"},{"id":"558f7c1305ee","level":"MUST","text":"The `PluginComponentProvider` MUST provide the following functions:","section":"specification/configuration/sdk.md#plugincomponentprovider-operations","sectionTitle":"PluginComponentProvider operations","status":"Stable","source":"spec"},{"id":"4816532f87a7","level":"MUST","text":"The SDK MUST provide a mechanism to register `PluginComponentProvider`.","section":"specification/configuration/sdk.md#register-plugincomponentprovider","sectionTitle":"Register PluginComponentProvider","status":"Stable","source":"spec"},{"id":"95c2336ee09d","level":"MAY","text":"The mechanism MAY be language-specific and automatic.","section":"specification/configuration/sdk.md#register-plugincomponentprovider","sectionTitle":"Register PluginComponentProvider","status":"Stable","source":"spec"},{"id":"eac2ae54a216","level":"MUST","text":"Register MUST return an error if it is called multiple times with the same `type` and `name` combination.","section":"specification/configuration/sdk.md#register-plugincomponentprovider","sectionTitle":"Register PluginComponentProvider","status":"Stable","source":"spec"},{"id":"93d6a1358cd9","level":"SHOULD","text":"SDKs SHOULD represent `type` in a manner that is idiomatic for their language.","section":"specification/configuration/sdk.md#register-plugincomponentprovider","sectionTitle":"Register PluginComponentProvider","status":"Stable","source":"spec"},{"id":"fa1c567916f6","level":"SHOULD","text":"The configuration data model SHOULD define specific types for built-in implementations of these plugin components.","section":"specification/configuration/sdk.md#sdk-extension-components","sectionTitle":"SDK extension components","status":"Stable","source":"spec"},{"id":"966dc28234d8","level":"SHOULD","text":"The schema SHOULD support the ability to specify custom implementations of plugin components defined by libraries or users.","section":"specification/configuration/sdk.md#sdk-extension-components","sectionTitle":"SDK extension components","status":"Stable","source":"spec"},{"id":"f43032b6ded8","level":"MUST","text":"SDK implementations of configuration MUST provide the following operations.","section":"specification/configuration/sdk.md#sdk-operations","sectionTitle":"SDK operations","status":"Stable","source":"spec"},{"id":"5d2fedac6e79","level":"MAY","text":"According to the trace, metric, and log specs, SDKs MAY support updating the config, but there is no conflict with declarative config which doesn't already exist.","section":"specification/configuration/supplementary-guidelines.md#configuration-interface-prioritization-and-create","sectionTitle":"Configuration interface prioritization and `create`","status":"Unspecified","source":"spec"},{"id":"e6c7cadff6b9","level":"MUST","text":"MUST attempt to extract B3 encoded using single and multi-header formats.","section":"specification/context/api-propagators.md#b3-extract","sectionTitle":"B3 Extract","status":"Stable","source":"spec"},{"id":"ea69da009d2d","level":"MUST","text":"MUST preserve a debug trace flag, if received, and propagate it with subsequent requests.","section":"specification/context/api-propagators.md#b3-extract","sectionTitle":"B3 Extract","status":"Stable","source":"spec"},{"id":"ee22490e92d1","level":"MUST","text":"Additionally, an OpenTelemetry implementation MUST set the sampled trace flag when the debug flag is set.","section":"specification/context/api-propagators.md#b3-extract","sectionTitle":"B3 Extract","status":"Stable","source":"spec"},{"id":"e1ab57697dd9","level":"MUST NOT","text":"MUST NOT reuse `X-B3-SpanId` as the ID for the server-side span.","section":"specification/context/api-propagators.md#b3-extract","sectionTitle":"B3 Extract","status":"Stable","source":"spec"},{"id":"217ab215101f","level":"MUST","text":"MUST default to injecting B3 using the single-header format","section":"specification/context/api-propagators.md#b3-inject","sectionTitle":"B3 Inject","status":"Stable","source":"spec"},{"id":"b8908477ca5d","level":"MUST","text":"MUST provide configuration to change the default injection format to B3 multi-header","section":"specification/context/api-propagators.md#b3-inject","sectionTitle":"B3 Inject","status":"Stable","source":"spec"},{"id":"1d95ba83b798","level":"MUST NOT","text":"MUST NOT propagate `X-B3-ParentSpanId` as OpenTelemetry does not support reusing the same ID for both sides of a request.","section":"specification/context/api-propagators.md#b3-inject","sectionTitle":"B3 Inject","status":"Stable","source":"spec"},{"id":"295047e6568f","level":"REQUIRED","text":"If the `TextMapPropagator`'s `Extract` implementation accepts the optional `Getter` argument, the following arguments are REQUIRED, otherwise they are OPTIONAL:","section":"specification/context/api-propagators.md#composite-extract","sectionTitle":"Composite Extract","status":"Stable","source":"spec"},{"id":"df41ec69bbe5","level":"REQUIRED","text":"If the `TextMapPropagator`'s `Inject` implementation accepts the optional `Setter` argument, the following arguments are REQUIRED, otherwise they are OPTIONAL:","section":"specification/context/api-propagators.md#composite-inject","sectionTitle":"Composite Inject","status":"Stable","source":"spec"},{"id":"16c0bbd6603a","level":"MAY","text":"Propagators MAY invoke it multiple times in order to set multiple pairs.","section":"specification/context/api-propagators.md#composite-inject","sectionTitle":"Composite Inject","status":"Stable","source":"spec"},{"id":"1e3fb761a6b9","level":"MUST","text":"Implementations MUST offer a facility to group multiple `Propagator`s from different cross-cutting concerns in order to leverage them as a single entity.","section":"specification/context/api-propagators.md#composite-propagator","sectionTitle":"Composite Propagator","status":"Stable","source":"spec"},{"id":"e80ae1633acc","level":"MUST","text":"There MUST be functions to accomplish the following operations.","section":"specification/context/api-propagators.md#composite-propagator","sectionTitle":"Composite Propagator","status":"Stable","source":"spec"},{"id":"9697b57b5a4c","level":"MUST NOT","text":"If a value can not be parsed from the carrier, for a cross-cutting concern, the implementation MUST NOT throw an exception and MUST NOT store a new value in the `Context`, in order to preserve any previously existing valid value.","section":"specification/context/api-propagators.md#extract","sectionTitle":"Extract","status":"Stable","source":"spec"},{"id":"e04eb4ed704e","level":"MUST","text":"Fields MUST return the header names that correspond to the configured format, i.e., the headers used for the inject operation.","section":"specification/context/api-propagators.md#fields-1","sectionTitle":"Fields","status":"Stable","source":"spec"},{"id":"2b964e2a4af6","level":"MUST","text":"The Get function MUST return the first value of the given propagation key or return null if the key doesn't exist.","section":"specification/context/api-propagators.md#get","sectionTitle":"Get","status":"Stable","source":"spec"},{"id":"f17da4715b65","level":"MUST","text":"If the getter is intended to work with an HTTP request object, the getter MUST be case insensitive.","section":"specification/context/api-propagators.md#get","sectionTitle":"Get","status":"Stable","source":"spec"},{"id":"0211fd2aeadc","level":"SHOULD","text":"This method SHOULD exist for each supported `Propagator` type.","section":"specification/context/api-propagators.md#get-global-propagator","sectionTitle":"Get Global Propagator","status":"Stable","source":"spec"},{"id":"b6f34207b2be","level":"MUST","text":"If explicitly implemented, the `GetAll` function MUST return all values of the given propagation key.","section":"specification/context/api-propagators.md#getall","sectionTitle":"GetAll","status":"Stable","source":"spec"},{"id":"b1a49337876a","level":"SHOULD","text":"It SHOULD return them in the same order as they appear in the carrier.","section":"specification/context/api-propagators.md#getall","sectionTitle":"GetAll","status":"Stable","source":"spec"},{"id":"a9fc8b4a28f6","level":"SHOULD","text":"If the key doesn't exist, it SHOULD return an empty collection.","section":"specification/context/api-propagators.md#getall","sectionTitle":"GetAll","status":"Stable","source":"spec"},{"id":"ae1ebc95867c","level":"MUST","text":"If the getter is intended to work with an HTTP request object, the getter MUST be case insensitive.","section":"specification/context/api-propagators.md#getall","sectionTitle":"GetAll","status":"Stable","source":"spec"},{"id":"693fa613ae78","level":"MUST","text":"The OpenTelemetry API MUST provide a way to obtain a propagator for each supported `Propagator` type.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"54f95f6aae9c","level":"SHOULD","text":"Instrumentation libraries SHOULD call propagators to extract and inject the context on all remote calls.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"b6f79e671647","level":"MAY","text":"Propagators, depending on the language, MAY be set up using various dependency injection techniques or available as global accessors.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"5732ce2548f3","level":"MAY","text":"In such cases, instrumentation libraries MAY choose not to use the API-provided propagators and instead hardcode the context extraction and injection logic.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"4627bf832016","level":"MUST","text":"The OpenTelemetry API MUST use no-op propagators unless explicitly configured otherwise.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"40551e933bcb","level":"MAY","text":"Therefore, context propagation MAY be enabled for any of them independently.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"366bfb6ef3fb","level":"SHOULD","text":"If pre-configured, `Propagator`s SHOULD default to a composite `Propagator` containing the W3C Trace Context Propagator and the Baggage `Propagator` specified in the Baggage API.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"46bfdbc2766c","level":"MUST","text":"These platforms MUST also allow pre-configured propagators to be disabled or overridden.","section":"specification/context/api-propagators.md#global-propagators","sectionTitle":"Global Propagators","status":"Stable","source":"spec"},{"id":"4cc0d6269209","level":"MUST","text":"The Propagator MUST retrieve the appropriate value from the `Context` first, such as `SpanContext`, `Baggage` or another cross-cutting concern context.","section":"specification/context/api-propagators.md#inject","sectionTitle":"Inject","status":"Stable","source":"spec"},{"id":"2ef72542b72c","level":"MUST","text":"The `Keys` function MUST return the list of all the keys in the carrier.","section":"specification/context/api-propagators.md#keys","sectionTitle":"Keys","status":"Stable","source":"spec"},{"id":"6f27ea2b9a36","level":"MUST","text":"`Propagator`s MUST define `Inject` and `Extract` operations, in order to write values to and read values from carriers respectively.","section":"specification/context/api-propagators.md#operations","sectionTitle":"Operations","status":"Stable","source":"spec"},{"id":"88d941bb68cf","level":"MUST","text":"Each `Propagator` type MUST define the specific carrier type and MAY define additional parameters.","section":"specification/context/api-propagators.md#operations","sectionTitle":"Operations","status":"Stable","source":"spec"},{"id":"00ee1ca0618e","level":"MUST","text":"The official list of propagators that MUST be maintained by the OpenTelemetry organization and MUST be distributed as OpenTelemetry Core packages:","section":"specification/context/api-propagators.md#propagators-distribution","sectionTitle":"Propagators Distribution","status":"Stable","source":"spec"},{"id":"0096b55a07f4","level":"MAY","text":"MAY alternatively be distributed as part of the OpenTelemetry API.","section":"specification/context/api-propagators.md#propagators-distribution","sectionTitle":"Propagators Distribution","status":"Stable","source":"spec"},{"id":"b04db74a01be","level":"MAY","text":"This is a list of additional propagators that MAY be maintained and distributed as OpenTelemetry Core packages:","section":"specification/context/api-propagators.md#propagators-distribution","sectionTitle":"Propagators Distribution","status":"Stable","source":"spec"},{"id":"dfed04f15e14","level":"MUST NOT","text":"It MUST NOT use `OpenTracing` in the resulting propagator name as it is not widely adopted format in the OpenTracing ecosystem.","section":"specification/context/api-propagators.md#propagators-distribution","sectionTitle":"Propagators Distribution","status":"Stable","source":"spec"},{"id":"f33f826f808a","level":"MUST NOT","text":"Additional `Propagator`s implementing vendor-specific protocols such as AWS X-Ray trace header protocol MUST NOT be maintained or distributed as part of the OpenTelemetry Core packages.","section":"specification/context/api-propagators.md#propagators-distribution","sectionTitle":"Propagators Distribution","status":"Stable","source":"spec"},{"id":"0cb7aa6dffc8","level":"MUST","text":"The implementation SHOULD preserve casing (e.g. it should not transform `Content-Type` to `content-type`) if the used protocol is case insensitive, otherwise it MUST preserve casing.","section":"specification/context/api-propagators.md#set","sectionTitle":"Set","status":"Stable","source":"spec"},{"id":"922bd99a3bac","level":"SHOULD","text":"This method SHOULD exist for each supported `Propagator` type.","section":"specification/context/api-propagators.md#set-global-propagator","sectionTitle":"Set Global Propagator","status":"Stable","source":"spec"},{"id":"908a85b98efe","level":"MAY","text":"Propagators MAY invoke it multiple times in order to set multiple pairs.","section":"specification/context/api-propagators.md#textmap-inject","sectionTitle":"TextMap Inject","status":"Stable","source":"spec"},{"id":"cda3fbb7dd5b","level":"MUST","text":"In order to increase compatibility, the key-value pairs MUST only consist of US-ASCII characters that make up valid HTTP header fields as per RFC 9110.","section":"specification/context/api-propagators.md#textmap-propagator","sectionTitle":"TextMap Propagator","status":"Stable","source":"spec"},{"id":"202a18586598","level":"MUST","text":"`Getter` and `Setter` MUST be stateless and allowed to be saved as constants, in order to effectively avoid runtime allocations.","section":"specification/context/api-propagators.md#textmap-propagator","sectionTitle":"TextMap Propagator","status":"Stable","source":"spec"},{"id":"eb1cff1a0471","level":"MUST","text":"A W3C Trace Context propagator MUST parse and validate the `traceparent` and `tracestate` HTTP headers as specified in W3C Trace Context Level 2.","section":"specification/context/api-propagators.md#w3c-trace-context-requirements","sectionTitle":"W3C Trace Context Requirements","status":"Stable","source":"spec"},{"id":"976c8eb77e60","level":"MUST","text":"A W3C Trace Context propagator MUST propagate a valid `traceparent` value using the same header.","section":"specification/context/api-propagators.md#w3c-trace-context-requirements","sectionTitle":"W3C Trace Context Requirements","status":"Stable","source":"spec"},{"id":"66fd8068350e","level":"MUST","text":"A W3C Trace Context propagator MUST propagate a valid `tracestate` unless the value is empty, in which case the `tracestate` header may be omitted.","section":"specification/context/api-propagators.md#w3c-trace-context-requirements","sectionTitle":"W3C Trace Context Requirements","status":"Stable","source":"spec"},{"id":"6b0c337d6f45","level":"MUST","text":"Language implementations MUST ensure that environment variable `Get`, `Set`, and `Keys` operations use normalized key names for context propagation.","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"2c662ddfa86b","level":"MUST","text":"To normalize a key name, implementations MUST:","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"95394047607d","level":"MUST","text":"`Set` MUST write values using the normalized form of the key provided by the propagator.","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"84b02081ac69","level":"MUST","text":"`Get` MUST normalize the key requested by the propagator and MUST use the normalized key name to read from the carrier.","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"935b4b226ce3","level":"MUST","text":"`Keys` MUST return only key names that are already normalized.","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"508bb00d8933","level":"MUST","text":"For example, if a propagator requests the key `x-b3-traceid`, the environment-specific `Get` operation MUST normalize the requested key to `XB3TRACEID` and read the `XB3TRACEID` environment variable.","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"0a08a5ff5709","level":"MUST NOT","text":"It MUST NOT read a non-normalized environment variable named `x-b3-traceid`, even though that name normalizes to `XB3TRACEID`.","section":"specification/context/env-carriers.md#key-name-normalization","sectionTitle":"Key Name Normalization","status":"Release Candidate","source":"spec"},{"id":"06a4ce1867e0","level":"SHOULD","text":"A `TextMapPropagator` SHOULD be used alongside its normal `Get`, `Set`, `Extract`, and `Inject` functionality as described in the API Propagators specification.","section":"specification/context/env-carriers.md#propagator-mechanisms","sectionTitle":"Propagator Mechanisms","status":"Release Candidate","source":"spec"},{"id":"da8bf7e54e64","level":"MUST NOT","text":"The environment variable carrier MUST be format-agnostic and MUST treat values as opaque strings and MUST NOT apply propagation-format-specific logic such as validating, parsing values, or enforcing other format-specific constraints.","section":"specification/context/env-carriers.md#propagator-mechanisms","sectionTitle":"Propagator Mechanisms","status":"Release Candidate","source":"spec"},{"id":"5a6c50ea9193","level":"SHOULD","text":"Language implementations SHOULD document operational guidance, including initialization-time extraction, child process environment handling, and security considerations.","section":"specification/context/env-carriers.md#propagator-mechanisms","sectionTitle":"Propagator Mechanisms","status":"Release Candidate","source":"spec"},{"id":"2bd93af1d645","level":"MUST NOT","text":"Language implementations MUST NOT spawn child processes as part of environment variable context propagation.","section":"specification/context/env-carriers.md#propagator-mechanisms","sectionTitle":"Propagator Mechanisms","status":"Release Candidate","source":"spec"},{"id":"469706dc0ef1","level":"MUST","text":"The API MUST accept the following parameters:","section":"specification/context/README.md#attach-context","sectionTitle":"Attach Context","status":"Stable","source":"spec"},{"id":"66a63afd7af3","level":"MUST","text":"The API MUST return a value that can be used as a `Token` to restore the previous `Context`.","section":"specification/context/README.md#attach-context","sectionTitle":"Attach Context","status":"Stable","source":"spec"},{"id":"b4a691274332","level":"MUST","text":"The API MUST accept the following parameter:","section":"specification/context/README.md#create-a-key","sectionTitle":"Create a key","status":"Stable","source":"spec"},{"id":"c38a79233e4d","level":"SHOULD NOT","text":"Multiple calls to `CreateKey` with the same name SHOULD NOT return the same value unless language constraints dictate otherwise.","section":"specification/context/README.md#create-a-key","sectionTitle":"Create a key","status":"Stable","source":"spec"},{"id":"72383526e40e","level":"MUST","text":"The API MUST return an opaque object representing the newly created key.","section":"specification/context/README.md#create-a-key","sectionTitle":"Create a key","status":"Stable","source":"spec"},{"id":"494cf7091d66","level":"MUST","text":"The API MUST accept the following parameters:","section":"specification/context/README.md#detach-context","sectionTitle":"Detach Context","status":"Stable","source":"spec"},{"id":"3dffea397e14","level":"MAY","text":"The API MAY return a value used to check whether the operation was successful or not.","section":"specification/context/README.md#detach-context","sectionTitle":"Detach Context","status":"Stable","source":"spec"},{"id":"bb5edfecf835","level":"MUST","text":"The API MUST return the `Context` associated with the caller's current execution unit.","section":"specification/context/README.md#get-current-context","sectionTitle":"Get current Context","status":"Stable","source":"spec"},{"id":"b76eeddd6100","level":"MUST","text":"The API MUST accept the following parameters:","section":"specification/context/README.md#get-value","sectionTitle":"Get value","status":"Stable","source":"spec"},{"id":"a63f3d315f62","level":"MUST","text":"The API MUST return the value in the `Context` for the specified key.","section":"specification/context/README.md#get-value","sectionTitle":"Get value","status":"Stable","source":"spec"},{"id":"4c1369d29462","level":"SHOULD","text":"These operations SHOULD only be used to implement automatic scope switching and define higher level APIs by SDK components and OpenTelemetry instrumentation libraries.","section":"specification/context/README.md#optional-global-operations","sectionTitle":"Optional Global operations","status":"Stable","source":"spec"},{"id":"96cea09ca50e","level":"MUST","text":"A `Context` MUST be immutable, and its write operations MUST result in the creation of a new `Context` containing the original values and the specified values updated.","section":"specification/context/README.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"5c0e1978467b","level":"MUST","text":"In the cases where an extremely clear, pre-existing option is not available, OpenTelemetry MUST provide its own `Context` implementation.","section":"specification/context/README.md#overview","sectionTitle":"Overview","status":"Stable","source":"spec"},{"id":"fd8494ce5862","level":"MUST","text":"The API MUST accept the following parameters:","section":"specification/context/README.md#set-value","sectionTitle":"Set value","status":"Stable","source":"spec"},{"id":"78a4a45f6c46","level":"MUST","text":"The API MUST return a new `Context` containing the new value.","section":"specification/context/README.md#set-value","sectionTitle":"Set value","status":"Stable","source":"spec"},{"id":"dc5f37937002","level":"MUST","text":"MUST not change during the lifetime of the entity.","section":"specification/entities/data-model.md#entity-data-model","sectionTitle":"Entity Data Model","status":"Development","source":"spec"},{"id":"6697a639786c","level":"MUST","text":"This field is required and MUST not be empty for valid entities. | | ID | map<string, attribute value> | Attributes that identify the entity.<p>MUST not change during the lifetime of the entity.","section":"specification/entities/data-model.md#entity-data-model","sectionTitle":"Entity Data Model","status":"Development","source":"spec"},{"id":"e618b8b5d69a","level":"SHOULD","text":"SHOULD follow OpenTelemetry semantic conventions for attributes. | | Description | map<string, attribute value> | Descriptive (non-identifying) attributes of the entity.<p>MAY change over the lifetime of the entity.","section":"specification/entities/data-model.md#entity-data-model","sectionTitle":"Entity Data Model","status":"Development","source":"spec"},{"id":"08fd309d9207","level":"MAY","text":"MAY be empty.","section":"specification/entities/data-model.md#entity-data-model","sectionTitle":"Entity Data Model","status":"Development","source":"spec"},{"id":"1577f906c3ad","level":"SHOULD","text":"SHOULD follow OpenTelemetry semantic conventions for attributes. |","section":"specification/entities/data-model.md#entity-data-model","sectionTitle":"Entity Data Model","status":"Development","source":"spec"},{"id":"f7c82b666b91","level":"MAY","text":"Note: These examples MAY diverge from semantic conventions.","section":"specification/entities/data-model.md#examples-of-entities","sectionTitle":"Examples of Entities","status":"Development","source":"spec"},{"id":"df97e1a7e00a","level":"MUST","text":"OpenTelemetry Semantic Conventions MUST define a set of identifying attribute keys for every defined entity type.","section":"specification/entities/data-model.md#identifying-attributes","sectionTitle":"Identifying Attributes","status":"Development","source":"spec"},{"id":"6e5e7b1ccae2","level":"SHOULD","text":"Names of the identifying attributes SHOULD use the entity type as a prefix to avoid collisions with other entity types.","section":"specification/entities/data-model.md#identifying-attributes","sectionTitle":"Identifying Attributes","status":"Development","source":"spec"},{"id":"fc504f2f96cf","level":"MUST","text":"Two independent observers that report the same entity MUST be able to supply identical values for all identifying attributes.","section":"specification/entities/data-model.md#identifying-attributes","sectionTitle":"Identifying Attributes","status":"Development","source":"spec"},{"id":"011398e9db8d","level":"MUST NOT","text":"If an observer cannot reliably obtain one or more identifying attributes, it MUST NOT emit telemetry using that entity type.","section":"specification/entities/data-model.md#identifying-attributes","sectionTitle":"Identifying Attributes","status":"Development","source":"spec"},{"id":"846aae637c02","level":"SHOULD","text":"Instead, it SHOULD:","section":"specification/entities/data-model.md#identifying-attributes","sectionTitle":"Identifying Attributes","status":"Development","source":"spec"},{"id":"d1f746425542","level":"MAY","text":"Entities MAY be merged if and only if their types are the same, their identity attributes are exactly the same AND their schema_url is the same.","section":"specification/entities/data-model.md#merging-of-entities","sectionTitle":"Merging of Entities","status":"Development","source":"spec"},{"id":"a6a753c65e31","level":"MUST","text":"This means both Entities MUST have the same identity attribute keys and for each key, the values of the key MUST be the same.","section":"specification/entities/data-model.md#merging-of-entities","sectionTitle":"Merging of Entities","status":"Development","source":"spec"},{"id":"8a4aca68f69e","level":"SHOULD","text":"Note: If Entities have different `schema_url`s, they SHOULD be converted to the same schema version (if possible) before attempting a merge.","section":"specification/entities/data-model.md#merging-of-entities","sectionTitle":"Merging of Entities","status":"Development","source":"spec"},{"id":"f06629921b14","level":"MUST","text":"If multiple entities share the same descriptive attribute key with potentially conflicting values, the attribute MUST logically belong to only one of them.","section":"specification/entities/data-model.md#placement-of-shared-descriptive-attributes","sectionTitle":"Placement of Shared Descriptive Attributes","status":"Development","source":"spec"},{"id":"cec221ea3ae1","level":"SHOULD NOT","text":"All others SHOULD NOT reference it.","section":"specification/entities/data-model.md#placement-of-shared-descriptive-attributes","sectionTitle":"Placement of Shared Descriptive Attributes","status":"Development","source":"spec"},{"id":"7d59080b04ff","level":"MUST","text":"The attribute MUST be referenced by the most specific entity, the one closest in the topology graph to the entity associated with the telemetry signal.","section":"specification/entities/data-model.md#placement-of-shared-descriptive-attributes","sectionTitle":"Placement of Shared Descriptive Attributes","status":"Development","source":"spec"},{"id":"be20d325455c","level":"SHOULD","text":"The identifying attributes for entity SHOULD be values that can be repeatably obtained by observers of that entity.","section":"specification/entities/data-model.md#repeatable-identity","sectionTitle":"Repeatable Identity","status":"Development","source":"spec"},{"id":"904eee5dc928","level":"SHOULD","text":"For example, a `process` entity SHOULD have the same identity (and be recognized as the same process), regardless of whether the identity was generated from the process itself, e.g. via SDK, or by an OpenTelemetry Collector running on the same host, or by some other system describing the process.","section":"specification/entities/data-model.md#repeatable-identity","sectionTitle":"Repeatable Identity","status":"Development","source":"spec"},{"id":"1d9139e8eab8","level":"MUST","text":"Recipients of entity signals MUST be prepared to handle this situation by expiring entities that are no longer seeing Entity State events reported.","section":"specification/entities/entity-events.md#entity-delete-event","sectionTitle":"Entity Delete Event","status":"Development","source":"spec"},{"id":"84dba6670c99","level":"MUST","text":"Recipients MUST also be prepared to receive an Entity Delete event out of order, for example, before the last Entity State event.","section":"specification/entities/entity-events.md#entity-delete-event","sectionTitle":"Entity Delete Event","status":"Development","source":"spec"},{"id":"ae7f605dc751","level":"SHOULD","text":"In this case, recipients SHOULD apply state updates regardless, as each Entity State event represents the full current state of the entity and can be used to update a previously deleted entity record.","section":"specification/entities/entity-events.md#entity-delete-event","sectionTitle":"Entity Delete Event","status":"Development","source":"spec"},{"id":"08170b76b91f","level":"MUST","text":"MUST not change during the lifetime of the entity.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"1d78c29d64fd","level":"MUST","text":"The map MUST contain at least one attribute.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"6490ccae9e9f","level":"MUST","text":"Keys and values MUST be strings.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"0ae765be8c77","level":"SHOULD","text":"SHOULD follow OpenTelemetry semantic conventions for attribute names. |","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"4b955a575ea5","level":"MUST","text":"When absent, MUST be treated as an empty map.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"3b7d2c8a81a5","level":"SHOULD","text":"SHOULD follow OpenTelemetry semantic conventions for attributes. | | `entity.relationships` | array of maps | Relationships to other entities.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"5d15113fa91d","level":"MUST","text":"When absent, MUST be treated as an empty array. | | `entity.report.interval` | int64 (seconds) | The reporting period for this entity.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"d353b74ea63b","level":"MUST","text":"MUST be a non-negative value when present.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"76ecb2966410","level":"SHOULD","text":"Implementations SHOULD emit Entity State events whenever entity descriptive attributes change, and periodically based on the `entity.report.interval` value to indicate the entity still exists.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"1c52930a4de6","level":"SHOULD","text":"Implementations SHOULD also emit Entity Delete events when entities are removed.","section":"specification/entities/entity-events.md#entity-state-event","sectionTitle":"Entity State Event","status":"Development","source":"spec"},{"id":"1c067f96692a","level":"SHOULD","text":"Backends SHOULD handle this accordingly.","section":"specification/entities/entity-events.md#relationship-lifecycle","sectionTitle":"Relationship Lifecycle","status":"Development","source":"spec"},{"id":"0cff2979f5ab","level":"SHOULD","text":"When choosing which entity should contain a relationship in its `entity.relationships` array, implementations SHOULD prefer placing relationships on the entity type with the shorter lifespan or higher churn rate.","section":"specification/entities/entity-events.md#relationship-placement","sectionTitle":"Relationship Placement","status":"Development","source":"spec"},{"id":"71a8decfaedc","level":"SHOULD","text":"Semantic conventions SHOULD provide guidance on relationship placement for common entity types.","section":"specification/entities/entity-events.md#relationship-placement","sectionTitle":"Relationship Placement","status":"Development","source":"spec"},{"id":"31425c6bf182","level":"SHOULD","text":"Standard relationship types SHOULD be defined in OpenTelemetry semantic conventions.","section":"specification/entities/entity-events.md#standard-relationship-types","sectionTitle":"Standard Relationship Types","status":"Development","source":"spec"},{"id":"9f5fa101b471","level":"MAY","text":"Custom relationship types MAY be defined to represent domain-specific relationships.","section":"specification/entities/entity-events.md#standard-relationship-types","sectionTitle":"Standard Relationship Types","status":"Development","source":"spec"},{"id":"3ed896dc0ab0","level":"MUST","text":"All attribute values MUST be considered strings and characters outside the `baggage-octet` range MUST be percent-encoded following the W3C Baggage specification.","section":"specification/entities/entity-propagation.md#character-encoding","sectionTitle":"Character Encoding","status":"Development","source":"spec"},{"id":"c03bb00d1e9d","level":"MUST","text":"The reserved characters `{}[]@;,=` MUST be percent-encoded when they appear literally in attribute values:","section":"specification/entities/entity-propagation.md#character-encoding","sectionTitle":"Character Encoding","status":"Development","source":"spec"},{"id":"4717348f46c1","level":"SHOULD","text":"The SDK SHOULD be resilient to malformed input and follow these error handling rules:","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"1bf19aed103f","level":"SHOULD","text":"Invalid syntax: If the environment variable contains invalid syntax, the SDK SHOULD log a warning and ignore the malformed portions while processing valid parts","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"7c74dee845ed","level":"SHOULD","text":"Missing required fields: If an entity is missing required fields (type or identifying attributes), the SDK SHOULD log a warning and skip that entity","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"cca0e53c00d7","level":"SHOULD","text":"Duplicate entities: If multiple entities of the same type with identical identifying attributes are defined, the SDK SHOULD use the last occurrence and SHOULD log a warning","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"e6bb56b4a58b","level":"SHOULD","text":"Schema URL validation: If a schema URL is present but invalid, the SDK SHOULD log a warning and ignore the URL while processing the entity","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"ea2615a50fce","level":"SHOULD","text":"Conflicting identifying attributes: If two entities of the same type define different values for the same identifying attribute key, the SDK SHOULD log a warning and preserve only the last entity","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"c6bf8b0dc340","level":"SHOULD","text":"Conflicting descriptive attributes: If two entities define different values for the same descriptive attribute key, the SDK SHOULD use the value from the last entity definition and SHOULD log a warning.","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"17ffdfdb2350","level":"SHOULD NOT","text":"The conflicting attributes SHOULD NOT be recorded for entities other than the last one","section":"specification/entities/entity-propagation.md#error-handling","sectionTitle":"Error Handling","status":"Development","source":"spec"},{"id":"0152279864f4","level":"MUST","text":"The SDK that has access to environment variables MUST provide an `EnvEntityDetector` which will use the `OTEL_ENTITIES` environment variable to discover and associate defined entities with the resource.","section":"specification/entities/entity-propagation.md#specifying-entity-information-via-an-environment-variable","sectionTitle":"Specifying entity information via an environment variable","status":"Development","source":"spec"},{"id":"48de42adf36e","level":"MUST NOT","text":"Entity type MUST NOT be empty and MUST match the pattern `[a-zA-Z][a-zA-Z0-9.-]`","section":"specification/entities/entity-propagation.md#validation-requirements","sectionTitle":"Validation Requirements","status":"Development","source":"spec"},{"id":"c6f9e923d512","level":"MUST","text":"At least one identifying attribute MUST be present in the `{...}` block","section":"specification/entities/entity-propagation.md#validation-requirements","sectionTitle":"Validation Requirements","status":"Development","source":"spec"},{"id":"a22528f83cce","level":"MUST NOT","text":"Attribute keys MUST NOT be empty and SHOULD follow OpenTelemetry semantic conventions","section":"specification/entities/entity-propagation.md#validation-requirements","sectionTitle":"Validation Requirements","status":"Development","source":"spec"},{"id":"9a57d9245bc1","level":"MUST","text":"Schema URL, if present, MUST be a valid URI","section":"specification/entities/entity-propagation.md#validation-requirements","sectionTitle":"Validation Requirements","status":"Development","source":"spec"},{"id":"da0b621c55de","level":"SHOULD","text":"Entity types SHOULD follow existing OpenTelemetry entity naming conventions (e.g., \"service\", \"host\", \"container\", \"k8s.pod\")","section":"specification/entities/entity-propagation.md#validation-requirements","sectionTitle":"Validation Requirements","status":"Development","source":"spec"},{"id":"9d8cda29b726","level":"MUST NOT","text":"OpenTelemetry implementations MUST NOT throw unhandled exceptions at runtime.","section":"specification/error-handling.md#basic-error-handling-principles","sectionTitle":"Basic error handling principles","status":"Unspecified","source":"spec"},{"id":"2eaad126ee13","level":"MUST NOT","text":"API methods MUST NOT throw unhandled exceptions when used incorrectly by end users.","section":"specification/error-handling.md#basic-error-handling-principles","sectionTitle":"Basic error handling principles","status":"Unspecified","source":"spec"},{"id":"5f43abd79214","level":"SHOULD","text":"The API and SDK SHOULD provide safe defaults for missing or invalid arguments.","section":"specification/error-handling.md#basic-error-handling-principles","sectionTitle":"Basic error handling principles","status":"Unspecified","source":"spec"},{"id":"c961d3623138","level":"MUST NOT","text":"The API or SDK MAY fail fast and cause the application to fail on initialization, e.g. because of a bad user config or environment, but MUST NOT cause the application to fail later at runtime, e.g. due to dynamic config settings received from the Collector.","section":"specification/error-handling.md#basic-error-handling-principles","sectionTitle":"Basic error handling principles","status":"Unspecified","source":"spec"},{"id":"d7ecae349083","level":"MUST NOT","text":"The SDK MUST NOT throw unhandled exceptions for errors in their own operations.","section":"specification/error-handling.md#basic-error-handling-principles","sectionTitle":"Basic error handling principles","status":"Unspecified","source":"spec"},{"id":"1b84f172c7c7","level":"MUST","text":"SDK implementations MUST allow end users to change the library's default error handling behavior for relevant errors.","section":"specification/error-handling.md#configuring-error-handlers","sectionTitle":"Configuring Error Handlers","status":"Unspecified","source":"spec"},{"id":"a537a4fc10e2","level":"MUST","text":"API methods that accept external callbacks MUST handle all errors.","section":"specification/error-handling.md#guidance","sectionTitle":"Guidance","status":"Unspecified","source":"spec"},{"id":"bb73cb8b3d8b","level":"MUST","text":"Whenever API call returns values that is expected to be non-`null` value - in case of error in processing logic - SDK MUST return a \"no-op\" or any other \"default\" object that was (ideally) pre-allocated and readily available.","section":"specification/error-handling.md#guidance","sectionTitle":"Guidance","status":"Unspecified","source":"spec"},{"id":"f353883acee3","level":"SHOULD","text":"Whenever the library suppresses an error that would otherwise have been exposed to the user, the library SHOULD log the error using language-specific conventions.","section":"specification/error-handling.md#self-diagnostics","sectionTitle":"Self-diagnostics","status":"Unspecified","source":"spec"},{"id":"a9d531f8074c","level":"MAY","text":"SDKs MAY expose callbacks to allow end users to handle self-diagnostics separately from application code.","section":"specification/error-handling.md#self-diagnostics","sectionTitle":"Self-diagnostics","status":"Unspecified","source":"spec"},{"id":"16c36c68a195","level":"MUST","text":"To enable this clean separation, the OpenTelemetry API and SDK libraries MUST be provided as independent artifacts.","section":"specification/library-guidelines.md#requirements","sectionTitle":"Requirements","status":"Unspecified","source":"spec"},{"id":"52621f80bf2d","level":"MUST","text":"These MUST be implemented outside of the SDK.","section":"specification/library-guidelines.md#resource-detection","sectionTitle":"Resource Detection","status":"Unspecified","source":"spec"},{"id":"10e409fec49a","level":"MUST","text":"API and SDK packages MUST be labeled with their own version number.","section":"specification/library-guidelines.md#version-labeling","sectionTitle":"Version Labeling","status":"Unspecified","source":"spec"},{"id":"27de22157526","level":"MUST","text":"Because API and SDK package version numbers are not coupled, every API and SDK package release MUST clearly mention the Specification version number that they implement.","section":"specification/library-guidelines.md#version-labeling","sectionTitle":"Version Labeling","status":"Unspecified","source":"spec"},{"id":"0a79d33102c3","level":"MUST","text":"OpenTelemetry client authors MUST include this information in the release notes.","section":"specification/library-guidelines.md#version-labeling","sectionTitle":"Version Labeling","status":"Unspecified","source":"spec"},{"id":"c36d315790cb","level":"MUST","text":"LoggerProvider - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/logs/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"a54b20783525","level":"MUST","text":"Logger - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/logs/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"ae71736a16ad","level":"MUST","text":"The API MUST accept the following parameters:","section":"specification/logs/api.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"217dcc21dd6c","level":"MUST","text":"When implicit Context is supported, then this parameter SHOULD be optional and if unspecified then MUST use current Context.","section":"specification/logs/api.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"5379077c729f","level":"SHOULD","text":"When only explicit Context is supported, this parameter SHOULD be required.","section":"specification/logs/api.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"e214f6c74a27","level":"MAY","text":"The API MAY accept the following parameter:","section":"specification/logs/api.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"8abd61aac0b5","level":"SHOULD","text":"To help users avoid performing computationally expensive operations when generating a `LogRecord`, a `Logger` SHOULD provide this `Enabled` API.","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"cd0d79a44695","level":"SHOULD","text":"The API SHOULD accept the following parameters:","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"b0c95956f31d","level":"MUST","text":"When implicit Context is supported, then this parameter SHOULD be optional and if unspecified then MUST use current Context.","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"de887f59d240","level":"REQUIRED","text":"When only explicit Context is supported, accepting this parameter is REQUIRED.","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"0741080ff296","level":"MUST","text":"This API MUST return a language idiomatic boolean type.","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"624cfbbe3125","level":"SHOULD","text":"The API documentation SHOULD state that calling `Enabled` is optional and is not required before emitting a `LogRecord`.","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"5dec17dd495e","level":"SHOULD","text":"The documentation SHOULD also state that the returned value is not static and can change over time, so a cached value can become stale.","section":"specification/logs/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"e31a8c0d86c2","level":"MAY","text":"Languages MAY additionally provide a more ergonomic and convenient logging API.","section":"specification/logs/api.md#ergonomic-api","sectionTitle":"Ergonomic API","status":"Stable","source":"spec"},{"id":"1d66a16fc23a","level":"SHOULD","text":"The ergonomic API SHOULD make it more convenient to emit event records following the event semantics.","section":"specification/logs/api.md#ergonomic-api","sectionTitle":"Ergonomic API","status":"Stable","source":"spec"},{"id":"611de86db336","level":"SHOULD","text":"The design of the ergonomic API SHOULD be idiomatic for its language.","section":"specification/logs/api.md#ergonomic-api","sectionTitle":"Ergonomic API","status":"Stable","source":"spec"},{"id":"e4c6c84b6e16","level":"MUST","text":"This API MUST accept the following instrumentation scope parameters:","section":"specification/logs/api.md#get-a-logger","sectionTitle":"Get a Logger","status":"Stable","source":"spec"},{"id":"35bbe49b4297","level":"MUST","text":"This API MUST be structured to accept a variable number of attributes, including none.","section":"specification/logs/api.md#get-a-logger","sectionTitle":"Get a Logger","status":"Stable","source":"spec"},{"id":"94c2cd5f1980","level":"MUST","text":"The `Logger` MUST provide a function to:","section":"specification/logs/api.md#logger","sectionTitle":"Logger","status":"Stable","source":"spec"},{"id":"77f72bf2059b","level":"SHOULD","text":"The `Logger` SHOULD provide functions to:","section":"specification/logs/api.md#logger","sectionTitle":"Logger","status":"Stable","source":"spec"},{"id":"a2614ef788f4","level":"SHOULD","text":"Thus, the API SHOULD provide a way to set/register and access a global default `LoggerProvider`.","section":"specification/logs/api.md#loggerprovider","sectionTitle":"LoggerProvider","status":"Stable","source":"spec"},{"id":"d6587105c42b","level":"MUST","text":"The `LoggerProvider` MUST provide the following functions:","section":"specification/logs/api.md#loggerprovider-operations","sectionTitle":"LoggerProvider operations","status":"Stable","source":"spec"},{"id":"44f9d9f521d0","level":"MUST NOT","text":"For each optional parameter, the API MUST be structured to accept it, but MUST NOT obligate a user to provide it.","section":"specification/logs/api.md#optional-and-required-parameters","sectionTitle":"Optional and required parameters","status":"Stable","source":"spec"},{"id":"2a7d004aebd6","level":"MUST","text":"For each required parameter, the API MUST be structured to obligate a user to provide it.","section":"specification/logs/api.md#optional-and-required-parameters","sectionTitle":"Optional and required parameters","status":"Stable","source":"spec"},{"id":"8ad4871fab58","level":"MAY","text":"Special handling MAY be given to `SeverityNumber=0` when it is used to represent an unspecified severity.","section":"specification/logs/data-model.md#comparing-severity","sectionTitle":"Comparing Severity","status":"Stable","source":"spec"},{"id":"20f2448e1c9f","level":"MAY","text":"Additional information about errors and/or exceptions that are associated with a log record MAY be included in the structured data in the `Attributes` section of the record.","section":"specification/logs/data-model.md#errors-and-exceptions","sectionTitle":"Errors and Exceptions","status":"Stable","source":"spec"},{"id":"5a1eee9a08ed","level":"MUST","text":"If included, they MUST follow the OpenTelemetry semantic conventions for exception-related attributes.","section":"specification/logs/data-model.md#errors-and-exceptions","sectionTitle":"Errors and Exceptions","status":"Stable","source":"spec"},{"id":"3ed1143bf61b","level":"SHOULD","text":"All semantic conventions defined for logs SHOULD be formatted as Events.","section":"specification/logs/data-model.md#events","sectionTitle":"Events","status":"Stable","source":"spec"},{"id":"27cb7be250b4","level":"MUST","text":"Body MUST support AnyValue to preserve the semantics of structured logs emitted by the applications.","section":"specification/logs/data-model.md#field-body","sectionTitle":"Field: `Body`","status":"Stable","source":"spec"},{"id":"7c13790f762e","level":"SHOULD","text":"This name SHOULD uniquely identify the event structure (both attributes and body).","section":"specification/logs/data-model.md#field-eventname","sectionTitle":"Field: `EventName`","status":"Stable","source":"spec"},{"id":"fb5a61c84d95","level":"SHOULD","text":"This field SHOULD be set once the event is observed by OpenTelemetry.","section":"specification/logs/data-model.md#field-observedtimestamp","sectionTitle":"Field: `ObservedTimestamp`","status":"Stable","source":"spec"},{"id":"ca9c3aa962ef","level":"SHOULD","text":"SHOULD follow OpenTelemetry semantic conventions for Resources.","section":"specification/logs/data-model.md#field-resource","sectionTitle":"Field: `Resource`","status":"Stable","source":"spec"},{"id":"1368b951d46c","level":"MAY","text":"`SeverityNumber=0` MAY be used to represent an unspecified value.","section":"specification/logs/data-model.md#field-severitynumber","sectionTitle":"Field: `SeverityNumber`","status":"Stable","source":"spec"},{"id":"ba5ad6c31911","level":"SHOULD","text":"If SpanId is present TraceId SHOULD be also present.","section":"specification/logs/data-model.md#field-spanid","sectionTitle":"Field: `SpanId`","status":"Stable","source":"spec"},{"id":"f6b30ffd40bb","level":"MAY","text":"Source formats that do not define a concept of severity or log level MAY omit `SeverityNumber` and `SeverityText` fields.","section":"specification/logs/data-model.md#mapping-of-severitynumber","sectionTitle":"Mapping of `SeverityNumber`","status":"Stable","source":"spec"},{"id":"9d99e1394efe","level":"MUST","text":"The No-Op `Logger` MUST allow for emitting LogRecords.","section":"specification/logs/noop.md#emit-logrecord","sectionTitle":"Emit LogRecord","status":"Stable","source":"spec"},{"id":"f790e28c485e","level":"MUST","text":"MUST always return `false`.","section":"specification/logs/noop.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"a45e37b03870","level":"MUST","text":"Therefore, `LoggerProvider` MUST allow for the creation of `Logger`s.","section":"specification/logs/noop.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"3257b561c725","level":"MUST","text":"All `Logger`s created MUST be an instance of the No-Op Logger.","section":"specification/logs/noop.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"34660927b9f2","level":"MAY","text":"Since all `Logger`s will hold the same empty state, a `LoggerProvider` MAY return the same `Logger` instances to all creation requests.","section":"specification/logs/noop.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"7d3b8240191c","level":"MUST","text":"The No-Op MUST allow the creation of multiple `LoggerProviders`s.","section":"specification/logs/noop.md#loggerprovider","sectionTitle":"LoggerProvider","status":"Stable","source":"spec"},{"id":"a244c5f37bb2","level":"MAY","text":"Since all `LoggerProviders`s hold the same empty state, a No-Op MAY provide the same `LoggerProvider` instances to all creation requests.","section":"specification/logs/noop.md#loggerprovider","sectionTitle":"LoggerProvider","status":"Stable","source":"spec"},{"id":"cab895d37316","level":"MUST","text":"All language implementations of OpenTelemetry MUST provide a No-Op.","section":"specification/logs/noop.md#logs-api-no-op-implementation","sectionTitle":"Logs API No-Op Implementation","status":"Stable","source":"spec"},{"id":"dcffad958233","level":"MUST NOT","text":"All No-Op components MUST NOT hold configuration or operational state.","section":"specification/logs/noop.md#logs-api-no-op-implementation","sectionTitle":"Logs API No-Op Implementation","status":"Stable","source":"spec"},{"id":"d75ceb02f8e8","level":"MUST NOT","text":"All No-op operations MUST accept all defined parameters, MUST NOT validate any arguments received, and MUST NOT return any non-empty error or log any message.","section":"specification/logs/noop.md#logs-api-no-op-implementation","sectionTitle":"Logs API No-Op Implementation","status":"Stable","source":"spec"},{"id":"72e269a5ada6","level":"SHOULD","text":"Documentation SHOULD warn users about this.","section":"specification/logs/sdk_exporters/stdout.md#logs-exporter---standard-output","sectionTitle":"Logs Exporter - Standard output","status":"Stable","source":"spec"},{"id":"8ad48b09151e","level":"MAY","text":"OpenTelemetry SDK authors MAY choose the best idiomatic name for their language.","section":"specification/logs/sdk_exporters/stdout.md#logs-exporter---standard-output","sectionTitle":"Logs Exporter - Standard output","status":"Stable","source":"spec"},{"id":"22fd7a6eef3c","level":"SHOULD","text":"If a language provides a mechanism to automatically configure a LogRecordProcessor to pair with the associated exporter (e.g., using the `OTELLOGSEXPORTER` environment variable), by default the standard output exporter SHOULD be paired with a simple processor.","section":"specification/logs/sdk_exporters/stdout.md#logs-exporter---standard-output","sectionTitle":"Logs Exporter - Standard output","status":"Stable","source":"spec"},{"id":"78217df96280","level":"MUST","text":"The processor MUST synchronize calls to `LogRecordExporter`'s `Export` to make sure that they are not invoked concurrently.","section":"specification/logs/sdk.md#batching-processor","sectionTitle":"Batching processor","status":"Stable","source":"spec"},{"id":"95ec7417fe23","level":"MUST","text":"The standard OpenTelemetry SDK MUST implement both simple and batch processors, as described below.","section":"specification/logs/sdk.md#built-in-processors","sectionTitle":"Built-in processors","status":"Stable","source":"spec"},{"id":"c77f1946039f","level":"SHOULD","text":"Other common processing scenarios SHOULD be first considered for implementation out-of-process in OpenTelemetry Collector.","section":"specification/logs/sdk.md#built-in-processors","sectionTitle":"Built-in processors","status":"Stable","source":"spec"},{"id":"3063a154567f","level":"SHOULD","text":"Additional processors defined in this document SHOULD be provided by SDK packages.","section":"specification/logs/sdk.md#built-in-processors","sectionTitle":"Built-in processors","status":"Stable","source":"spec"},{"id":"d831eed561d6","level":"MUST","text":"LoggerProvider - Logger creation, `ForceFlush` and `Shutdown` MUST be safe to be called concurrently.","section":"specification/logs/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"995080ba1ac7","level":"MUST","text":"Logger - all methods MUST be safe to be called concurrently.","section":"specification/logs/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"0e88bcc600cb","level":"MUST","text":"LogRecordExporter - `ForceFlush` and `Shutdown` MUST be safe to be called concurrently.","section":"specification/logs/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"953241fe0c7f","level":"MUST","text":"Configuration ( i.e. LogRecordProcessors and (Development) LoggerConfigurator) MUST be owned by the `LoggerProvider`.","section":"specification/logs/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"30d023d95fc9","level":"MAY","text":"The configuration MAY be applied at the time of `LoggerProvider` creation if appropriate.","section":"specification/logs/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"cbdfdb7312a9","level":"MAY","text":"The `LoggerProvider` MAY provide methods to update the configuration.","section":"specification/logs/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"ef50f0bcb71a","level":"MUST NOT","text":"If configuration is updated (e.g., adding a `LogRecordProcessor`), the updated configuration MUST also apply to all already returned `Logger`s (i.e. it MUST NOT matter whether a `Logger` was obtained from the `LoggerProvider` before or after the configuration change).","section":"specification/logs/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"9f6ec327e44f","level":"SHOULD","text":"If Observed Timestamp is unspecified, the implementation SHOULD set it equal to the current time.","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"e2903a45b18e","level":"MUST","text":"If an Exception is provided, the SDK MUST by default set attributes from the exception on the `LogRecord` with the conventions outlined in the exception semantic conventions.","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"bdf3c72f7bce","level":"MUST NOT","text":"User-provided attributes MUST take precedence and MUST NOT be overwritten by exception-derived attributes.","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"e176642eda29","level":"MAY","text":"Note: For performance optimization, SDKs MAY take the configured attribute limits into consideration when generating large exception attributes (e.g., `exception.stacktrace`).","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"1b4fb25ed4de","level":"MUST","text":"Status: Development Before processing a log record, the implementation MUST apply the filtering rules defined by the LoggerConfig:","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"71eb24048f14","level":"MUST","text":"Enabled: If the `Logger` is not enabled (i.e. `LoggerConfig.enabled` is `false`), the log record MUST be dropped.","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"e363e2155fdb","level":"MUST","text":"Minimum severity: If the log record's SeverityNumber is specified (i.e. not `0`) and is less than the configured `minimum_severity`, the log record MUST be dropped.","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"acf72e0f7841","level":"MUST","text":"Trace-based: If `trace_based` is `true`, and if the log record has a `SpanId` and the `TraceFlags` SAMPLED flag is unset, the log record MUST be dropped.","section":"specification/logs/sdk.md#emit-a-logrecord","sectionTitle":"Emit a LogRecord","status":"Stable","source":"spec"},{"id":"99c7fa8e3838","level":"MUST","text":"`Enabled` MUST return `false` when either:","section":"specification/logs/sdk.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"47d427859e42","level":"SHOULD","text":"Otherwise, it SHOULD return `true`.","section":"specification/logs/sdk.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"eb227d8e8c85","level":"MAY","text":"It MAY return `false` to support additional optimizations and features.","section":"specification/logs/sdk.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"5411f42384af","level":"MAY","text":"`Enabled` is an operation that a `LogRecordProcessor` MAY implement in order to support filtering via `Logger.Enabled`.","section":"specification/logs/sdk.md#enabled-1","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"f6dfb4e9664d","level":"MUST NOT","text":"Any modifications to parameters inside `Enabled` MUST NOT be propagated to the caller.","section":"specification/logs/sdk.md#enabled-1","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"a1dc992ed35d","level":"SHOULD","text":"This processor SHOULD be provided by SDK.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"920909e80890","level":"MUST","text":"The processor MUST bridge a `LogRecord` to a span event if and only if all of the following conditions are met:","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"18beb2199b6d","level":"MUST","text":"If any of these conditions is not met, the processor MUST do nothing.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"a88f82e2f5c4","level":"MUST","text":"When a `LogRecord` is bridged, the processor MUST add exactly one span event with the following mapping:","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"25ca004f4585","level":"MUST","text":"the span event name MUST be the `LogRecord`'s Event Name.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"f2f3b5b7aa02","level":"MUST","text":"if the `LogRecord` has a Timestamp set, it MUST be used as the span event timestamp.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"f029625c1396","level":"MUST","text":"Otherwise, if the `LogRecord` has an ObservedTimestamp set, it MUST be used as the span event timestamp.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"3c2ad1566bc7","level":"MUST","text":"all `LogRecord` Attributes MUST be copied to the span event as span event attributes.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"cb7f692bffc6","level":"MUST NOT","text":"Note that bridging a `LogRecord` to a span event MUST NOT prevent that `LogRecord` from continuing through the normal log processing pipeline.","section":"specification/logs/sdk.md#event-to-span-event-bridge","sectionTitle":"Event to span event bridge","status":"Stable","source":"spec"},{"id":"d194ba7d7643","level":"MUST NOT","text":"`Export` MUST NOT block indefinitely, there MUST be a reasonable upper limit after which the call must time out with an error result (`Failure`).","section":"specification/logs/sdk.md#export","sectionTitle":"Export","status":"Stable","source":"spec"},{"id":"24360d4a40ee","level":"SHOULD NOT","text":"The default SDK's `LogRecordProcessors` SHOULD NOT implement retry logic, as the required logic is likely to depend heavily on the specific protocol and backend the logs are being sent to.","section":"specification/logs/sdk.md#export","sectionTitle":"Export","status":"Stable","source":"spec"},{"id":"f7b40a5c45d6","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/logs/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"1a20cf6031c9","level":"SHOULD","text":"`ForceFlush` SHOULD return some ERROR status if there is an error condition; and if there is no error condition, it SHOULD return some NO ERROR status, language implementations MAY decide how to model ERROR and NO ERROR.","section":"specification/logs/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"43c822a80cf2","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/logs/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"9a9f0f2a9687","level":"MAY","text":"`ForceFlush` MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.","section":"specification/logs/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"8f8ed1367bff","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the flush timeout configurable.","section":"specification/logs/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"aedf6b7eb5bf","level":"MUST","text":"`ForceFlush` MUST invoke `ForceFlush` on all registered LogRecordProcessors.","section":"specification/logs/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"c61899b6468e","level":"SHOULD","text":"This is a hint to ensure that any tasks associated with `LogRecord`s for which the `LogRecordProcessor` had already received events prior to the call to `ForceFlush` SHOULD be completed as soon as possible, preferably before returning from this method.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"6fee03eace49","level":"SHOULD","text":"In particular, if any `LogRecordProcessor` has any associated exporter, it SHOULD try to call the exporter's `Export` with all `LogRecord`s for which this was not already done and then invoke `ForceFlush` on it.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"a473c25d39a5","level":"MUST","text":"The built-in LogRecordProcessors MUST do so.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"39536c56d002","level":"MUST","text":"If a timeout is specified (see below), the `LogRecordProcessor` MUST prioritize honoring the timeout over finishing all calls.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"ca63d3d1fae4","level":"MAY","text":"It MAY skip or abort some or all Export or ForceFlush calls it has made to achieve this goal.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"543e62f6f3ff","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"f3d5a7c11fbf","level":"SHOULD","text":"`ForceFlush` SHOULD only be called in cases where it is absolutely necessary, such as when using some FaaS providers that may suspend the process after an invocation, but before the `LogRecordProcessor` exports the emitted `LogRecord`s.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"dc7cd6c1f072","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/logs/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"b298c333e138","level":"SHOULD","text":"This is a hint to ensure that the export of any `ReadableLogRecords` the exporter has received prior to the call to `ForceFlush` SHOULD be completed as soon as possible, preferably before returning from this method.","section":"specification/logs/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"e661dc775b25","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/logs/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"6780b2e5467c","level":"SHOULD","text":"`ForceFlush` SHOULD only be called in cases where it is absolutely necessary, such as when using some FaaS providers that may suspend the process after an invocation, but before the exporter exports the `ReadlableLogRecords`.","section":"specification/logs/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"1fa29ae52653","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/logs/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"b3fdcfadb995","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the flush timeout configurable.","section":"specification/logs/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"ce99435fdb39","level":"MUST","text":"Status: Development - `Logger` MUST behave according to the LoggerConfig computed during logger creation.","section":"specification/logs/sdk.md#logger","sectionTitle":"Logger","status":"Stable","source":"spec"},{"id":"afe0db27451f","level":"MUST","text":"If the `LoggerProvider` supports updating the LoggerConfigurator, then upon update the `Logger` MUST be updated to behave according to the new `LoggerConfig`.","section":"specification/logs/sdk.md#logger","sectionTitle":"Logger","status":"Stable","source":"spec"},{"id":"8bc29d63432b","level":"SHOULD","text":"It SHOULD only be possible to create `Logger` instances through a `LoggerProvider` (see API).","section":"specification/logs/sdk.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"5f574e33ceac","level":"MUST","text":"The `LoggerProvider` MUST implement the Get a Logger API.","section":"specification/logs/sdk.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"c7e76f26dab4","level":"MUST","text":"The input provided by the user MUST be used to create an `InstrumentationScope` instance which is stored on the created `Logger`.","section":"specification/logs/sdk.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"71e7b5b11c23","level":"MUST","text":"In the case where an invalid `name` (null or empty string) is specified, a working `Logger` 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.","section":"specification/logs/sdk.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"b99164201116","level":"MUST","text":"Status: Development - The `LoggerProvider` MUST compute the relevant LoggerConfig using the configured LoggerConfigurator, and create a `Logger` whose behavior conforms to that `LoggerConfig`.","section":"specification/logs/sdk.md#logger-creation","sectionTitle":"Logger Creation","status":"Stable","source":"spec"},{"id":"1191361f2cd3","level":"SHOULD","text":"If not explicitly set, the `enabled` parameter SHOULD default to `true` ( i.e. `Logger`s are enabled by default).","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"90e561d6424c","level":"MUST","text":"If a `Logger` is disabled, it MUST behave equivalently to No-op Logger.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"f09afaeeae6e","level":"MUST","text":"If not explicitly set, the `minimum_severity` parameter MUST default to `0`.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"c9277de55967","level":"MUST","text":"If a log record's SeverityNumber is specified (i.e. not `0`) and is less than the configured `minimum_severity`, the log record MUST be dropped by the `Logger`.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"00f887603c1d","level":"MUST","text":"If not explicitly set, the `trace_based` parameter MUST default to `false`.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"79adcb986c89","level":"MUST NOT","text":"If `trace_based` is `false`, log records MUST NOT be affected because of this parameter.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"b40693a820fe","level":"MUST","text":"If `trace_based` is `true`, log records associated with unsampled traces MUST be dropped by the `Logger`.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"11c2a7f1ad2a","level":"MUST","text":"However, the changes MUST be eventually visible.","section":"specification/logs/sdk.md#loggerconfig","sectionTitle":"LoggerConfig","status":"Stable","source":"spec"},{"id":"1f8e9a15ec92","level":"MUST","text":"The function MUST accept the following parameter:","section":"specification/logs/sdk.md#loggerconfigurator","sectionTitle":"LoggerConfigurator","status":"Stable","source":"spec"},{"id":"3d8e5a213d95","level":"MUST","text":"The function MUST return the relevant `LoggerConfig`, or some signal indicating that the default LoggerConfig should be used.","section":"specification/logs/sdk.md#loggerconfigurator","sectionTitle":"LoggerConfigurator","status":"Stable","source":"spec"},{"id":"2217221fc3b9","level":"MAY","text":"This signal MAY be nil, null, empty, or an instance of the default `LoggerConfig` depending on what is idiomatic in the language.","section":"specification/logs/sdk.md#loggerconfigurator","sectionTitle":"LoggerConfigurator","status":"Stable","source":"spec"},{"id":"1338135194b0","level":"MAY","text":"However, implementations MAY provide shorthand or helper functions to accommodate common use cases:","section":"specification/logs/sdk.md#loggerconfigurator","sectionTitle":"LoggerConfigurator","status":"Stable","source":"spec"},{"id":"995889ea1e6c","level":"MUST","text":"A `LoggerProvider` MUST provide a way to allow a Resource to be specified.","section":"specification/logs/sdk.md#loggerprovider","sectionTitle":"LoggerProvider","status":"Stable","source":"spec"},{"id":"5a988e5b706e","level":"SHOULD","text":"If a `Resource` is specified, it SHOULD be associated with all the `LogRecord`s produced by any `Logger` from the `LoggerProvider`.","section":"specification/logs/sdk.md#loggerprovider","sectionTitle":"LoggerProvider","status":"Stable","source":"spec"},{"id":"7fe4476b71b3","level":"SHOULD","text":"The SDK SHOULD allow the creation of multiple independent `LoggerProviders`s.","section":"specification/logs/sdk.md#loggerprovider-creation","sectionTitle":"LoggerProvider Creation","status":"Stable","source":"spec"},{"id":"aa6b370ee2bd","level":"MUST","text":"`LogRecord` attributes MUST adhere to the common rules of attribute limits.","section":"specification/logs/sdk.md#logrecord-limits","sectionTitle":"LogRecord Limits","status":"Stable","source":"spec"},{"id":"e536e41a902e","level":"MUST","text":"If the SDK implements attribute limits it MUST provide a way to change these limits, via a configuration to the `LoggerProvider`, by allowing users to configure individual limits like in the Java example below.","section":"specification/logs/sdk.md#logrecord-limits","sectionTitle":"LogRecord Limits","status":"Stable","source":"spec"},{"id":"820a3394be2d","level":"SHOULD","text":"The options MAY be bundled in a class, which then SHOULD be called `LogRecordLimits`.","section":"specification/logs/sdk.md#logrecord-limits","sectionTitle":"LogRecord Limits","status":"Stable","source":"spec"},{"id":"2bfa187353f1","level":"SHOULD","text":"There SHOULD be a message printed in the SDK's log to indicate to the user that an attribute was discarded due to such a limit.","section":"specification/logs/sdk.md#logrecord-limits","sectionTitle":"LogRecord Limits","status":"Stable","source":"spec"},{"id":"e472ed8abc47","level":"MUST","text":"To prevent excessive logging, the message MUST be printed at most once per `LogRecord` (i.e., not per discarded attribute).","section":"specification/logs/sdk.md#logrecord-limits","sectionTitle":"LogRecord Limits","status":"Stable","source":"spec"},{"id":"0f530012db14","level":"MUST","text":"Each implementation MUST document the concurrency characteristics the SDK requires of the exporter.","section":"specification/logs/sdk.md#logrecordexporter","sectionTitle":"LogRecordExporter","status":"Stable","source":"spec"},{"id":"32cab405c09b","level":"MUST","text":"A `LogRecordExporter` MUST support the following functions:","section":"specification/logs/sdk.md#logrecordexporter-operations","sectionTitle":"LogRecordExporter operations","status":"Stable","source":"spec"},{"id":"eef2f7f6f013","level":"MUST","text":"The SDK MUST allow each pipeline to end with an individual exporter.","section":"specification/logs/sdk.md#logrecordprocessor","sectionTitle":"LogRecordProcessor","status":"Stable","source":"spec"},{"id":"1e2084840320","level":"MUST","text":"The SDK MUST allow users to implement and configure custom processors and decorate built-in processors for advanced scenarios such as enriching with attributes.","section":"specification/logs/sdk.md#logrecordprocessor","sectionTitle":"LogRecordProcessor","status":"Stable","source":"spec"},{"id":"cc85ff0fc503","level":"MUST","text":"All language implementations of OpenTelemetry MUST provide an SDK.","section":"specification/logs/sdk.md#logs-sdk","sectionTitle":"Logs SDK","status":"Stable","source":"spec"},{"id":"6c1d3f476e30","level":"SHOULD NOT","text":"This method is called synchronously on the thread that emitted the `LogRecord`, therefore it SHOULD NOT block or throw exceptions.","section":"specification/logs/sdk.md#onemit","sectionTitle":"OnEmit","status":"Stable","source":"spec"},{"id":"3cccfbb5115a","level":"MUST","text":"For a `LogRecordProcessor` registered directly on SDK `LoggerProvider`, the `logRecord` mutations MUST be visible in next registered processors.","section":"specification/logs/sdk.md#onemit","sectionTitle":"OnEmit","status":"Stable","source":"spec"},{"id":"77326a41d665","level":"OPTIONAL","text":"However, it is OPTIONAL for `ReadWriteLogRecord` to be concurrent-safe.","section":"specification/logs/sdk.md#onemit","sectionTitle":"OnEmit","status":"Stable","source":"spec"},{"id":"1e7e58ca0aeb","level":"SHOULD","text":"To avoid such race conditions, implementations SHOULD recommended to users that a clone of `logRecord` be used for any concurrent processing, such as in a batching processor.","section":"specification/logs/sdk.md#onemit","sectionTitle":"OnEmit","status":"Stable","source":"spec"},{"id":"7617525ba798","level":"MUST","text":"A function receiving this as an argument MUST be able to access all the information added to the LogRecord.","section":"specification/logs/sdk.md#readablelogrecord","sectionTitle":"ReadableLogRecord","status":"Stable","source":"spec"},{"id":"23e75b52d7ac","level":"MUST","text":"It MUST also be able to access the Instrumentation Scope and Resource information (implicitly) associated with the `LogRecord`.","section":"specification/logs/sdk.md#readablelogrecord","sectionTitle":"ReadableLogRecord","status":"Stable","source":"spec"},{"id":"db454566bd88","level":"MUST","text":"The trace context fields MUST be populated from the resolved `Context` (either the explicitly passed `Context` or the current `Context`) when emitted.","section":"specification/logs/sdk.md#readablelogrecord","sectionTitle":"ReadableLogRecord","status":"Stable","source":"spec"},{"id":"dae6232900af","level":"MUST","text":"Counts for attributes due to collection limits MUST be available for exporters to report as described in the transformation to non-OTLP formats specification.","section":"specification/logs/sdk.md#readablelogrecord","sectionTitle":"ReadableLogRecord","status":"Stable","source":"spec"},{"id":"61ea27da12ad","level":"MUST","text":"A function receiving this as an argument MUST additionally be able to modify the following information added to the LogRecord:","section":"specification/logs/sdk.md#readwritelogrecord","sectionTitle":"ReadWriteLogRecord","status":"Stable","source":"spec"},{"id":"2f120d9756d6","level":"MAY","text":"The SDK MAY provide an operation that makes a deep clone of a `ReadWriteLogRecord`.","section":"specification/logs/sdk.md#readwritelogrecord","sectionTitle":"ReadWriteLogRecord","status":"Stable","source":"spec"},{"id":"ece7d0861677","level":"SHOULD","text":"The Logs SDK SHOULD support SDK self-observability.","section":"specification/logs/sdk.md#self-observability","sectionTitle":"Self-observability","status":"Stable","source":"spec"},{"id":"2d624dbfd53b","level":"MUST","text":"`Shutdown` MUST be called only once for each `LoggerProvider` instance.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"9e7e39685c94","level":"SHOULD","text":"SDKs SHOULD return a valid no-op `Logger` for these calls, if possible.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"6c4284d34e03","level":"SHOULD","text":"`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"b0d3a1ed8669","level":"SHOULD","text":"`Shutdown` SHOULD complete or abort within some timeout.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"6690b371cb8f","level":"MAY","text":"`Shutdown` MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"3cb992faead5","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the shutdown timeout configurable.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"5e3ed71d5dbc","level":"MUST","text":"`Shutdown` MUST be implemented by invoking `Shutdown` on all registered LogRecordProcessors.","section":"specification/logs/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"929a8c215556","level":"SHOULD","text":"`Shutdown` SHOULD be called only once for each `LogRecordProcessor` instance.","section":"specification/logs/sdk.md#shutdown-1","sectionTitle":"ShutDown","status":"Stable","source":"spec"},{"id":"14f07801a319","level":"SHOULD","text":"SDKs SHOULD ignore these calls gracefully, if possible.","section":"specification/logs/sdk.md#shutdown-1","sectionTitle":"ShutDown","status":"Stable","source":"spec"},{"id":"8e5d4ec93457","level":"SHOULD","text":"`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/logs/sdk.md#shutdown-1","sectionTitle":"ShutDown","status":"Stable","source":"spec"},{"id":"f1dd5c865159","level":"MUST","text":"`Shutdown` MUST include the effects of `ForceFlush`.","section":"specification/logs/sdk.md#shutdown-1","sectionTitle":"ShutDown","status":"Stable","source":"spec"},{"id":"ec9b300e57b1","level":"SHOULD","text":"`Shutdown` SHOULD complete or abort within some timeout.","section":"specification/logs/sdk.md#shutdown-1","sectionTitle":"ShutDown","status":"Stable","source":"spec"},{"id":"d4ed803e5a22","level":"SHOULD","text":"Shutdown SHOULD be called only once for each `LogRecordExporter` instance.","section":"specification/logs/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"0381cd3af77b","level":"SHOULD","text":"After the call to `Shutdown` subsequent calls to `Export` are not allowed and SHOULD return a Failure result.","section":"specification/logs/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"7ced5d8cf810","level":"SHOULD NOT","text":"`Shutdown` SHOULD NOT block indefinitely (e.g. if it attempts to flush the data and the destination is unavailable).","section":"specification/logs/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"a6426660e8de","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the shutdown timeout configurable.","section":"specification/logs/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"1cdea9234691","level":"MUST","text":"The processor MUST synchronize calls to `LogRecordExporter`'s `Export` to make sure that they are not invoked concurrently.","section":"specification/logs/sdk.md#simple-processor","sectionTitle":"Simple processor","status":"Stable","source":"spec"},{"id":"ea32af0d878f","level":"MUST","text":"They also MUST communicate in which version they will be removed, either in terms of a concrete version number or the date of a release, like: \"the first release after 2023-08-01\".","section":"specification/maturity-levels.md#deprecated","sectionTitle":"Deprecated","status":"Unspecified","source":"spec"},{"id":"3bdb7c0b62ed","level":"SHOULD NOT","text":"The component SHOULD NOT be used in production.","section":"specification/maturity-levels.md#development","sectionTitle":"Development","status":"Unspecified","source":"spec"},{"id":"4709f8a0c5c1","level":"MAY","text":"The component MAY be removed without prior notice.","section":"specification/maturity-levels.md#development","sectionTitle":"Development","status":"Unspecified","source":"spec"},{"id":"6b766cc7b659","level":"MUST","text":"Deliverables of a SIG MUST have a declared maturity level, established by SIG maintainers, likely with the input of the code owners.","section":"specification/maturity-levels.md#maturity-levels","sectionTitle":"Maturity levels","status":"Unspecified","source":"spec"},{"id":"e9224b8535dd","level":"SHOULD NOT","text":"Components SHOULD NOT be marked as [Stable][] if their user-visible interfaces are not [Stable][].","section":"specification/maturity-levels.md#maturity-levels","sectionTitle":"Maturity levels","status":"Unspecified","source":"spec"},{"id":"59c9245af2bc","level":"SHOULD","text":"Issues and pull requests for Unmaintained components SHOULD be labeled as such.","section":"specification/maturity-levels.md#unmaintained","sectionTitle":"Unmaintained","status":"Unspecified","source":"spec"},{"id":"8e460c923623","level":"MAY","text":"After 6 months of being Unmaintained, these components MAY be [Deprecated][].","section":"specification/maturity-levels.md#unmaintained","sectionTitle":"Unmaintained","status":"Unspecified","source":"spec"},{"id":"0f738122ad52","level":"SHOULD NOT","text":"This API SHOULD NOT return a value (it MAY return a dummy value if required by certain programming languages or systems, for example `null`, `undefined`).","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"d4681382e9df","level":"MUST","text":"This API MUST accept the following parameter:","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"38fc8a1957f7","level":"SHOULD","text":"If possible, this API SHOULD be structured so a user is obligated to provide this parameter.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"87837e1872f5","level":"MUST","text":"If it is not possible to structurally enforce this obligation, this API MUST be documented in a way to communicate to users that this parameter is needed.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"3563395b4ef4","level":"SHOULD","text":"This API SHOULD be documented in a way to communicate to users that this value is expected to be non-negative.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"fd363ce10b4c","level":"SHOULD NOT","text":"This API SHOULD NOT validate this value, that is left to implementations of the API.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"e77338ff7029","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of attributes, including none.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"f0f58dd758bb","level":"MAY","text":"The OpenTelemetry API authors MAY decide to allow flexible attributes to be passed in as arguments.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"58b134124748","level":"MAY","text":"If the attribute names and types are provided during the counter creation, the OpenTelemetry API authors MAY allow attribute values to be passed in using a more efficient way (e.g. strong typed struct allocated on the callstack, tuple).","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"c6cba7cda2e6","level":"MUST","text":"The API MUST allow callers to provide flexible attributes at invocation time rather than having to register all the possible attribute names during the instrument creation.","section":"specification/metrics/api.md#add","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"ca81b863c52c","level":"SHOULD NOT","text":"This API SHOULD NOT return a value (it MAY return a dummy value if required by certain programming languages or systems, for example `null`, `undefined`).","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"7d1db439fe94","level":"MUST","text":"This API MUST accept the following parameter:","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"d338fe86f4d6","level":"SHOULD","text":"If possible, this API SHOULD be structured so a user is obligated to provide this parameter.","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"8b5a1951f8f3","level":"MUST","text":"If it is not possible to structurally enforce this obligation, this API MUST be documented in a way to communicate to users that this parameter is needed.","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"fc49bc38d156","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of attributes, including none.","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"f34b9f459f81","level":"MAY","text":"OpenTelemetry API authors MAY decide to allow flexible attributes to be passed in as individual arguments.","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"fb74d10a64c8","level":"MAY","text":"OpenTelemetry API authors MAY allow attribute values to be passed in using a more efficient way (e.g. strong typed struct allocated on the callstack, tuple).","section":"specification/metrics/api.md#add-1","sectionTitle":"Add","status":"Stable","source":"spec"},{"id":"d8fd5ec3e6aa","level":"MUST NOT","text":"There MUST NOT be any API for creating an Asynchronous Counter other than with a `Meter`.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"4d818949917f","level":"MAY","text":"This MAY be called `CreateObservableCounter`.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"14bcb44e4201","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateUInt64ObservableCounter`, `CreateDoubleObservableCounter`, `CreateObservableCounter<UInt64>`, `CreateObservableCounter<double>`.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"7f17a1819bef","level":"MAY","text":"OpenTelemetry API authors MAY decide what is the idiomatic approach.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"d1afe7339145","level":"MAY","text":"If it happens, OpenTelemetry SDK authors MAY decide how to handle it in the SDK.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"9d6faf407501","level":"MAY","text":"For example, during the callback invocation if two measurements `value=1, attributes={pid:4, bitness:64}` and `value=2, attributes={pid:4, bitness:64}` are reported, OpenTelemetry SDK authors MAY decide to simply let them pass through (so the downstream consumer can handle duplication), drop the entire data, pick the last one, or something else.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"046ce03cec92","level":"MUST","text":"The API MUST treat observations from a single callback as logically taking place at a single instant, such that when recorded, observations from a single callback MUST be reported with identical timestamps.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"15a196081350","level":"SHOULD","text":"The API SHOULD provide some way to pass `state` to the callback.","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"f2ac66c85dbf","level":"MAY","text":"OpenTelemetry API authors MAY decide what is the idiomatic approach (e.g. it could be an additional parameter to the callback function, or captured by the lambda closure, or something else).","section":"specification/metrics/api.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter creation","status":"Stable","source":"spec"},{"id":"ea057d2c3161","level":"MUST NOT","text":"There MUST NOT be any API for creating an Asynchronous Gauge other than with a `Meter`.","section":"specification/metrics/api.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge creation","status":"Stable","source":"spec"},{"id":"f6fcdc5539b7","level":"MAY","text":"This MAY be called `CreateObservableGauge`.","section":"specification/metrics/api.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge creation","status":"Stable","source":"spec"},{"id":"1f72f793c199","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateUInt64ObservableGauge`, `CreateDoubleObservableGauge`, `CreateObservableGauge<UInt64>`, `CreateObservableGauge<double>`.","section":"specification/metrics/api.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge creation","status":"Stable","source":"spec"},{"id":"f767364d0f4c","level":"MUST","text":"The API to construct asynchronous instruments MUST accept the following parameters:","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"7dc85a05cba8","level":"SHOULD","text":"If possible, the API SHOULD be structured so a user is obligated to provide this parameter.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"0f04988fc9c8","level":"MUST","text":"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.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"719fdbe88119","level":"SHOULD","text":"The API SHOULD be documented in a way to communicate to users that the `name` parameter needs to conform to the instrument name syntax.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"b8282fc9a969","level":"SHOULD NOT","text":"The API SHOULD NOT validate the `name`, that is left to implementations of the API.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"626702ffb38a","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept a `unit`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"4158833ca14c","level":"MUST","text":"Meaning, the API MUST accept a case-sensitive string that supports ASCII character encoding and can hold at least 63 characters.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"e3d77fe4b656","level":"SHOULD NOT","text":"The API SHOULD NOT validate the `unit`.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"6feda7f1819c","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept a `description`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"f28912452c04","level":"MUST","text":"Meaning, the API MUST accept a string that supports at least BMP (Unicode Plane 0)#BasicMultilingualPlane) encoded characters and hold at least 1023 characters.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"f8b123d161ff","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept `advisory` parameters, but MUST NOT obligate the user to provide it.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"6a5db68e9e64","level":"SHOULD NOT","text":"The API SHOULD NOT validate `advisory` parameters.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"0ec876208b53","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of `callback` functions, including none.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"b96dbf59ec16","level":"MUST","text":"The API MUST support creation of asynchronous instruments by passing zero or more `callback` functions to be permanently registered to the newly created instrument.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"91299442e4c1","level":"SHOULD","text":"The API SHOULD support registration of `callback` functions associated with asynchronous instruments after they are created.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"b4dc471c59e6","level":"MUST","text":"Where the API supports registration of `callback` functions after asynchronous instrumentation creation, the user MUST be able to undo registration of the specific callback after its registration by some means.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"dc5a626f8788","level":"MUST","text":"Every currently registered Callback associated with a set of instruments MUST be evaluated exactly once during collection prior to reading data for that instrument set.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"024047521136","level":"MUST","text":"Callback functions MUST be documented as follows for the end user:","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"148278c7c8cd","level":"SHOULD","text":"Callback functions SHOULD be reentrant safe.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"a8ac59f691a6","level":"SHOULD NOT","text":"Callback functions SHOULD NOT take an indefinite amount of time.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"a50c4cabc8e1","level":"SHOULD NOT","text":"Callback functions SHOULD NOT make duplicate observations (more than one `Measurement` with the same `attributes`) across all registered callbacks.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"f54ffe65fef4","level":"MAY","text":"OpenTelemetry API authors MAY decide what is the idiomatic approach for capturing measurements from callback functions.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"7e81a9678ca4","level":"MUST","text":"Callbacks registered at the time of instrument creation MUST apply to the single instruments which is under construction.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"2b6c1fcc7ddb","level":"MAY","text":"Callbacks registered after the time of instrument creation MAY be associated with multiple instruments.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"9f149c0f80fa","level":"MUST","text":"Idiomatic APIs for multiple-instrument Callbacks MUST distinguish the instrument associated with each observed `Measurement` value.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"804b9753a9aa","level":"MUST","text":"Multiple-instrument Callbacks MUST be associated at the time of registration with a declared set of asynchronous instruments from the same `Meter` instance.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"156b2ef40998","level":"MUST","text":"The API MUST treat observations from a single Callback as logically taking place at a single instant, such that when recorded, observations from a single callback MUST be reported with identical timestamps.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"7400bb98a071","level":"SHOULD","text":"The API SHOULD provide some way to pass `state` to the callback.","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"78ef26cbca43","level":"MAY","text":"OpenTelemetry API authors MAY decide what is the idiomatic approach (e.g. it could be an additional parameter to the callback function, or captured by the lambda closure, or something else).","section":"specification/metrics/api.md#asynchronous-instrument-api","sectionTitle":"Asynchronous Instrument API","status":"Stable","source":"spec"},{"id":"088190f19353","level":"MUST NOT","text":"There MUST NOT be any API for creating an Asynchronous UpDownCounter other than with a `Meter`.","section":"specification/metrics/api.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter creation","status":"Stable","source":"spec"},{"id":"0dc512ca7793","level":"MAY","text":"This MAY be called `CreateObservableUpDownCounter`.","section":"specification/metrics/api.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter creation","status":"Stable","source":"spec"},{"id":"7b182fe600d5","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateUInt64ObservableUpDownCounter`, `CreateDoubleObservableUpDownCounter`, `CreateObservableUpDownCounter<UInt64>`, `CreateObservableUpDownCounter<double>`.","section":"specification/metrics/api.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter creation","status":"Stable","source":"spec"},{"id":"d2ba0c261540","level":"MUST","text":"This API MUST accept the following parameter:","section":"specification/metrics/api.md#bind","sectionTitle":"Bind","status":"Stable","source":"spec"},{"id":"79954e8f18fa","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of attributes, including none.","section":"specification/metrics/api.md#bind","sectionTitle":"Bind","status":"Stable","source":"spec"},{"id":"f5f37a8e682f","level":"MUST","text":"This API MUST return a language-idiomatic type representing the instrument bound to those attributes.","section":"specification/metrics/api.md#bind","sectionTitle":"Bind","status":"Stable","source":"spec"},{"id":"394a6068a4ba","level":"MUST","text":"The returned bound instrument MUST support the instrument's core recording operation.","section":"specification/metrics/api.md#bind","sectionTitle":"Bind","status":"Stable","source":"spec"},{"id":"dd2a0a9b73f8","level":"MAY","text":"This MAY be achieved by introducing a dedicated bound instrument type, or by reusing the existing instrument interface.","section":"specification/metrics/api.md#bind","sectionTitle":"Bind","status":"Stable","source":"spec"},{"id":"1a329d7c53f9","level":"MUST","text":"If the existing instrument interface is reused, the `Bind` API MUST be documented to communicate to users that invoking attribute-bearing recording operations on the returned bound instrument negates the performance benefits of binding.","section":"specification/metrics/api.md#bind","sectionTitle":"Bind","status":"Stable","source":"spec"},{"id":"4b6c4a4b48bd","level":"SHOULD","text":"All the metrics components SHOULD allow new APIs to be added to existing components without introducing breaking changes.","section":"specification/metrics/api.md#compatibility-requirements","sectionTitle":"Compatibility requirements","status":"Stable","source":"spec"},{"id":"6301df63b718","level":"SHOULD","text":"All the metrics APIs SHOULD allow optional parameter(s) to be added to existing APIs without introducing breaking changes, if possible.","section":"specification/metrics/api.md#compatibility-requirements","sectionTitle":"Compatibility requirements","status":"Stable","source":"spec"},{"id":"f9eec3f30112","level":"MUST","text":"MeterProvider - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/metrics/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"c0783d6d4906","level":"MUST","text":"Meter - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/metrics/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"b002222eb138","level":"MUST","text":"Instrument - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/metrics/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"af309a41d9da","level":"MUST NOT","text":"There MUST NOT be any API for creating a `Counter` other than with a `Meter`.","section":"specification/metrics/api.md#counter-creation","sectionTitle":"Counter creation","status":"Stable","source":"spec"},{"id":"c371c6eff189","level":"MAY","text":"This MAY be called `CreateCounter`.","section":"specification/metrics/api.md#counter-creation","sectionTitle":"Counter creation","status":"Stable","source":"spec"},{"id":"870f077c57dc","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateUInt64Counter`, `CreateDoubleCounter`, `CreateCounter<UInt64>`, `CreateCounter<double>`.","section":"specification/metrics/api.md#counter-creation","sectionTitle":"Counter creation","status":"Stable","source":"spec"},{"id":"0394f91fbd3d","level":"SHOULD","text":"To help users avoid performing computationally expensive operations when recording measurements, synchronous instruments SHOULD provide this `Enabled` API.","section":"specification/metrics/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"344a21cd2c2d","level":"MUST","text":"Parameters can be added in the future, therefore, the API MUST be structured in a way for parameters to be added.","section":"specification/metrics/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"53f2dcb2e853","level":"MUST","text":"This API MUST return a language idiomatic boolean type.","section":"specification/metrics/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"7b646da38a90","level":"SHOULD","text":"The API SHOULD be documented that instrumentation authors needs to call this API each time they record a measurement to ensure they have the most up-to-date response.","section":"specification/metrics/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"c152e63de24f","level":"MUST NOT","text":"There MUST NOT be any API for creating a `Gauge` other than with a `Meter`.","section":"specification/metrics/api.md#gauge-creation","sectionTitle":"Gauge creation","status":"Stable","source":"spec"},{"id":"ad5cdd8d05b2","level":"MAY","text":"This MAY be called `CreateGauge`.","section":"specification/metrics/api.md#gauge-creation","sectionTitle":"Gauge creation","status":"Stable","source":"spec"},{"id":"aba255effb34","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateUInt64Gauge`, `CreateDoubleGauge`, `CreateGauge<UInt64>`, `CreateGauge<double>`.","section":"specification/metrics/api.md#gauge-creation","sectionTitle":"Gauge creation","status":"Stable","source":"spec"},{"id":"fe7b956ba4d8","level":"SHOULD","text":"All synchronous instruments SHOULD provide functions to:","section":"specification/metrics/api.md#general-operations","sectionTitle":"General operations","status":"Stable","source":"spec"},{"id":"ebf91cfdc274","level":"MAY","text":"All synchronous instruments MAY provide:","section":"specification/metrics/api.md#general-operations","sectionTitle":"General operations","status":"Stable","source":"spec"},{"id":"7f37c20f9197","level":"MUST","text":"This API MUST accept the following parameters:","section":"specification/metrics/api.md#get-a-meter","sectionTitle":"Get a Meter","status":"Stable","source":"spec"},{"id":"7bc7dd83d7d7","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept a `version`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/api.md#get-a-meter","sectionTitle":"Get a Meter","status":"Stable","source":"spec"},{"id":"72e6ce6dbb5a","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept a `schemaurl`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/api.md#get-a-meter","sectionTitle":"Get a Meter","status":"Stable","source":"spec"},{"id":"1beaeb62b57e","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of attributes, including none.","section":"specification/metrics/api.md#get-a-meter","sectionTitle":"Get a Meter","status":"Stable","source":"spec"},{"id":"03e85f9cf6fd","level":"MUST NOT","text":"There MUST NOT be any API for creating a `Histogram` other than with a `Meter`.","section":"specification/metrics/api.md#histogram-creation","sectionTitle":"Histogram creation","status":"Stable","source":"spec"},{"id":"01f9e57283a5","level":"MAY","text":"This MAY be called `CreateHistogram`.","section":"specification/metrics/api.md#histogram-creation","sectionTitle":"Histogram creation","status":"Stable","source":"spec"},{"id":"63fda8ea0918","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateUInt64Histogram`, `CreateDoubleHistogram`, `CreateHistogram<UInt64>`, `CreateHistogram<double>`.","section":"specification/metrics/api.md#histogram-creation","sectionTitle":"Histogram creation","status":"Stable","source":"spec"},{"id":"6c58eead83de","level":"SHOULD","text":"Language-level features such as the distinction between integer and floating point numbers SHOULD be considered as identifying.","section":"specification/metrics/api.md#instrument","sectionTitle":"Instrument","status":"Stable","source":"spec"},{"id":"e9b1aadbfd9d","level":"MAY","text":"They differ from other parameters in that Implementations MAY ignore `advisory` parameters.","section":"specification/metrics/api.md#instrument-advisory-parameters","sectionTitle":"Instrument advisory parameters","status":"Stable","source":"spec"},{"id":"42b3f0c68ee3","level":"MUST","text":"OpenTelemetry SDKs MUST handle `advisory` parameters as described here.","section":"specification/metrics/api.md#instrument-advisory-parameters","sectionTitle":"Instrument advisory parameters","status":"Stable","source":"spec"},{"id":"3056872230da","level":"MUST","text":"The API MUST treat it as an opaque string.","section":"specification/metrics/api.md#instrument-description","sectionTitle":"Instrument description","status":"Stable","source":"spec"},{"id":"3d3b11541816","level":"MUST","text":"It MUST support BMP (Unicode Plane 0)#BasicMultilingualPlane), which is basically only the first three bytes of UTF-8 (or `utf8mb3`).","section":"specification/metrics/api.md#instrument-description","sectionTitle":"Instrument description","status":"Stable","source":"spec"},{"id":"cae9c4063e36","level":"MAY","text":"OpenTelemetry API authors MAY decide if they want to support more Unicode Planes).","section":"specification/metrics/api.md#instrument-description","sectionTitle":"Instrument description","status":"Stable","source":"spec"},{"id":"7e0cc8dd622e","level":"MUST","text":"It MUST support at least 1023 characters.","section":"specification/metrics/api.md#instrument-description","sectionTitle":"Instrument description","status":"Stable","source":"spec"},{"id":"4e7177ec5f30","level":"MAY","text":"OpenTelemetry API authors MAY decide if they want to support more.","section":"specification/metrics/api.md#instrument-description","sectionTitle":"Instrument description","status":"Stable","source":"spec"},{"id":"8a2def08e852","level":"SHOULD","text":"The API SHOULD treat it as an opaque string.","section":"specification/metrics/api.md#instrument-unit","sectionTitle":"Instrument unit","status":"Stable","source":"spec"},{"id":"a92c05c388bf","level":"MUST","text":"It MUST be case-sensitive (e.g. `kb` and `kB` are different units), ASCII string.","section":"specification/metrics/api.md#instrument-unit","sectionTitle":"Instrument unit","status":"Stable","source":"spec"},{"id":"a5419805c972","level":"SHOULD NOT","text":"Note: `Meter` SHOULD NOT be responsible for the configuration.","section":"specification/metrics/api.md#meter","sectionTitle":"Meter","status":"Stable","source":"spec"},{"id":"4ae1eba961fb","level":"MUST","text":"The `Meter` MUST provide functions to create new Instruments:","section":"specification/metrics/api.md#meter-operations","sectionTitle":"Meter operations","status":"Stable","source":"spec"},{"id":"5deabf45c922","level":"SHOULD","text":"Thus, the API SHOULD provide a way to set/register and access a global default `MeterProvider`.","section":"specification/metrics/api.md#meterprovider","sectionTitle":"MeterProvider","status":"Stable","source":"spec"},{"id":"bc26ecd0d80a","level":"MUST","text":"The `MeterProvider` MUST provide the following functions:","section":"specification/metrics/api.md#meterprovider-operations","sectionTitle":"MeterProvider operations","status":"Stable","source":"spec"},{"id":"7a721946c6c9","level":"MAY","text":"The Metrics API MAY support an interface allowing the use of multiple instruments from a single registered Callback.","section":"specification/metrics/api.md#multiple-instrument-callbacks","sectionTitle":"Multiple-instrument callbacks","status":"Stable","source":"spec"},{"id":"1a924155559c","level":"SHOULD","text":"The API to register a new Callback SHOULD accept:","section":"specification/metrics/api.md#multiple-instrument-callbacks","sectionTitle":"Multiple-instrument callbacks","status":"Stable","source":"spec"},{"id":"92bb1f4c8b9d","level":"RECOMMENDED","text":"It is RECOMMENDED that the API authors use one of the following forms for the `callback` function:","section":"specification/metrics/api.md#multiple-instrument-callbacks","sectionTitle":"Multiple-instrument callbacks","status":"Stable","source":"spec"},{"id":"3aac9297cb4d","level":"SHOULD NOT","text":"This API SHOULD NOT return a value (it MAY return a dummy value if required by certain programming languages or systems, for example `null`, `undefined`).","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"f4e39a1afd65","level":"MUST","text":"This API MUST accept the following parameter:","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"2b934b615878","level":"SHOULD","text":"If possible, this API SHOULD be structured so a user is obligated to provide this parameter.","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"397a06dac89c","level":"MUST","text":"If it is not possible to structurally enforce this obligation, this API MUST be documented in a way to communicate to users that this parameter is needed.","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"3af1f789b539","level":"SHOULD","text":"This API SHOULD be documented in a way to communicate to users that this value is expected to be non-negative.","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"ba82211d74d4","level":"SHOULD NOT","text":"This API SHOULD NOT validate this value, that is left to implementations of the API.","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"df9253918e92","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of attributes, including none.","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"3809fbfa6398","level":"MAY","text":"OpenTelemetry API authors MAY decide to allow flexible attributes to be passed in as individual arguments.","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"1c266b1daad3","level":"MAY","text":"OpenTelemetry API authors MAY allow attribute values to be passed in using a more efficient way (e.g. strong typed struct allocated on the callstack, tuple).","section":"specification/metrics/api.md#record","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"87fc26268bed","level":"SHOULD NOT","text":"This API SHOULD NOT return a value (it MAY return a dummy value if required by certain programming languages or systems, for example `null`, `undefined`).","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"f053a8462d33","level":"MUST","text":"This API MUST accept the following parameter:","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"ebb69bdc1305","level":"SHOULD","text":"If possible, this API SHOULD be structured so a user is obligated to provide this parameter.","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"c55946daf4c8","level":"MUST","text":"If it is not possible to structurally enforce this obligation, this API MUST be documented in a way to communicate to users that this parameter is needed.","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"b80031ffc870","level":"MUST","text":"Therefore, this API MUST be structured to accept a variable number of attributes, including none.","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"05386ca14487","level":"MAY","text":"The OpenTelemetry API authors MAY decide to allow flexible attributes to be passed in as arguments.","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"1a0e34b202bb","level":"MAY","text":"If the attribute names and types are provided during the gauge creation, the OpenTelemetry API authors MAY allow attribute values to be passed in using a more efficient way (e.g. strong typed struct allocated on the callstack, tuple).","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"9961822b80f0","level":"MUST","text":"The API MUST allow callers to provide flexible attributes at invocation time rather than having to register all the possible attribute names during the instrument creation.","section":"specification/metrics/api.md#record-1","sectionTitle":"Record","status":"Stable","source":"spec"},{"id":"937d5cfa692e","level":"MUST","text":"The API to construct synchronous instruments MUST accept the following parameters:","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"9c4f7e856727","level":"SHOULD","text":"If possible, the API SHOULD be structured so a user is obligated to provide this parameter.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"e8cb0aa327c0","level":"MUST","text":"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.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"4c5e4af79d9b","level":"SHOULD","text":"The API SHOULD be documented in a way to communicate to users that the `name` parameter needs to conform to the instrument name syntax.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"14596b848d00","level":"SHOULD NOT","text":"The API SHOULD NOT validate the `name`; that is left to implementations of the API, like the SDK.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"52a7e9650502","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept a `unit`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"3f3ee1aff625","level":"MUST","text":"Meaning, the API MUST accept a case-sensitive string that supports ASCII character encoding and can hold at least 63 characters.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"b501ba477dbc","level":"SHOULD NOT","text":"The API SHOULD NOT validate the `unit`.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"6bd4148f7f2f","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept a `description`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"9c062f02da34","level":"MUST","text":"Meaning, the API MUST accept a string that supports at least BMP (Unicode Plane 0)#BasicMultilingualPlane) encoded characters and hold at least 1023 characters.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"0369c78d93ec","level":"MUST NOT","text":"Therefore, this API needs to be structured to accept `advisory` parameters, but MUST NOT obligate the user to provide it.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"9ef3ac789c14","level":"SHOULD NOT","text":"The API SHOULD NOT validate `advisory` parameters.","section":"specification/metrics/api.md#synchronous-instrument-api","sectionTitle":"Synchronous Instrument API","status":"Stable","source":"spec"},{"id":"1876a55ce72a","level":"MUST NOT","text":"There MUST NOT be any API for creating an `UpDownCounter` other than with a `Meter`.","section":"specification/metrics/api.md#updowncounter-creation","sectionTitle":"UpDownCounter creation","status":"Stable","source":"spec"},{"id":"2e790376e4e7","level":"MAY","text":"This MAY be called `CreateUpDownCounter`.","section":"specification/metrics/api.md#updowncounter-creation","sectionTitle":"UpDownCounter creation","status":"Stable","source":"spec"},{"id":"0ab7019b9c1b","level":"MAY","text":"If strong type is desired, OpenTelemetry API authors MAY decide the language idiomatic name(s), for example `CreateInt64UpDownCounter`, `CreateDoubleUpDownCounter`, `CreateUpDownCounter<Int64>`, `CreateUpDownCounter<double>`.","section":"specification/metrics/api.md#updowncounter-creation","sectionTitle":"UpDownCounter creation","status":"Stable","source":"spec"},{"id":"0f1221e2aceb","level":"MAY","text":"The methods in this section MAY be used at all scales, although they are definitely useful for positive scales.","section":"specification/metrics/data-model.md#all-scales-use-the-logarithm-function","sectionTitle":"All Scales: Use the Logarithm Function","status":"Mixed","source":"spec"},{"id":"2d8d79b3e350","level":"SHOULD","text":"Since it is relatively simple to check for exact powers of two, implementations SHOULD apply such a special case:","section":"specification/metrics/data-model.md#all-scales-use-the-logarithm-function","sectionTitle":"All Scales: Use the Logarithm Function","status":"Mixed","source":"spec"},{"id":"9f1d19c35194","level":"MAY","text":"Consumers MAY round the unrepresentable boundary of a partially representable bucket index to the nearest representable value.","section":"specification/metrics/data-model.md#exponentialhistogram-consumer-recommendations","sectionTitle":"ExponentialHistogram: Consumer Recommendations","status":"Mixed","source":"spec"},{"id":"75630656c30a","level":"SHOULD","text":"Consumers SHOULD reject ExponentialHistogram data with `scale` and bucket indexes that overflow or underflow this representation.","section":"specification/metrics/data-model.md#exponentialhistogram-consumer-recommendations","sectionTitle":"ExponentialHistogram: Consumer Recommendations","status":"Mixed","source":"spec"},{"id":"c075e65f13f0","level":"SHOULD","text":"Consumers that reject such data SHOULD warn the user through error logging that out-of-range data was received.","section":"specification/metrics/data-model.md#exponentialhistogram-consumer-recommendations","sectionTitle":"ExponentialHistogram: Consumer Recommendations","status":"Mixed","source":"spec"},{"id":"a2a122c9cbe7","level":"SHOULD NOT","text":"It serves as an indicator that a previously present timeseries was removed and that this timeseries SHOULD NOT be returned in queries after such an indicator was received.","section":"specification/metrics/data-model.md#no-recorded-value","sectionTitle":"No recorded value","status":"Mixed","source":"spec"},{"id":"7e9e510648fe","level":"SHOULD","text":"If this flag is set, all other data point properties except attributes, time stamps, or time windows, SHOULD be ignored.","section":"specification/metrics/data-model.md#no-recorded-value","sectionTitle":"No recorded value","status":"Mixed","source":"spec"},{"id":"fac9a0992d63","level":"MAY","text":"Consumers MAY reject OpenTelemetry Metrics data containing semantic errors (i.e., more than one `Metric` identity for a given `name`, `Resource`, and `Scope`).","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-consumer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Consumer recommendations","status":"Mixed","source":"spec"},{"id":"ca69afbd1367","level":"SHOULD","text":"Producers SHOULD prevent the presence of multiple `Metric` identities for a given `name` with the same `Resource` and `Scope` attributes.","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-producer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Producer recommendations","status":"Mixed","source":"spec"},{"id":"a8e7f8b10953","level":"MAY","text":"Producers MAY be able to remediate the problem, depending on whether they are an SDK or a downstream processor:","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-producer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Producer recommendations","status":"Mixed","source":"spec"},{"id":"1cd92cf322b3","level":"SHOULD","text":"If the potential conflict involves a non-identifying property (i.e., `description`), the producer SHOULD choose the longer string.","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-producer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Producer recommendations","status":"Mixed","source":"spec"},{"id":"f9b4330d3342","level":"SHOULD","text":"If the potential conflict involves similar but disagreeing units (e.g., \"ms\" and \"s\"), an implementation MAY convert units to avoid semantic errors; otherwise an implementation SHOULD inform the user of a semantic error and pass through conflicting data.","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-producer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Producer recommendations","status":"Mixed","source":"spec"},{"id":"ea7bf5cb63fd","level":"SHOULD","text":"If the potential conflict involves an `AggregationTemporality` property, an implementation MAY convert temporality using a Cumulative-to-Delta or a Delta-to-Cumulative transformation; otherwise, an implementation SHOULD inform the user of a semantic error and pass through conflicting data.","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-producer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Producer recommendations","status":"Mixed","source":"spec"},{"id":"e15790d0a5a6","level":"SHOULD","text":"Generally, for potential conflicts involving an identifying property (i.e., all properties except `description`), the producer SHOULD inform the user of a semantic error and pass through conflicting data.","section":"specification/metrics/data-model.md#opentelemetry-protocol-data-model-producer-recommendations","sectionTitle":"OpenTelemetry Protocol data model: Producer recommendations","status":"Mixed","source":"spec"},{"id":"2eecfdb00a95","level":"SHOULD","text":"In this case, OpenTelemetry collectors SHOULD modify points at the change-over using interpolation for Sum data points, to reduce gaps to zero width in these cases, without any overlap.","section":"specification/metrics/data-model.md#overlap-interpolation","sectionTitle":"Overlap interpolation","status":"Mixed","source":"spec"},{"id":"8454d3d19385","level":"SHOULD","text":"OpenTelemetry collectors SHOULD export telemetry when they observe overlapping points in data streams, so that the user can monitor for erroneous configurations.","section":"specification/metrics/data-model.md#overlap-observability","sectionTitle":"Overlap observability","status":"Mixed","source":"spec"},{"id":"3e4bbbb1ad02","level":"SHOULD","text":"When there are overlapping points, receivers SHOULD eliminate points so that there are no overlaps.","section":"specification/metrics/data-model.md#overlap-resolution","sectionTitle":"Overlap resolution","status":"Mixed","source":"spec"},{"id":"f549acae49e7","level":"MAY","text":"Producers MAY use an inexact mapping function because in the general case:","section":"specification/metrics/data-model.md#producer-expectations","sectionTitle":"Producer Expectations","status":"Mixed","source":"spec"},{"id":"37326ff230cb","level":"SHOULD","text":"Generally, producers SHOULD use a mapping function with an expected difference of at most 1 from the correct result for all inputs.","section":"specification/metrics/data-model.md#producer-expectations","sectionTitle":"Producer Expectations","status":"Mixed","source":"spec"},{"id":"35b3d6c85f66","level":"SHOULD","text":"Regardless of scale, producers SHOULD ensure that the index of any encoded bucket falls within the range of a signed 32-bit integer.","section":"specification/metrics/data-model.md#producer-expectations","sectionTitle":"Producer Expectations","status":"Mixed","source":"spec"},{"id":"f0b58b912a3d","level":"MUST","text":"All metric data streams within OTLP MUST have one logical writer.","section":"specification/metrics/data-model.md#single-writer","sectionTitle":"Single-Writer","status":"Mixed","source":"spec"},{"id":"2029c986e766","level":"MUST","text":"This means, conceptually, that any Timeseries created from the Protocol MUST have one originating source of truth.","section":"specification/metrics/data-model.md#single-writer","sectionTitle":"Single-Writer","status":"Mixed","source":"spec"},{"id":"d69de608a3f9","level":"SHOULD","text":"All metric data streams produced by OTel SDKs SHOULD have globally unique identity at any given point in time.","section":"specification/metrics/data-model.md#single-writer","sectionTitle":"Single-Writer","status":"Mixed","source":"spec"},{"id":"4510c5bc9abe","level":"MUST","text":"Aggregations of metric streams MUST only be written from a single logical source at any given point time.","section":"specification/metrics/data-model.md#single-writer","sectionTitle":"Single-Writer","status":"Mixed","source":"spec"},{"id":"aa00053a2a98","level":"SHOULD","text":"Receivers SHOULD presume a single writer was intended and eliminate overlap / deduplicate.","section":"specification/metrics/data-model.md#single-writer","sectionTitle":"Single-Writer","status":"Mixed","source":"spec"},{"id":"b49c22d7b1ab","level":"MUST","text":"This MUST be non-negative.","section":"specification/metrics/data-model.md#summary-legacy","sectionTitle":"Summary (Legacy)","status":"Mixed","source":"spec"},{"id":"82fc9f136ffe","level":"SHOULD","text":"For delta monotonic sums, this means the reader SHOULD expect non-negative values.","section":"specification/metrics/data-model.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"30ae074e9f0a","level":"SHOULD","text":"For cumulative monotonic sums, this means the reader SHOULD expect values that are not less than the previous value.","section":"specification/metrics/data-model.md#sums","sectionTitle":"Sums","status":"Mixed","source":"spec"},{"id":"22bb7bbc990b","level":"MUST NOT","text":"Asynchronous Counters MUST NOT return a non-empty error or log any message for any operations they perform.","section":"specification/metrics/noop.md#asynchronous-counter","sectionTitle":"Asynchronous Counter","status":"Stable","source":"spec"},{"id":"f1a122d29963","level":"MUST","text":"All operations an Asynchronous Counter provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#asynchronous-counter","sectionTitle":"Asynchronous Counter","status":"Stable","source":"spec"},{"id":"386023d5cc6e","level":"MUST","text":"The No-Op Meter MUST allow for the creation of an Asynchronous Counter instrument.","section":"specification/metrics/noop.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter Creation","status":"Stable","source":"spec"},{"id":"5658835f6c40","level":"MAY","text":"Since all Asynchronous Counters hold the same empty state, a Meter MAY return the same Asynchronous Counter instance to all creation requests.","section":"specification/metrics/noop.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter Creation","status":"Stable","source":"spec"},{"id":"99f4bd43382b","level":"MUST","text":"The Meter MUST accept these parameters.","section":"specification/metrics/noop.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter Creation","status":"Stable","source":"spec"},{"id":"3548135ac405","level":"MUST NOT","text":"However, the Meter MUST NOT validate any argument it receives and it MUST NOT hold any reference to the passed callbacks.","section":"specification/metrics/noop.md#asynchronous-counter-creation","sectionTitle":"Asynchronous Counter Creation","status":"Stable","source":"spec"},{"id":"e14a1c625982","level":"MUST NOT","text":"The No-Op Asynchronous Counter MUST NOT validate or retain any state about observations made for the instrument.","section":"specification/metrics/noop.md#asynchronous-counter-observations","sectionTitle":"Asynchronous Counter Observations","status":"Stable","source":"spec"},{"id":"2cc61b8c21eb","level":"MUST NOT","text":"Asynchronous Gauges MUST NOT return a non-empty error or log any message for any operations they perform.","section":"specification/metrics/noop.md#asynchronous-gauge","sectionTitle":"Asynchronous Gauge","status":"Stable","source":"spec"},{"id":"e21c3a9fed48","level":"MUST","text":"All operations an Asynchronous Gauge provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#asynchronous-gauge","sectionTitle":"Asynchronous Gauge","status":"Stable","source":"spec"},{"id":"e7b8a8b3130a","level":"MUST","text":"The No-Op Meter MUST allow for the creation of an Asynchronous Gauge instrument.","section":"specification/metrics/noop.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge Creation","status":"Stable","source":"spec"},{"id":"3c307fe8c362","level":"MAY","text":"Since all Asynchronous Gauges hold the same empty state, a Meter MAY return the same Asynchronous UpDownCounter instance to all creation requests.","section":"specification/metrics/noop.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge Creation","status":"Stable","source":"spec"},{"id":"4b58449ca8f2","level":"MUST","text":"The Meter MUST accept these parameters.","section":"specification/metrics/noop.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge Creation","status":"Stable","source":"spec"},{"id":"87a54a4fd73d","level":"MUST NOT","text":"However, the Meter MUST NOT validate any argument it receives and it MUST NOT hold any reference to the passed callbacks.","section":"specification/metrics/noop.md#asynchronous-gauge-creation","sectionTitle":"Asynchronous Gauge Creation","status":"Stable","source":"spec"},{"id":"fcaad2ed0d44","level":"MUST NOT","text":"The No-Op Asynchronous Gauge MUST NOT validate or retain any state about observations made for the instrument.","section":"specification/metrics/noop.md#asynchronous-gauge-observations","sectionTitle":"Asynchronous Gauge Observations","status":"Stable","source":"spec"},{"id":"a58b419c55cf","level":"MUST NOT","text":"Asynchronous UpDownCounters MUST NOT return a non-empty error or log any message for any operations they perform.","section":"specification/metrics/noop.md#asynchronous-updowncounter","sectionTitle":"Asynchronous UpDownCounter","status":"Stable","source":"spec"},{"id":"4b7eca7fddc4","level":"MUST","text":"All operations an Asynchronous UpDownCounter provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#asynchronous-updowncounter","sectionTitle":"Asynchronous UpDownCounter","status":"Stable","source":"spec"},{"id":"c474eb1c99d0","level":"MUST","text":"The No-Op Meter MUST allow for the creation of an Asynchronous UpDownCounter instrument.","section":"specification/metrics/noop.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"91d4a6a1d5ac","level":"MAY","text":"Since all Asynchronous UpDownCounters hold the same empty state, a Meter MAY return the same Asynchronous UpDownCounter instance to all creation requests.","section":"specification/metrics/noop.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"cd1d5544d9c7","level":"MUST","text":"The Meter MUST accept these parameters.","section":"specification/metrics/noop.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"aea5dbca503a","level":"MUST NOT","text":"However, the Meter MUST NOT validate any argument it receives and it MUST NOT hold any reference to the passed callbacks.","section":"specification/metrics/noop.md#asynchronous-updowncounter-creation","sectionTitle":"Asynchronous UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"6747f573fd85","level":"MUST NOT","text":"The No-Op Asynchronous UpDownCounter MUST NOT validate or retain any state about observations made for the instrument.","section":"specification/metrics/noop.md#asynchronous-updowncounter-observations","sectionTitle":"Asynchronous UpDownCounter Observations","status":"Stable","source":"spec"},{"id":"7ae3b724c3b3","level":"MUST NOT","text":"Counters MUST NOT return a non-empty error or log any message for any operations they perform.","section":"specification/metrics/noop.md#counter","sectionTitle":"Counter","status":"Stable","source":"spec"},{"id":"743661e1f64f","level":"MUST","text":"All operations a Counter provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#counter","sectionTitle":"Counter","status":"Stable","source":"spec"},{"id":"6e32253ed041","level":"MUST","text":"The No-Op Counter MUST provide the user an interface to Add that implements the API.","section":"specification/metrics/noop.md#counter-add","sectionTitle":"Counter Add","status":"Stable","source":"spec"},{"id":"45eefb2868c4","level":"MUST NOT","text":"It MUST NOT validate or retain any state about the arguments it receives.","section":"specification/metrics/noop.md#counter-add","sectionTitle":"Counter Add","status":"Stable","source":"spec"},{"id":"20f1cc799ca9","level":"MUST","text":"The No-Op Meter MUST allow for the creation of a Counter instrument.","section":"specification/metrics/noop.md#counter-creation","sectionTitle":"Counter Creation","status":"Stable","source":"spec"},{"id":"c7db21c7a94b","level":"MAY","text":"Since all Counters hold the same empty state, a Meter MAY return the same Counter instance to all creation requests.","section":"specification/metrics/noop.md#counter-creation","sectionTitle":"Counter Creation","status":"Stable","source":"spec"},{"id":"e57806c41442","level":"MUST","text":"The Meter MUST accept these parameters.","section":"specification/metrics/noop.md#counter-creation","sectionTitle":"Counter Creation","status":"Stable","source":"spec"},{"id":"ea4e4431e87a","level":"MUST NOT","text":"However, the Meter MUST NOT validate any argument it receives.","section":"specification/metrics/noop.md#counter-creation","sectionTitle":"Counter Creation","status":"Stable","source":"spec"},{"id":"8419d430db49","level":"MUST NOT","text":"Histograms MUST NOT return a non-empty error or log any message for any operations they perform.","section":"specification/metrics/noop.md#histogram","sectionTitle":"Histogram","status":"Stable","source":"spec"},{"id":"3d09eb963377","level":"MUST","text":"All operations a Histogram provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#histogram","sectionTitle":"Histogram","status":"Stable","source":"spec"},{"id":"f6b1cf1a0ddf","level":"MUST","text":"The No-Op Meter MUST allow for the creation of a Histogram instrument.","section":"specification/metrics/noop.md#histogram-creation","sectionTitle":"Histogram Creation","status":"Stable","source":"spec"},{"id":"82069e78d3a2","level":"MAY","text":"Since all Histograms hold the same empty state, a Meter MAY return the same Histogram instance to all creation requests.","section":"specification/metrics/noop.md#histogram-creation","sectionTitle":"Histogram Creation","status":"Stable","source":"spec"},{"id":"b2eacdb78673","level":"MUST","text":"The Meter MUST accept these parameters.","section":"specification/metrics/noop.md#histogram-creation","sectionTitle":"Histogram Creation","status":"Stable","source":"spec"},{"id":"f623e08e5c8b","level":"MUST NOT","text":"However, the Meter MUST NOT validate any argument it receives.","section":"specification/metrics/noop.md#histogram-creation","sectionTitle":"Histogram Creation","status":"Stable","source":"spec"},{"id":"49c60ec1464b","level":"MUST","text":"The No-Op Histogram MUST provide the user an interface to Record that implements the API.","section":"specification/metrics/noop.md#histogram-record","sectionTitle":"Histogram Record","status":"Stable","source":"spec"},{"id":"3ef35366efe1","level":"MUST NOT","text":"It MUST NOT validate or retain any state about the arguments it receives.","section":"specification/metrics/noop.md#histogram-record","sectionTitle":"Histogram Record","status":"Stable","source":"spec"},{"id":"c7866be4f217","level":"MUST NOT","text":"Because of this, all instruments the No-Op provides MUST NOT hold any configuration or operational state including the aggregation of telemetry.","section":"specification/metrics/noop.md#instruments","sectionTitle":"Instruments","status":"Stable","source":"spec"},{"id":"b69d6f1032e7","level":"MUST NOT","text":"Therefore, all Meters created MUST NOT hold configuration or operational state.","section":"specification/metrics/noop.md#meter","sectionTitle":"Meter","status":"Stable","source":"spec"},{"id":"4d784fde2055","level":"MUST NOT","text":"The Meter MUST NOT return a non-empty error or log any message for any operations it performs.","section":"specification/metrics/noop.md#meter","sectionTitle":"Meter","status":"Stable","source":"spec"},{"id":"45b8a534654b","level":"MUST","text":"All operations a Meter provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#meter","sectionTitle":"Meter","status":"Stable","source":"spec"},{"id":"5dec23c22482","level":"MUST","text":"Therefore, MeterProviders MUST allow for the creation of Meters.","section":"specification/metrics/noop.md#meter-creation","sectionTitle":"Meter Creation","status":"Stable","source":"spec"},{"id":"70a15f21abb3","level":"MUST","text":"All Meters created MUST be an instance of the No-Op Meter.","section":"specification/metrics/noop.md#meter-creation","sectionTitle":"Meter Creation","status":"Stable","source":"spec"},{"id":"807bee4c2e3a","level":"MAY","text":"Since all Meters will hold the same empty state, a MeterProvider MAY return the same Meter instances to all creation requests.","section":"specification/metrics/noop.md#meter-creation","sectionTitle":"Meter Creation","status":"Stable","source":"spec"},{"id":"f94062adce2f","level":"MUST","text":"The MeterProvider MUST accept these parameters.","section":"specification/metrics/noop.md#meter-creation","sectionTitle":"Meter Creation","status":"Stable","source":"spec"},{"id":"c7a0d489070f","level":"MUST NOT","text":"However, the MeterProvider MUST NOT validate any argument it receives.","section":"specification/metrics/noop.md#meter-creation","sectionTitle":"Meter Creation","status":"Stable","source":"spec"},{"id":"7fed3b6972e9","level":"MUST","text":"The No-Op MUST allow the creation of multiple MeterProviders.","section":"specification/metrics/noop.md#meterprovider","sectionTitle":"MeterProvider","status":"Stable","source":"spec"},{"id":"25714693c849","level":"MUST NOT","text":"Therefore, all MeterProviders created MUST NOT hold configuration or operational state.","section":"specification/metrics/noop.md#meterprovider","sectionTitle":"MeterProvider","status":"Stable","source":"spec"},{"id":"4ca93d6d6243","level":"MAY","text":"Since all MeterProviders hold the same empty state, a No-Op MAY provide the same MeterProvider instances to all creation requests.","section":"specification/metrics/noop.md#meterprovider","sectionTitle":"MeterProvider","status":"Stable","source":"spec"},{"id":"fef7ff92e2a4","level":"MUST NOT","text":"For this reason, the MeterProvider MUST NOT return a non-empty error or log any message for any operations it performs.","section":"specification/metrics/noop.md#meterprovider","sectionTitle":"MeterProvider","status":"Stable","source":"spec"},{"id":"8aa5b3e30d75","level":"MUST","text":"All operations a MeterProvider provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#meterprovider","sectionTitle":"MeterProvider","status":"Stable","source":"spec"},{"id":"18bcda966901","level":"MUST","text":"All language implementations of OpenTelemetry MUST provide a No-Op.","section":"specification/metrics/noop.md#metrics-no-op-api-implementation","sectionTitle":"Metrics No-Op API Implementation","status":"Stable","source":"spec"},{"id":"1f9090fcb7c4","level":"MUST NOT","text":"UpDownCounters MUST NOT return a non-empty error or log any message for any operations they perform.","section":"specification/metrics/noop.md#updowncounter","sectionTitle":"UpDownCounter","status":"Stable","source":"spec"},{"id":"a98e85c903b2","level":"MUST","text":"All operations an UpDownCounter provides MUST be safe to be run concurrently.","section":"specification/metrics/noop.md#updowncounter","sectionTitle":"UpDownCounter","status":"Stable","source":"spec"},{"id":"cc9bc3bdeb2c","level":"MUST","text":"The No-Op UpDownCounter MUST provide the user an interface to Add that implements the API.","section":"specification/metrics/noop.md#updowncounter-add","sectionTitle":"UpDownCounter Add","status":"Stable","source":"spec"},{"id":"324a8dad967c","level":"MUST NOT","text":"It MUST NOT validate or retain any state about the arguments it receives.","section":"specification/metrics/noop.md#updowncounter-add","sectionTitle":"UpDownCounter Add","status":"Stable","source":"spec"},{"id":"3179b7c30d12","level":"MUST","text":"The No-Op Meter MUST allow for the creation of a UpDownCounter instrument.","section":"specification/metrics/noop.md#updowncounter-creation","sectionTitle":"UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"fa425d331750","level":"MAY","text":"Since all UpDownCounters hold the same empty state, a Meter MAY return the same UpDownCounter instance to all creation requests.","section":"specification/metrics/noop.md#updowncounter-creation","sectionTitle":"UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"35dd73f5ff35","level":"MUST","text":"The Meter MUST accept these parameters.","section":"specification/metrics/noop.md#updowncounter-creation","sectionTitle":"UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"d6ef960fe852","level":"MUST NOT","text":"However, the Meter MUST NOT validate any argument it receives.","section":"specification/metrics/noop.md#updowncounter-creation","sectionTitle":"UpDownCounter Creation","status":"Stable","source":"spec"},{"id":"173025f1fc05","level":"MUST","text":"In-memory Metrics Exporter MUST provide configuration to set the MetricReader output `temporality` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/in-memory.md#metrics-exporter---in-memory","sectionTitle":"Metrics Exporter - In-memory","status":"Stable","source":"spec"},{"id":"ad393f2b88e2","level":"MUST","text":"This option MAY be named `temporality`, and MUST set temporality to Cumulative for all instrument kinds by default.","section":"specification/metrics/sdk_exporters/in-memory.md#metrics-exporter---in-memory","sectionTitle":"Metrics Exporter - In-memory","status":"Stable","source":"spec"},{"id":"a5c023a168a5","level":"MAY","text":"In-memory Metrics Exporter MAY provide configuration to set the MetricReader default `aggregation` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/in-memory.md#metrics-exporter---in-memory","sectionTitle":"Metrics Exporter - In-memory","status":"Stable","source":"spec"},{"id":"6bde28bff5fa","level":"MUST","text":"This option MAY be named `default_aggregation`, and MUST use the default aggregation by default.","section":"specification/metrics/sdk_exporters/in-memory.md#metrics-exporter---in-memory","sectionTitle":"Metrics Exporter - In-memory","status":"Stable","source":"spec"},{"id":"b4cb6a3ef82b","level":"MUST","text":"If a language provides a mechanism to automatically configure a MetricReader to pair with the associated exporter (e.g., using the `OTELMETRICSEXPORTER` environment variable), by default the exporter MUST be paired with a periodic exporting MetricReader.","section":"specification/metrics/sdk_exporters/in-memory.md#metrics-exporter---in-memory","sectionTitle":"Metrics Exporter - In-memory","status":"Stable","source":"spec"},{"id":"0e3ab4d1064e","level":"MUST","text":"OTLP Metrics Exporter MUST provide configuration to influence the MetricReader output `temporality` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"51d50dbc28f0","level":"MUST","text":"This option MAY be named `temporality`, and MUST set temporality preference to Cumulative for all instrument kinds by default.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"e2363a73e69f","level":"MUST","text":"OTLP Metrics Exporter MUST provide configuration to influence the MetricReader default `aggregation` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"543947850985","level":"MUST","text":"This option MAY be named `default_aggregation`, and MUST set the default aggregation for all instrument kinds by default.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"d1b211fde189","level":"MUST","text":"The exporter MUST provide configuration according to the OpenTelemetry Protocol Exporter specification.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"6e2fe636617a","level":"MUST","text":"The exporter MUST be paired with a periodic exporting MetricReader.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"28fd2dcb4700","level":"MUST","text":"The exporter MUST configure the default aggregation temporality on the basis of instrument kind using the `OTELEXPORTEROTLPMETRICSTEMPORALITY_PREFERENCE` variable as described below.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"f2e216ddbf27","level":"MUST","text":"The exporter MUST configure the default aggregation on the basis of instrument kind using the `OTELEXPORTEROTLPMETRICSDEFAULTHISTOGRAMAGGREGATION` variable as described below if it is implemented.","section":"specification/metrics/sdk_exporters/otlp.md#general","sectionTitle":"General","status":"Stable","source":"spec"},{"id":"192cc3afd443","level":"SHOULD NOT","text":"A Prometheus Exporter SHOULD use an official Prometheus client library when one exists for the implementation language and it is practical to do so (e.g., dependency concerns) for serving Prometheus metrics; it SHOULD NOT use an unofficial Prometheus client library.","section":"specification/metrics/sdk_exporters/prometheus.md#client-libraries","sectionTitle":"Client Libraries","status":"Mixed","source":"spec"},{"id":"214614e230e7","level":"SHOULD","text":"If a Prometheus client library is used, the OpenTelemetry Prometheus Exporter SHOULD be modeled as a custom Collector so it can be used in conjunction with existing Prometheus instrumentation.","section":"specification/metrics/sdk_exporters/prometheus.md#client-libraries","sectionTitle":"Client Libraries","status":"Mixed","source":"spec"},{"id":"a07224e7c38e","level":"MUST","text":"A Prometheus Exporter MUST support content negotiation to allow clients to request metrics in different formats based on the `Accept` header in HTTP requests.","section":"specification/metrics/sdk_exporters/prometheus.md#content-negotiation","sectionTitle":"Content Negotiation","status":"Mixed","source":"spec"},{"id":"b78894898268","level":"MUST","text":"Content negotiation MUST follow Prometheus Content Negotiation guidelines.","section":"specification/metrics/sdk_exporters/prometheus.md#content-negotiation","sectionTitle":"Content Negotiation","status":"Mixed","source":"spec"},{"id":"b3e25da7f40d","level":"MUST","text":"If no `Accept` header is provided and no fallback protocol is configured, the exporter MUST use Prometheus text format 0.0.4 (`text/plain; version=0.0.4`) and apply `underscores` escaping.","section":"specification/metrics/sdk_exporters/prometheus.md#content-negotiation","sectionTitle":"Content Negotiation","status":"Mixed","source":"spec"},{"id":"3d23ffccd942","level":"SHOULD","text":"A Prometheus Exporter SHOULD support a configuration option to set the MetricReader default `aggregation` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/prometheus.md#default-aggregation","sectionTitle":"Default Aggregation","status":"Mixed","source":"spec"},{"id":"484fa6174529","level":"MUST","text":"This option MAY be named `default_aggregation`, and MUST use the default aggregation by default.","section":"specification/metrics/sdk_exporters/prometheus.md#default-aggregation","sectionTitle":"Default Aggregation","status":"Mixed","source":"spec"},{"id":"2a60bd2a80e6","level":"SHOULD","text":"A Prometheus Exporter SHOULD support a configuration option to set the host that metrics are served on.","section":"specification/metrics/sdk_exporters/prometheus.md#host","sectionTitle":"Host","status":"Mixed","source":"spec"},{"id":"0abcdb53ce77","level":"MUST","text":"The option MAY be named `host`, and MUST be `localhost` by default.","section":"specification/metrics/sdk_exporters/prometheus.md#host","sectionTitle":"Host","status":"Mixed","source":"spec"},{"id":"5544402488be","level":"MUST","text":"Regardless of the configured `translation_strategy`, the final output format and character escaping MUST comply with the content negotiation's restrictions based on the `Accept` header.","section":"specification/metrics/sdk_exporters/prometheus.md#interaction-with-translation-strategy","sectionTitle":"Interaction with Translation Strategy","status":"Mixed","source":"spec"},{"id":"c2a99b1ac853","level":"MUST","text":"First, `translation_strategy` MUST be applied to construct metric names.","section":"specification/metrics/sdk_exporters/prometheus.md#interaction-with-translation-strategy","sectionTitle":"Interaction with Translation Strategy","status":"Mixed","source":"spec"},{"id":"5c7984c54a73","level":"MUST","text":"Then, the Prometheus Exporter MUST apply content negotiation, which may include a second translation of metric names using the requested escaping scheme.","section":"specification/metrics/sdk_exporters/prometheus.md#interaction-with-translation-strategy","sectionTitle":"Interaction with Translation Strategy","status":"Mixed","source":"spec"},{"id":"c93ec56d6546","level":"MUST","text":"OpenTelemetry metrics MUST be converted to Prometheus metrics according to the Prometheus Compatibility specification.","section":"specification/metrics/sdk_exporters/prometheus.md#metric-conversion","sectionTitle":"Metric Conversion","status":"Mixed","source":"spec"},{"id":"e05311142ee6","level":"SHOULD","text":"A Prometheus Exporter SHOULD support a configuration option to set the port that metrics are served on.","section":"specification/metrics/sdk_exporters/prometheus.md#port","sectionTitle":"Port","status":"Mixed","source":"spec"},{"id":"527a24e538e6","level":"MUST","text":"The option MAY be named `port`, and MUST be `9464` by default.","section":"specification/metrics/sdk_exporters/prometheus.md#port","sectionTitle":"Port","status":"Mixed","source":"spec"},{"id":"43ae4e141b18","level":"MUST","text":"A Prometheus Exporter MUST be a Pull Metric Exporter which responds to HTTP requests with Prometheus metrics in the appropriate format.","section":"specification/metrics/sdk_exporters/prometheus.md#pull-metric-exporter","sectionTitle":"Pull Metric Exporter","status":"Mixed","source":"spec"},{"id":"4952d7f87f4d","level":"MAY","text":"A Prometheus Exporter MAY offer configuration to add resource attributes as metric labels.","section":"specification/metrics/sdk_exporters/prometheus.md#resource-attributes-as-metric-labels","sectionTitle":"Resource Attributes as Metric Labels","status":"Mixed","source":"spec"},{"id":"88c55513ab45","level":"MUST NOT","text":"By default, it MUST NOT add any resource attributes as metric labels.","section":"specification/metrics/sdk_exporters/prometheus.md#resource-attributes-as-metric-labels","sectionTitle":"Resource Attributes as Metric Labels","status":"Mixed","source":"spec"},{"id":"6e5d629d7d9b","level":"SHOULD","text":"The configuration SHOULD allow the user to select resource attributes to include or exclude.","section":"specification/metrics/sdk_exporters/prometheus.md#resource-attributes-as-metric-labels","sectionTitle":"Resource Attributes as Metric Labels","status":"Mixed","source":"spec"},{"id":"bb8c8d58ba84","level":"MUST NOT","text":"Copied Resource attributes MUST NOT be excluded from the `targetinfo` metric.","section":"specification/metrics/sdk_exporters/prometheus.md#resource-attributes-as-metric-labels","sectionTitle":"Resource Attributes as Metric Labels","status":"Mixed","source":"spec"},{"id":"5c8fbdb14261","level":"MAY","text":"The option MAY be named `resourceconstant_labels`.","section":"specification/metrics/sdk_exporters/prometheus.md#resource-attributes-as-metric-labels","sectionTitle":"Resource Attributes as Metric Labels","status":"Mixed","source":"spec"},{"id":"c390c19e4c61","level":"MAY","text":"A Prometheus Exporter MAY support configuration to specify whether metrics include scope labels.","section":"specification/metrics/sdk_exporters/prometheus.md#scope-info","sectionTitle":"Scope Info","status":"Mixed","source":"spec"},{"id":"c45c04a845d2","level":"MUST","text":"The option MAY be named `scopeinfoenabled`, and MUST be `true` by default.","section":"specification/metrics/sdk_exporters/prometheus.md#scope-info","sectionTitle":"Scope Info","status":"Mixed","source":"spec"},{"id":"3d371c3c4f07","level":"MUST","text":"There MUST be at most one `target` info metric exposed by an SDK Prometheus exporter.","section":"specification/metrics/sdk_exporters/prometheus.md#target","sectionTitle":"Target","status":"Mixed","source":"spec"},{"id":"d2b1c038c8d5","level":"MAY","text":"A Prometheus Exporter MAY support a configuration to specify whether to produce a target info metric.","section":"specification/metrics/sdk_exporters/prometheus.md#target-info","sectionTitle":"Target Info","status":"Mixed","source":"spec"},{"id":"fc96ef4b567f","level":"MUST","text":"The option MAY be named `targetinfoenabled`, and MUST be `true` by default.","section":"specification/metrics/sdk_exporters/prometheus.md#target-info","sectionTitle":"Target Info","status":"Mixed","source":"spec"},{"id":"b2e8f24ba95f","level":"MUST","text":"A Prometheus Exporter MUST set the MetricReader `temporality` as a function of instrument kind to be `cumulative` for all instrument kinds.","section":"specification/metrics/sdk_exporters/prometheus.md#temporality","sectionTitle":"Temporality","status":"Mixed","source":"spec"},{"id":"63166d1d948d","level":"MAY","text":"A Prometheus Exporter MAY support a configuration option that controls the translation of metric names from OpenTelemetry Naming Conventions to Prometheus Naming conventions.","section":"specification/metrics/sdk_exporters/prometheus.md#translation-strategy","sectionTitle":"Translation Strategy","status":"Mixed","source":"spec"},{"id":"1e50b816faa5","level":"MUST","text":"If the Prometheus exporter supports such configuration it MUST be named to something that resembles Prometheus configuration option `translation_strategy`, and the translation options MUST be:","section":"specification/metrics/sdk_exporters/prometheus.md#translation-strategy","sectionTitle":"Translation Strategy","status":"Mixed","source":"spec"},{"id":"0e2aad714c30","level":"MUST","text":"Regardless of whether a Prometheus client library is used, the Prometheus Exporter MUST support version `0.0.4` of the Text-based format.","section":"specification/metrics/sdk_exporters/prometheus.md#version-and-format","sectionTitle":"Version and Format","status":"Mixed","source":"spec"},{"id":"df195ff95f54","level":"MAY","text":"A Prometheus Exporter MAY support Exemplars and Exponential Histograms, which are not currently supported by the Prometheus text format, by supporting other Protocols, but is not required to implement them.","section":"specification/metrics/sdk_exporters/prometheus.md#version-and-format","sectionTitle":"Version and Format","status":"Mixed","source":"spec"},{"id":"3244ce13575e","level":"MUST NOT","text":"A Prometheus Exporter for an OpenTelemetry metrics SDK MUST NOT use Prometheus Remote Write format or OpenMetrics protobuf format.","section":"specification/metrics/sdk_exporters/prometheus.md#version-and-format","sectionTitle":"Version and Format","status":"Mixed","source":"spec"},{"id":"4e96e3856e34","level":"SHOULD NOT","text":"A Prometheus Exporter for an OpenTelemetry metrics SDK SHOULD NOT add explicit timestamps on Metric points.","section":"specification/metrics/sdk_exporters/prometheus.md#version-and-format","sectionTitle":"Version and Format","status":"Mixed","source":"spec"},{"id":"b0badab27edb","level":"SHOULD","text":"Documentation SHOULD warn users about this.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"d72daae0b858","level":"MAY","text":"OpenTelemetry SDK authors MAY choose the best idiomatic name for their language.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"db9836f6cf0e","level":"MUST","text":"\"Standard output\" Metrics Exporter MUST provide configuration to set the MetricReader output `temporality` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"bc23863d6805","level":"MUST","text":"This option MAY be named `temporality`, and MUST set temporality to Cumulative for all instrument kinds by default.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"e817b4561731","level":"MAY","text":"\"Standard output\" Metrics Exporter MAY provide configuration to set the MetricReader default `aggregation` as a function of instrument kind.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"f026237f3b8f","level":"MUST","text":"This option MAY be named `default_aggregation`, and MUST use the default aggregation by default.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"4c4051ab451a","level":"MUST","text":"If a language provides a mechanism to automatically configure a MetricReader to pair with the associated exporter (e.g., using the `OTELMETRICSEXPORTER` environment variable), by default the exporter MUST be paired with a periodic exporting MetricReader with a default `exportIntervalMilliseconds` of 10000.","section":"specification/metrics/sdk_exporters/stdout.md#metrics-exporter---standard-output","sectionTitle":"Metrics Exporter - Standard output","status":"Stable","source":"spec"},{"id":"f8b44c950522","level":"RECOMMENDED","text":"It is RECOMMENDED that implementors reserve the \"aggregator\" term for the future when the SDK allows custom aggregation implementations.","section":"specification/metrics/sdk.md#aggregation","sectionTitle":"Aggregation","status":"Mixed","source":"spec"},{"id":"4cdb6d83e98b","level":"MAY","text":"Note: Implementors MAY choose the best idiomatic practice for their language to represent the semantic of an Aggregation and optional configuration parameters.","section":"specification/metrics/sdk.md#aggregation","sectionTitle":"Aggregation","status":"Mixed","source":"spec"},{"id":"f688b14e5e99","level":"MUST","text":"The SDK MUST provide the following `Aggregation` to support the Metric Points in the Metrics Data Model.","section":"specification/metrics/sdk.md#aggregation","sectionTitle":"Aggregation","status":"Mixed","source":"spec"},{"id":"42ebac9387a4","level":"SHOULD","text":"The SDK SHOULD provide the following `Aggregation`:","section":"specification/metrics/sdk.md#aggregation","sectionTitle":"Aggregation","status":"Mixed","source":"spec"},{"id":"97cdee738525","level":"MUST","text":"This Exemplar reservoir MUST take a configuration parameter that is the configuration of a Histogram.","section":"specification/metrics/sdk.md#alignedhistogrambucketexemplarreservoir","sectionTitle":"AlignedHistogramBucketExemplarReservoir","status":"Mixed","source":"spec"},{"id":"3f7ea0754469","level":"MUST","text":"This implementation MUST store at most one measurement that falls within a histogram bucket, and SHOULD use a uniformly-weighted sampling algorithm based on the number of measurements the bucket has seen so far to determine if the offered measurements should be sampled.","section":"specification/metrics/sdk.md#alignedhistogrambucketexemplarreservoir","sectionTitle":"AlignedHistogramBucketExemplarReservoir","status":"Mixed","source":"spec"},{"id":"9a0f0cbade47","level":"MAY","text":"Alternatively, the implementation MAY instead keep the last seen measurement that falls within a histogram bucket.","section":"specification/metrics/sdk.md#alignedhistogrambucketexemplarreservoir","sectionTitle":"AlignedHistogramBucketExemplarReservoir","status":"Mixed","source":"spec"},{"id":"7c1870d07f1c","level":"MAY","text":"This Exemplar reservoir MAY take a configuration parameter for the bucket boundaries used by the reservoir.","section":"specification/metrics/sdk.md#alignedhistogrambucketexemplarreservoir","sectionTitle":"AlignedHistogramBucketExemplarReservoir","status":"Mixed","source":"spec"},{"id":"2e0c3263151f","level":"SHOULD","text":"This configuration parameter SHOULD have the same format as specifying bucket boundaries to Explicit Bucket Histogram Aggregation.","section":"specification/metrics/sdk.md#alignedhistogrambucketexemplarreservoir","sectionTitle":"AlignedHistogramBucketExemplarReservoir","status":"Mixed","source":"spec"},{"id":"613005b3ac11","level":"SHOULD","text":"Aggregators of asynchronous instruments SHOULD prefer the first-observed attributes in the callback when limiting cardinality, regardless of temporality.","section":"specification/metrics/sdk.md#asynchronous-instrument-cardinality-limits","sectionTitle":"Asynchronous instrument cardinality limits","status":"Mixed","source":"spec"},{"id":"b118c0537ede","level":"SHOULD","text":"SDKs SHOULD support being configured with a cardinality limit.","section":"specification/metrics/sdk.md#cardinality-limits","sectionTitle":"Cardinality limits","status":"Mixed","source":"spec"},{"id":"672bca4770db","level":"SHOULD","text":"Cardinality limit enforcement SHOULD occur after attribute filtering, if any.","section":"specification/metrics/sdk.md#cardinality-limits","sectionTitle":"Cardinality limits","status":"Mixed","source":"spec"},{"id":"65fb1ad5b760","level":"SHOULD","text":"`Collect` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"41a30b6368de","level":"MAY","text":"When the `Collect` operation fails or times out on some of the instruments, the SDK MAY return successfully collected results and a failed reasons list to the caller.","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"a9ed8223ceac","level":"MAY","text":"`Collect` does not have any required parameters, however, OpenTelemetry SDK authors MAY choose to add parameters (e.g. callback, filter, timeout).","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"952c6d8ccc71","level":"MAY","text":"OpenTelemetry SDK authors MAY choose the return value type, or do not return anything.","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"8b1b460524c6","level":"SHOULD","text":"`Collect` SHOULD invoke Produce on registered MetricProducers.","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"143d7762c77b","level":"MAY","text":"If the batch of metric points from `Produce` includes Resource information, `Collect` MAY replace the `Resource` from the MetricProducer with the `Resource` provided when constructing the MeterProvider instead.","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"6343442b8a0b","level":"RECOMMENDED","text":"Note: it is expected that the `MetricReader.Collect` implementations will be provided by the SDK, so it is RECOMMENDED to prevent the user from accidentally overriding it, if possible (e.g. `final` in C++ and Java, `sealed` in C#).","section":"specification/metrics/sdk.md#collect","sectionTitle":"Collect","status":"Mixed","source":"spec"},{"id":"22e32a1a5d5a","level":"SHOULD","text":"All the metrics components SHOULD allow new methods to be added to existing components without introducing breaking changes.","section":"specification/metrics/sdk.md#compatibility-requirements","sectionTitle":"Compatibility requirements","status":"Mixed","source":"spec"},{"id":"e01f7659e657","level":"SHOULD","text":"All the metrics SDK methods SHOULD allow optional parameter(s) to be added to existing methods without introducing breaking changes, if possible.","section":"specification/metrics/sdk.md#compatibility-requirements","sectionTitle":"Compatibility requirements","status":"Mixed","source":"spec"},{"id":"beedc6ed07d8","level":"MUST","text":"MeterProvider - Meter creation, `ForceFlush` and `Shutdown` MUST be safe to be called concurrently.","section":"specification/metrics/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Mixed","source":"spec"},{"id":"e1f54ac82fc9","level":"MUST","text":"ExemplarReservoir - all methods MUST be safe to be called concurrently.","section":"specification/metrics/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Mixed","source":"spec"},{"id":"9705245b4299","level":"MUST","text":"MetricReader - `Collect`, `ForceFlush` (for periodic exporting MetricReader) and `Shutdown` MUST be safe to be called concurrently.","section":"specification/metrics/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Mixed","source":"spec"},{"id":"22849c74ed38","level":"MUST","text":"MetricExporter - `ForceFlush` and `Shutdown` MUST be safe to be called concurrently.","section":"specification/metrics/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Mixed","source":"spec"},{"id":"3f8b01fd2b57","level":"MUST","text":"Configuration ( i.e. MetricExporters, MetricReaders, Views, and (Development) MeterConfigurator and (Development) viewmatchingmode) MUST be owned by the `MeterProvider`.","section":"specification/metrics/sdk.md#configuration","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"8b3152a1d614","level":"MAY","text":"The configuration MAY be applied at the time of `MeterProvider` creation if appropriate.","section":"specification/metrics/sdk.md#configuration","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"8c78f678dde2","level":"MAY","text":"The `MeterProvider` MAY provide methods to update the configuration.","section":"specification/metrics/sdk.md#configuration","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"416917d211ba","level":"MUST NOT","text":"If configuration is updated (e.g., adding a `MetricReader`), the updated configuration MUST also apply to all already returned `Meters` (i.e. it MUST NOT matter whether a `Meter` was obtained from the `MeterProvider` before or after the configuration change).","section":"specification/metrics/sdk.md#configuration","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"67f1e0c8982d","level":"SHOULD","text":"A view with criteria matching the instrument an aggregation is created for has an `aggregationcardinalitylimit` value defined for the stream, that value SHOULD be used.","section":"specification/metrics/sdk.md#configuration-1","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"8eaecd843cb5","level":"SHOULD","text":"If there is no matching view, but the `MetricReader` defines a default cardinality limit value based on the instrument an aggregation is created for, that value SHOULD be used.","section":"specification/metrics/sdk.md#configuration-1","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"5536a21a4a53","level":"SHOULD","text":"If none of the previous values are defined, the default value of 2000 SHOULD be used.","section":"specification/metrics/sdk.md#configuration-1","sectionTitle":"Configuration","status":"Mixed","source":"spec"},{"id":"e71ad231e797","level":"MUST","text":"The SDK MUST provide a mechanism for SDK users to provide their own ExemplarReservoir implementation.","section":"specification/metrics/sdk.md#custom-exemplarreservoir","sectionTitle":"Custom ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"6256aafcefa6","level":"MUST","text":"This extension MUST be configurable on a metric View, although individual reservoirs MUST still be instantiated per metric-timeseries (see Exemplar Reservoir - Paragraph 2).","section":"specification/metrics/sdk.md#custom-exemplarreservoir","sectionTitle":"Custom ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"da703dcf3fa2","level":"MUST","text":"The SDK MUST provide configuration according to the SDK environment variables specification.","section":"specification/metrics/sdk.md#defaults-and-configuration","sectionTitle":"Defaults and configuration","status":"Mixed","source":"spec"},{"id":"8305f7b0f255","level":"MUST","text":"This means that the Meter MUST return a functional instrument that can be expected to export data even if this will cause semantic error in the data model.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"ad59638b01fe","level":"SHOULD","text":"Therefore, when a duplicate instrument registration occurs, and it is not corrected with a View, a warning SHOULD be emitted.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"42d4b4447167","level":"SHOULD","text":"The emitted warning SHOULD include information for the user on how to resolve the conflict, if possible.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"32fcfe2be3b9","level":"SHOULD","text":"If the potential conflict involves multiple `description` properties, setting the `description` through a configured View SHOULD avoid the warning.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"68dcefa43714","level":"SHOULD","text":"If the potential conflict involves instruments that can be distinguished by a supported View selector (e.g. name, instrument kind) a renaming View recipe SHOULD be included in the warning.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"42e45c5241ab","level":"SHOULD","text":"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.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"cb0de39ae5c1","level":"MUST","text":"To accommodate the recommendations from the data model, the SDK MUST aggregate data from identical Instruments together in its export pipeline.","section":"specification/metrics/sdk.md#duplicate-instrument-registration","sectionTitle":"Duplicate instrument registration","status":"Mixed","source":"spec"},{"id":"59bb90d54f3f","level":"MUST","text":"A Metric SDK MUST provide a mechanism to sample `Exemplar`s from measurements via the `ExemplarFilter` and `ExemplarReservoir` hooks.","section":"specification/metrics/sdk.md#exemplar","sectionTitle":"Exemplar","status":"Mixed","source":"spec"},{"id":"54c2e8a3145d","level":"SHOULD","text":"`Exemplar` sampling SHOULD be turned on by default.","section":"specification/metrics/sdk.md#exemplar","sectionTitle":"Exemplar","status":"Mixed","source":"spec"},{"id":"006fa9189391","level":"MUST NOT","text":"If `Exemplar` sampling is off, the SDK MUST NOT have overhead related to exemplar sampling.","section":"specification/metrics/sdk.md#exemplar","sectionTitle":"Exemplar","status":"Mixed","source":"spec"},{"id":"8130fea07ca3","level":"MUST","text":"A Metric SDK MUST allow exemplar sampling to leverage the configuration of metric aggregation.","section":"specification/metrics/sdk.md#exemplar","sectionTitle":"Exemplar","status":"Mixed","source":"spec"},{"id":"ac3153b9dea5","level":"SHOULD","text":"A Metric SDK SHOULD provide configuration for Exemplar sampling, specifically:","section":"specification/metrics/sdk.md#exemplar","sectionTitle":"Exemplar","status":"Mixed","source":"spec"},{"id":"8b747a9c5caf","level":"MUST","text":"The SDK MUST include two types of built-in exemplar reservoirs:","section":"specification/metrics/sdk.md#exemplar-defaults","sectionTitle":"Exemplar defaults","status":"Mixed","source":"spec"},{"id":"c7aa3f891122","level":"SHOULD","text":"Explicit bucket histogram aggregation with more than 1 bucket SHOULD use `AlignedHistogramBucketExemplarReservoir`.","section":"specification/metrics/sdk.md#exemplar-defaults","sectionTitle":"Exemplar defaults","status":"Mixed","source":"spec"},{"id":"8bc58e418f24","level":"SHOULD","text":"Base2 Exponential Histogram Aggregation SHOULD use a `SimpleFixedSizeExemplarReservoir` with a reservoir equal to the smaller of the maximum number of buckets configured on the aggregation or twenty (e.g. `min(20, max_buckets)`).","section":"specification/metrics/sdk.md#exemplar-defaults","sectionTitle":"Exemplar defaults","status":"Mixed","source":"spec"},{"id":"0db542d8c35c","level":"SHOULD","text":"All other aggregations SHOULD use `SimpleFixedSizeExemplarReservoir`.","section":"specification/metrics/sdk.md#exemplar-defaults","sectionTitle":"Exemplar defaults","status":"Mixed","source":"spec"},{"id":"b6b0a1d7b0f1","level":"MAY","text":"Exemplar default reservoirs MAY change in a minor version bump.","section":"specification/metrics/sdk.md#exemplar-defaults","sectionTitle":"Exemplar defaults","status":"Mixed","source":"spec"},{"id":"dda995c270ac","level":"MUST","text":"The `ExemplarFilter` configuration MUST allow users to select between one of the built-in ExemplarFilters.","section":"specification/metrics/sdk.md#exemplarfilter","sectionTitle":"ExemplarFilter","status":"Mixed","source":"spec"},{"id":"61617e297884","level":"SHOULD","text":"The ExemplarFilter SHOULD be a configuration parameter of a `MeterProvider` for an SDK.","section":"specification/metrics/sdk.md#exemplarfilter","sectionTitle":"ExemplarFilter","status":"Mixed","source":"spec"},{"id":"3dd0f55c36e5","level":"SHOULD","text":"The default value SHOULD be `TraceBased`.","section":"specification/metrics/sdk.md#exemplarfilter","sectionTitle":"ExemplarFilter","status":"Mixed","source":"spec"},{"id":"7463c3ee4ac8","level":"SHOULD","text":"The filter configuration SHOULD follow the environment variable specification.","section":"specification/metrics/sdk.md#exemplarfilter","sectionTitle":"ExemplarFilter","status":"Mixed","source":"spec"},{"id":"f9cda618f421","level":"MUST","text":"An OpenTelemetry SDK MUST support the following filters:","section":"specification/metrics/sdk.md#exemplarfilter","sectionTitle":"ExemplarFilter","status":"Mixed","source":"spec"},{"id":"f769d72a3a56","level":"MUST","text":"The `ExemplarReservoir` interface MUST provide a method to offer measurements to the reservoir and another to collect accumulated Exemplars.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"f41844a25809","level":"MUST","text":"A new `ExemplarReservoir` MUST be created for every known timeseries data point, as determined by aggregation and view configuration.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"ec91e92ab7d0","level":"SHOULD","text":"The \"offer\" method SHOULD accept measurements, including:","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"3da86de48a55","level":"SHOULD","text":"The \"offer\" method SHOULD have the ability to pull associated trace and span information without needing to record full context.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"bd1776fa85ee","level":"MAY","text":"The \"offer\" method does not need to store all measurements it is given and MAY further sample beyond the `ExemplarFilter`.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"c1f772dfd621","level":"MAY","text":"The \"offer\" method MAY accept a filtered subset of `Attributes` which diverge from the timeseries the reservoir is associated with.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"469ac10c355e","level":"MUST","text":"This MUST be clearly documented in the API and the reservoir MUST be given the `Attributes` associated with its timeseries point either at construction so that additional sampling performed by the reservoir has access to all attributes from a measurement in the \"offer\" method.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"0879173321cb","level":"MUST","text":"The \"collect\" method MUST return accumulated `Exemplar`s.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"5f71cbaa2317","level":"SHOULD","text":"In other words, Exemplars reported against a metric data point SHOULD have occurred within the start/stop timestamps of that point.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"dc3433d88756","level":"MUST","text":"`Exemplar`s MUST retain any attributes available in the measurement that are not preserved by aggregation or view configuration for the associated timeseries.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"1d6d6df0fc2b","level":"SHOULD","text":"The `ExemplarReservoir` SHOULD avoid allocations when sampling exemplars.","section":"specification/metrics/sdk.md#exemplarreservoir","sectionTitle":"ExemplarReservoir","status":"Mixed","source":"spec"},{"id":"0b5a7fd9e142","level":"SHOULD","text":"SDKs SHOULD use the default value when boundaries are not explicitly provided, unless they have good reasons to use something different (e.g. for backward compatibility reasons in a stable SDK release). | | RecordMinMax | true, false | true | Whether to record min and max. |","section":"specification/metrics/sdk.md#explicit-bucket-histogram-aggregation","sectionTitle":"Explicit Bucket Histogram Aggregation","status":"Mixed","source":"spec"},{"id":"b0b8bf86ae51","level":"MUST","text":"The SDK MUST provide a way for the exporter to get the Meter information (e.g. name, version, etc.) associated with each `Metric Point`.","section":"specification/metrics/sdk.md#exportbatch","sectionTitle":"Export(batch)","status":"Mixed","source":"spec"},{"id":"c50f97aff66a","level":"MUST NOT","text":"`Export` MUST NOT block indefinitely, there MUST be a reasonable upper limit after which the call must time out with an error result (Failure).","section":"specification/metrics/sdk.md#exportbatch","sectionTitle":"Export(batch)","status":"Mixed","source":"spec"},{"id":"7743e6201ff6","level":"SHOULD NOT","text":"The default SDK SHOULD NOT implement retry logic, as the required logic is likely to depend heavily on the specific protocol and backend the metrics are being sent to.","section":"specification/metrics/sdk.md#exportbatch","sectionTitle":"Export(batch)","status":"Mixed","source":"spec"},{"id":"cb8fa75e8376","level":"MUST","text":"`ForceFlush` MUST invoke `ForceFlush` on all registered MetricReader instances that implement `ForceFlush`.","section":"specification/metrics/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"f258d15b2f71","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"9241c18a72fb","level":"SHOULD","text":"`ForceFlush` SHOULD return some ERROR status if there is an error condition; and if there is no error condition, it should return some NO ERROR status, language implementations MAY decide how to model ERROR and NO ERROR.","section":"specification/metrics/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"f27421c00e5f","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/metrics/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"e8ce04a00133","level":"MAY","text":"`ForceFlush` MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.","section":"specification/metrics/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"61d69b6adb0c","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the flush timeout configurable.","section":"specification/metrics/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"658571967ca2","level":"SHOULD","text":"`ForceFlush` SHOULD collect metrics, split into batches if necessary, call `Export(batch)` on each batch serially, and call `ForceFlush()` on the configured Push Metric Exporter.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"c018c29697a3","level":"SHOULD","text":"`ForceFlush` MAY skip `Export(batch)` calls if the timeout is already expired, but SHOULD still call `ForceFlush()` on the configured Push Metric Exporter even if the timeout has passed.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"361181d44b7e","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"833b4232ddaf","level":"SHOULD","text":"If any `Export(batch)` call fails or times out, or if the configured exporter's `ForceFlush()` fails or times out, `ForceFlush` SHOULD return some ERROR status.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"14cdd1a04991","level":"SHOULD","text":"If all calls succeed, `ForceFlush` SHOULD return some NO ERROR status.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"3ec29c382f99","level":"MAY","text":"Language implementations MAY decide how to model ERROR and NO ERROR.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"0991214dee7a","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"1c9cfa05b873","level":"MAY","text":"`ForceFlush` MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.","section":"specification/metrics/sdk.md#forceflush-1","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"d810a5094a44","level":"SHOULD","text":"This is a hint to ensure that the export of any `Metrics` the exporter has received prior to the call to `ForceFlush` SHOULD be completed as soon as possible, preferably before returning from this method.","section":"specification/metrics/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"21e887ea4a26","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"711290ec0022","level":"SHOULD","text":"`ForceFlush` SHOULD only be called in cases where it is absolutely necessary, such as when using some FaaS providers that may suspend the process after an invocation, but before the exporter exports the completed metrics.","section":"specification/metrics/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"02e083417c04","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/metrics/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"50ad4f354041","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the flush timeout configurable.","section":"specification/metrics/sdk.md#forceflush-2","sectionTitle":"ForceFlush","status":"Mixed","source":"spec"},{"id":"cb7c4c734c6f","level":"REQUIRED","text":"Implementations are REQUIRED to accept the entire normal range of IEEE floating point values (i.e., all values except for +Inf, -Inf and NaN values).","section":"specification/metrics/sdk.md#handle-all-normal-values","sectionTitle":"Handle all normal values","status":"Mixed","source":"spec"},{"id":"bfc75a55a73b","level":"SHOULD NOT","text":"Implementations SHOULD NOT incorporate non-normal values (i.e., +Inf, -Inf, and NaNs) into the `sum`, `min`, and `max` fields, because these values do not map into a valid bucket.","section":"specification/metrics/sdk.md#handle-all-normal-values","sectionTitle":"Handle all normal values","status":"Mixed","source":"spec"},{"id":"72fe6addf640","level":"MAY","text":"Implementations MAY round subnormal values away from zero to the nearest normal value.","section":"specification/metrics/sdk.md#handle-all-normal-values","sectionTitle":"Handle all normal values","status":"Mixed","source":"spec"},{"id":"bf67baae947e","level":"SHOULD NOT","text":"This SHOULD NOT be collected when used with instruments that record negative measurements (e.g. `UpDownCounter` or `ObservableGauge`).","section":"specification/metrics/sdk.md#histogram-aggregations","sectionTitle":"Histogram Aggregations","status":"Mixed","source":"spec"},{"id":"7e24808af188","level":"MUST","text":"If no View matches, or if a matching View selects the default aggregation, the `ExplicitBucketBoundaries` advisory parameter MUST be used.","section":"specification/metrics/sdk.md#instrument-advisory-parameter-explicitbucketboundaries","sectionTitle":"Instrument advisory parameter: `ExplicitBucketBoundaries`","status":"Mixed","source":"spec"},{"id":"63a8acffe5bc","level":"SHOULD","text":"When a Meter creates an instrument, it SHOULD validate the instrument advisory parameters.","section":"specification/metrics/sdk.md#instrument-advisory-parameters","sectionTitle":"Instrument advisory parameters","status":"Mixed","source":"spec"},{"id":"63e149d6d114","level":"SHOULD","text":"If an advisory parameter is not valid, the Meter SHOULD emit an error notifying the user and proceed as if the parameter was not provided.","section":"specification/metrics/sdk.md#instrument-advisory-parameters","sectionTitle":"Instrument advisory parameters","status":"Mixed","source":"spec"},{"id":"39827c26f205","level":"MUST","text":"If multiple identical Instruments are created with different advisory parameters, the Meter MUST return an instrument using the first-seen advisory parameters and log an appropriate error as described in duplicate instrument registrations.","section":"specification/metrics/sdk.md#instrument-advisory-parameters","sectionTitle":"Instrument advisory parameters","status":"Mixed","source":"spec"},{"id":"afc15ca3c1ac","level":"MUST","text":"If both a View and advisory parameters specify the same aspect of the Stream configuration, the setting defined by the View MUST take precedence over the advisory parameters.","section":"specification/metrics/sdk.md#instrument-advisory-parameters","sectionTitle":"Instrument advisory parameters","status":"Mixed","source":"spec"},{"id":"a4f02204867c","level":"MUST","text":"A bound instrument MUST behave identically to calling the equivalent unbound recording operation with the pre-bound Attributes on each measurement.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"4ae733da10de","level":"MUST","text":"Attribute processing and cardinality limit evaluation MUST be performed at bind time.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"78f6029a03ca","level":"MUST","text":"Each call to `Bind` MUST be independently evaluated against the cardinality state at that moment.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"face51672245","level":"MUST","text":"The resolved aggregator MUST be fixed and not change across collection cycles.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"b2ddc143c45b","level":"MUST","text":"Measurements recorded on a bound instrument MUST be candidates for Exemplar sampling.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"e5cb7dce6175","level":"MUST","text":"The Context associated with each recording, whether implicit or explicit, MUST be used for exemplar TraceBased filtering and passed to the ExemplarReservoir offer method.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"4a3e333d7fe0","level":"MUST","text":"The SDK MUST ensure attribute-free recordings on a bound instrument bypass per-recording map lookup.","section":"specification/metrics/sdk.md#instrument-bind","sectionTitle":"Instrument bind","status":"Mixed","source":"spec"},{"id":"c8f2601b657d","level":"SHOULD NOT","text":"When a Meter creates an instrument, it SHOULD NOT validate the instrument description.","section":"specification/metrics/sdk.md#instrument-description","sectionTitle":"Instrument description","status":"Mixed","source":"spec"},{"id":"fc366ec89edc","level":"MUST","text":"If a description is not provided or the description is null, the Meter MUST treat it the same as an empty description string.","section":"specification/metrics/sdk.md#instrument-description","sectionTitle":"Instrument description","status":"Mixed","source":"spec"},{"id":"3e7ad5437338","level":"MUST","text":"The synchronous instrument `Enabled` MUST return `false` when either:","section":"specification/metrics/sdk.md#instrument-enabled","sectionTitle":"Instrument enabled","status":"Mixed","source":"spec"},{"id":"98070bf883fe","level":"SHOULD","text":"Otherwise, it SHOULD return `true`.","section":"specification/metrics/sdk.md#instrument-enabled","sectionTitle":"Instrument enabled","status":"Mixed","source":"spec"},{"id":"e85290b34190","level":"MAY","text":"It MAY return `false` to support additional optimizations and features.","section":"specification/metrics/sdk.md#instrument-enabled","sectionTitle":"Instrument enabled","status":"Mixed","source":"spec"},{"id":"413b78cf35e5","level":"SHOULD","text":"When a Meter creates an instrument, it SHOULD validate the instrument name conforms to the instrument name syntax","section":"specification/metrics/sdk.md#instrument-name","sectionTitle":"Instrument name","status":"Mixed","source":"spec"},{"id":"6bc66c0037a7","level":"SHOULD","text":"If the instrument name does not conform to this syntax, the Meter SHOULD emit an error notifying the user about the invalid name.","section":"specification/metrics/sdk.md#instrument-name","sectionTitle":"Instrument name","status":"Mixed","source":"spec"},{"id":"c59af3f36fa7","level":"SHOULD","text":"Criteria SHOULD be treated as additive.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"aa60f344f15b","level":"MUST","text":"The SDK MUST accept the following criteria:","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"486864c41732","level":"MAY","text":"Additionally, the SDK MAY support wildcard pattern matching for the `name` criterion using the following characters.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"cc35b7955c97","level":"MUST","text":"If the SDK does not support wildcards in general, it MUST still recognize the special single asterisk (`*`) character as matching all Instruments.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"686eca836812","level":"MUST NOT","text":"Therefore, the instrument selection criteria parameter needs to be structured to accept a `name`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"48f7be822ede","level":"MUST NOT","text":"Therefore, the instrument selection criteria parameter needs to be structured to accept a `type`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"cd0d71303596","level":"MUST NOT","text":"Therefore, the instrument selection criteria parameter needs to be structured to accept a `unit`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"42ee2a659b9c","level":"MUST NOT","text":"Therefore, the instrument selection criteria parameter needs to be structured to accept a `metername`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"dfec7a6e74b7","level":"MUST NOT","text":"Therefore, the instrument selection criteria parameter needs to be structured to accept a `meterversion`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"e59cab1170a2","level":"MUST NOT","text":"Therefore, the instrument selection criteria parameter needs to be structured to accept a `meterschemaurl`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"0ee96fbb843a","level":"MAY","text":"The SDK MAY accept additional criteria.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"df977b9e57a1","level":"MUST NOT","text":"Therefore, the instrument selection criteria can be structured to accept the criteria, but MUST NOT obligate a user to provide them.","section":"specification/metrics/sdk.md#instrument-selection-criteria","sectionTitle":"Instrument selection criteria","status":"Mixed","source":"spec"},{"id":"07b09f6fb8e3","level":"SHOULD NOT","text":"When a Meter creates an instrument, it SHOULD NOT validate the instrument unit.","section":"specification/metrics/sdk.md#instrument-unit","sectionTitle":"Instrument unit","status":"Mixed","source":"spec"},{"id":"5f13492dbb60","level":"MUST","text":"If a unit is not provided or the unit is null, the Meter MUST treat it the same as an empty unit string.","section":"specification/metrics/sdk.md#instrument-unit","sectionTitle":"Instrument unit","status":"Mixed","source":"spec"},{"id":"764be411a402","level":"MUST","text":"A Push Metric Exporter MUST support the following functions:","section":"specification/metrics/sdk.md#interface-definition","sectionTitle":"Interface Definition","status":"Mixed","source":"spec"},{"id":"80688ecbd9b5","level":"MUST","text":"A `MetricProducer` MUST support the following functions:","section":"specification/metrics/sdk.md#interface-definition-1","sectionTitle":"Interface Definition","status":"Mixed","source":"spec"},{"id":"555f567ca4d2","level":"MUST","text":"A `MetricFilter` MUST support the following functions:","section":"specification/metrics/sdk.md#interface-definition-2","sectionTitle":"Interface Definition","status":"Mixed","source":"spec"},{"id":"43e8cb55ef9a","level":"SHOULD","text":"Implementations SHOULD adjust the histogram scale as necessary to maintain the best resolution possible, within the constraint of maximum size (max number of buckets).","section":"specification/metrics/sdk.md#maintain-the-ideal-scale","sectionTitle":"Maintain the ideal scale","status":"Mixed","source":"spec"},{"id":"85065748ed42","level":"SHOULD","text":"The SDK SHOULD use the following logic to determine how to process Measurements made with an Instrument:","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"7691a8a5cc45","level":"MUST","text":"Instrument advisory parameters, if any, MUST be honored.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"9eb490adbd1b","level":"SHOULD","text":"If applying the View results in conflicting metric identities the implementation SHOULD apply the View and emit a warning.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"1ec0b6412639","level":"SHOULD","text":"If applying the View would produce semantic errors (for example, configuring an asynchronous instrument to use the Explicit bucket histogram aggregation), the implementation SHOULD emit a warning and proceed as if that View did not exist.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"a028f6a5e3a7","level":"MUST","text":"If both the View and Instrument advisory parameters specify the same aspect of the Stream configuration, the setting defined by the View MUST take precedence over the advisory parameters.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"2c749c8136db","level":"SHOULD","text":"If a setting selected for the stream would produce semantic errors, the implementation SHOULD emit a warning and use the next valid setting for that aspect from a preceding View in the same group, or the Instrument default if no preceding View specifies a valid setting.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"8f08c98deb3e","level":"MUST","text":"If both the matching Views and Instrument advisory parameters specify the same aspect of the Stream configuration, the setting defined by the Views MUST take precedence over the advisory parameters.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"c3614799ee57","level":"SHOULD","text":"If the Instrument could not match with any of the registered `View`(s), the SDK SHOULD enable the instrument using the default aggregation and temporality.","section":"specification/metrics/sdk.md#measurement-processing","sectionTitle":"Measurement processing","status":"Mixed","source":"spec"},{"id":"1a271a3481ac","level":"MUST","text":"Distinct meters MUST be treated as separate namespaces for the purposes of detecting duplicate instrument registrations.","section":"specification/metrics/sdk.md#meter","sectionTitle":"Meter","status":"Mixed","source":"spec"},{"id":"c18d2f0fcac7","level":"MUST","text":"Status: Development - `Meter` MUST behave according to the MeterConfig computed during Meter creation.","section":"specification/metrics/sdk.md#meter","sectionTitle":"Meter","status":"Mixed","source":"spec"},{"id":"81b210b5b73d","level":"MUST","text":"If the `MeterProvider` supports updating the MeterConfigurator, then upon update the `Meter` MUST be updated to behave according to the new `MeterConfig`.","section":"specification/metrics/sdk.md#meter","sectionTitle":"Meter","status":"Mixed","source":"spec"},{"id":"3cfc4b12c3e1","level":"SHOULD","text":"It SHOULD only be possible to create `Meter` instances through a `MeterProvider` (see API).","section":"specification/metrics/sdk.md#meter-creation","sectionTitle":"Meter Creation","status":"Mixed","source":"spec"},{"id":"6138501b0f00","level":"MUST","text":"The `MeterProvider` MUST implement the Get a Meter API.","section":"specification/metrics/sdk.md#meter-creation","sectionTitle":"Meter Creation","status":"Mixed","source":"spec"},{"id":"397416aeaa7a","level":"MUST","text":"The input provided by the user MUST be used to create an `InstrumentationScope` instance which is stored on the created `Meter`.","section":"specification/metrics/sdk.md#meter-creation","sectionTitle":"Meter Creation","status":"Mixed","source":"spec"},{"id":"6afa30909b84","level":"MUST","text":"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.","section":"specification/metrics/sdk.md#meter-creation","sectionTitle":"Meter Creation","status":"Mixed","source":"spec"},{"id":"017231ef25f8","level":"MUST","text":"Status: Development - The `MeterProvider` MUST compute the relevant MeterConfig using the configured MeterConfigurator, and create a `Meter` whose behavior conforms to that `MeterConfig`.","section":"specification/metrics/sdk.md#meter-creation","sectionTitle":"Meter Creation","status":"Mixed","source":"spec"},{"id":"1c9ce30da915","level":"SHOULD","text":"If not explicitly set, the `enabled` parameter SHOULD default to `true` ( i.e. `Meter`s are enabled by default).","section":"specification/metrics/sdk.md#meterconfig","sectionTitle":"MeterConfig","status":"Mixed","source":"spec"},{"id":"cc589b179331","level":"MUST","text":"If a `Meter` is disabled, it MUST behave equivalently to No-op Meter.","section":"specification/metrics/sdk.md#meterconfig","sectionTitle":"MeterConfig","status":"Mixed","source":"spec"},{"id":"295d89ebdc38","level":"MUST","text":"The value of `enabled` MUST be used to resolve whether an instrument is Enabled.","section":"specification/metrics/sdk.md#meterconfig","sectionTitle":"MeterConfig","status":"Mixed","source":"spec"},{"id":"fe41e7afc97f","level":"MUST","text":"However, the changes MUST be eventually visible.","section":"specification/metrics/sdk.md#meterconfig","sectionTitle":"MeterConfig","status":"Mixed","source":"spec"},{"id":"e228a3f58ad2","level":"MUST","text":"The function MUST accept the following parameter:","section":"specification/metrics/sdk.md#meterconfigurator","sectionTitle":"MeterConfigurator","status":"Mixed","source":"spec"},{"id":"1fac78c7d6e4","level":"MUST","text":"The function MUST return the relevant `MeterConfig`, or some signal indicating that the default MeterConfig should be used.","section":"specification/metrics/sdk.md#meterconfigurator","sectionTitle":"MeterConfigurator","status":"Mixed","source":"spec"},{"id":"acafad8e80ba","level":"MAY","text":"This signal MAY be nil, null, empty, or an instance of the default `MeterConfig` depending on what is idiomatic in the language.","section":"specification/metrics/sdk.md#meterconfigurator","sectionTitle":"MeterConfigurator","status":"Mixed","source":"spec"},{"id":"0252cbd17154","level":"MAY","text":"However, implementations MAY provide shorthand or helper functions to accommodate common use cases:","section":"specification/metrics/sdk.md#meterconfigurator","sectionTitle":"MeterConfigurator","status":"Mixed","source":"spec"},{"id":"326d6be0bb64","level":"MUST","text":"A `MeterProvider` MUST provide a way to allow a Resource to be specified.","section":"specification/metrics/sdk.md#meterprovider","sectionTitle":"MeterProvider","status":"Mixed","source":"spec"},{"id":"b66dc2fd0569","level":"SHOULD","text":"If a `Resource` is specified, it SHOULD be associated with all the metrics produced by any `Meter` from the `MeterProvider`.","section":"specification/metrics/sdk.md#meterprovider","sectionTitle":"MeterProvider","status":"Mixed","source":"spec"},{"id":"29744c18d4c0","level":"SHOULD","text":"The SDK SHOULD allow the creation of multiple independent `MeterProvider`s.","section":"specification/metrics/sdk.md#meterprovider-creation","sectionTitle":"MeterProvider Creation","status":"Mixed","source":"spec"},{"id":"299192b91913","level":"MUST","text":"`MetricExporter` defines the interface that protocol-specific exporters MUST implement so that they can be plugged into OpenTelemetry SDK and support sending of telemetry data.","section":"specification/metrics/sdk.md#metricexporter","sectionTitle":"MetricExporter","status":"Mixed","source":"spec"},{"id":"37daa4e4e791","level":"MAY","text":"OpenTelemetry language implementations MAY support automatically configuring the MetricReader to use for an Exporter.","section":"specification/metrics/sdk.md#metricexporter","sectionTitle":"MetricExporter","status":"Mixed","source":"spec"},{"id":"9a2f8ce8745f","level":"SHOULD","text":"Metric Exporters SHOULD report an error condition for data output by the `MetricReader` with unsupported Aggregation or Aggregation Temporality, as this condition can be corrected by a change of `MetricReader` configuration.","section":"specification/metrics/sdk.md#metricexporter","sectionTitle":"MetricExporter","status":"Mixed","source":"spec"},{"id":"0862216c1493","level":"MUST","text":"`MetricProducer` defines the interface which bridges to third-party metric sources MUST implement, so they can be plugged into an OpenTelemetry MetricReader as a source of aggregated metric data.","section":"specification/metrics/sdk.md#metricproducer","sectionTitle":"MetricProducer","status":"Mixed","source":"spec"},{"id":"8513d11be611","level":"MAY","text":"The SDK's in-memory state MAY implement the `MetricProducer` interface for convenience.","section":"specification/metrics/sdk.md#metricproducer","sectionTitle":"MetricProducer","status":"Mixed","source":"spec"},{"id":"1ab3fd5d54a3","level":"SHOULD","text":"`MetricProducer` implementations SHOULD accept configuration for the `AggregationTemporality` of produced metrics.","section":"specification/metrics/sdk.md#metricproducer","sectionTitle":"MetricProducer","status":"Mixed","source":"spec"},{"id":"82588d00a61e","level":"MAY","text":"SDK authors MAY provide utility libraries to facilitate conversion between delta and cumulative temporalities.","section":"specification/metrics/sdk.md#metricproducer","sectionTitle":"MetricProducer","status":"Mixed","source":"spec"},{"id":"b6e142751651","level":"SHOULD","text":"To construct a `MetricReader` when setting up an SDK, at least the following SHOULD be provided:","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"f82bf0a1791d","level":"SHOULD","text":"This function SHOULD be obtained from the `exporter`.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"f1ead1bed119","level":"SHOULD","text":"If not configured, the default aggregation SHOULD be used.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"5b9cf46ea21c","level":"SHOULD","text":"If not configured, the Cumulative temporality SHOULD be used.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"528e5e7981c2","level":"SHOULD","text":"If not configured, a default value of 2000 SHOULD be used.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"0d8a1f2c5890","level":"SHOULD","text":"Status: Development - A `MetricReader` SHOULD provide the MetricFilter to the SDK or registered MetricProducer(s) when calling the `Produce` operation.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"579640c8e199","level":"SHOULD","text":"A common implementation of `MetricReader`, the periodic exporting `MetricReader` SHOULD be provided to be used typically with push-based metrics collection.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"991bf429874a","level":"MUST","text":"The `MetricReader` MUST ensure that data points from OpenTelemetry instruments are output in the configured aggregation temporality for each instrument kind.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"a87bc8c69214","level":"MUST","text":"For synchronous instruments with Cumulative aggregation temporality, MetricReader.Collect MUST receive data points exposed in previous collections regardless of whether new measurements have been recorded.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"25300dd5d965","level":"MUST","text":"For synchronous instruments with Delta aggregation temporality, MetricReader.Collect MUST only receive data points with measurements recorded since the previous collection.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"533f45d78105","level":"MUST","text":"For asynchronous instruments with Delta or Cumulative aggregation temporality, MetricReader.Collect MUST only receive data points with measurements recorded since the previous collection.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"f485bc302c0c","level":"MUST","text":"For instruments with Cumulative aggregation temporality, successive data points received by successive calls to MetricReader.Collect MUST repeat the same starting timestamps (e.g. `(T0, T1], (T0, T2], (T0, T3]`).","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"c9a3e54d16bc","level":"MUST","text":"For instruments with Delta aggregation temporality, successive data points received by successive calls to MetricReader.Collect MUST advance the starting timestamp ( e.g. `(T0, T1], (T1, T2], (T2, T3]`).","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"d8994e1ebca1","level":"MUST","text":"The ending timestamp (i.e. `TimeUnixNano`) MUST always be equal to time the metric data point took effect, which is equal to when MetricReader.Collect was invoked.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"abb7ef33d6c8","level":"SHOULD NOT","text":"The SDK MUST support multiple `MetricReader` instances to be registered on the same `MeterProvider`, and the MetricReader.Collect invocation on one `MetricReader` instance SHOULD NOT introduce side-effects to other `MetricReader` instances.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"27f1be885312","level":"MUST NOT","text":"The SDK MUST NOT allow a `MetricReader` instance to be registered on more than one `MeterProvider` instance.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"df7bf968e054","level":"SHOULD","text":"The SDK SHOULD provide a way to allow `MetricReader` to respond to MeterProvider.ForceFlush and MeterProvider.Shutdown.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"3a2edb4c41dc","level":"MAY","text":"OpenTelemetry SDK authors MAY decide the language idiomatic approach, for example, as `OnForceFlush` and `OnShutdown` callback functions.","section":"specification/metrics/sdk.md#metricreader","sectionTitle":"MetricReader","status":"Mixed","source":"spec"},{"id":"ca88e0a297c0","level":"MUST","text":"All language implementations of OpenTelemetry MUST provide an SDK.","section":"specification/metrics/sdk.md#metrics-sdk","sectionTitle":"Metrics SDK","status":"Mixed","source":"spec"},{"id":"3fc5fd579f08","level":"MUST","text":"When this happens, the Meter MUST return an instrument using the first-seen instrument name and log an appropriate error as described above.","section":"specification/metrics/sdk.md#name-conflict","sectionTitle":"Name conflict","status":"Mixed","source":"spec"},{"id":"3a460bbbc18b","level":"MUST","text":"The SDK MUST handle numerical limits in a graceful way according to Error handling in OpenTelemetry.","section":"specification/metrics/sdk.md#numerical-limits-handling","sectionTitle":"Numerical limits handling","status":"Mixed","source":"spec"},{"id":"123ee453ee9a","level":"MUST","text":"If the SDK receives float/double values from Instruments, it MUST handle all the possible values.","section":"specification/metrics/sdk.md#numerical-limits-handling","sectionTitle":"Numerical limits handling","status":"Mixed","source":"spec"},{"id":"fc5f196f3edd","level":"MAY","text":"The SDK authors MAY leverage/follow the language runtime behavior for better performance, rather than perform a check on each value coming from the API.","section":"specification/metrics/sdk.md#numerical-limits-handling","sectionTitle":"Numerical limits handling","status":"Mixed","source":"spec"},{"id":"80f21d15a4a9","level":"MAY","text":"The SDK authors MAY rely on the language runtime behavior as long as errors/exceptions are taken care of.","section":"specification/metrics/sdk.md#numerical-limits-handling","sectionTitle":"Numerical limits handling","status":"Mixed","source":"spec"},{"id":"d22e6478fd05","level":"MUST","text":"Callback functions MUST be invoked for the specific `MetricReader` performing collection, such that observations made or produced by executing callbacks only apply to the intended `MetricReader` during collection.","section":"specification/metrics/sdk.md#observations-inside-asynchronous-callbacks","sectionTitle":"Observations inside asynchronous callbacks","status":"Mixed","source":"spec"},{"id":"6377f86a7646","level":"SHOULD","text":"The implementation SHOULD disregard the use of asynchronous instrument APIs outside of registered callbacks.","section":"specification/metrics/sdk.md#observations-inside-asynchronous-callbacks","sectionTitle":"Observations inside asynchronous callbacks","status":"Mixed","source":"spec"},{"id":"88d1b9645e3b","level":"SHOULD","text":"The implementation SHOULD use a timeout to prevent indefinite callback execution.","section":"specification/metrics/sdk.md#observations-inside-asynchronous-callbacks","sectionTitle":"Observations inside asynchronous callbacks","status":"Mixed","source":"spec"},{"id":"9b9f5d880ccf","level":"MUST","text":"The implementation MUST complete the execution of all callbacks for a given instrument before starting a subsequent round of collection.","section":"specification/metrics/sdk.md#observations-inside-asynchronous-callbacks","sectionTitle":"Observations inside asynchronous callbacks","status":"Mixed","source":"spec"},{"id":"be4621aec527","level":"SHOULD NOT","text":"The implementation SHOULD NOT produce aggregated metric data for a previously-observed attribute set which is not observed during a successful callback.","section":"specification/metrics/sdk.md#observations-inside-asynchronous-callbacks","sectionTitle":"Observations inside asynchronous callbacks","status":"Mixed","source":"spec"},{"id":"36e80dc37313","level":"MUST","text":"The SDK MUST create an Aggregator with the overflow attribute set prior to reaching the cardinality limit and use it to aggregate Measurements for which the correct Aggregator could not be created.","section":"specification/metrics/sdk.md#overflow-attribute","sectionTitle":"Overflow attribute","status":"Mixed","source":"spec"},{"id":"1fad7ef0b4d2","level":"MUST","text":"The SDK MUST provide the guarantee that overflow would not happen if the maximum number of distinct, non-overflow attribute sets is less than or equal to the limit.","section":"specification/metrics/sdk.md#overflow-attribute","sectionTitle":"Overflow attribute","status":"Mixed","source":"spec"},{"id":"e994243b13ae","level":"MUST","text":"When `maxExportBatchSize` is configured, the reader MUST ensure no batch provided to `Export` exceeds the `maxExportBatchSize` by splitting the batch of metric data points into smaller batches.","section":"specification/metrics/sdk.md#periodic-exporting-metricreader","sectionTitle":"Periodic exporting MetricReader","status":"Mixed","source":"spec"},{"id":"63e264685a86","level":"MUST","text":"The initial batch of metric data MUST be split into as many \"full\" batches of size `maxExportBatchSize` as possible -- even if this splits up data points that belong to the same metric into different batches.","section":"specification/metrics/sdk.md#periodic-exporting-metricreader","sectionTitle":"Periodic exporting MetricReader","status":"Mixed","source":"spec"},{"id":"a06e93848533","level":"MUST","text":"The reader MUST ensure all batches produced from a single `Collect()` are provided to `Export` serially and in-order before metric data points from a subsequent `Collect()` are provided.","section":"specification/metrics/sdk.md#periodic-exporting-metricreader","sectionTitle":"Periodic exporting MetricReader","status":"Mixed","source":"spec"},{"id":"9a23b1f4bc35","level":"MUST NOT","text":"The reader MUST NOT combine metrics from different `Collect()` calls into the same batch provided to `Export`.","section":"specification/metrics/sdk.md#periodic-exporting-metricreader","sectionTitle":"Periodic exporting MetricReader","status":"Mixed","source":"spec"},{"id":"200b0e8af20c","level":"MUST","text":"The reader MUST synchronize calls to `MetricExporter`'s `Export` to make sure that they are not invoked concurrently.","section":"specification/metrics/sdk.md#periodic-exporting-metricreader","sectionTitle":"Periodic exporting MetricReader","status":"Mixed","source":"spec"},{"id":"304284f6f78f","level":"MUST","text":"If an export is still in progress when the next scheduled interval occurs, the reader MUST either delay the subsequent collection and export until the in-progress export finishes, or skip the scheduled collection for that interval.","section":"specification/metrics/sdk.md#periodic-exporting-metricreader","sectionTitle":"Periodic exporting MetricReader","status":"Mixed","source":"spec"},{"id":"8d9ed75c3f25","level":"MUST","text":"`Produce` MUST return a batch of Metric Points, filtered by the optional `metricFilter` parameter.","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"4369007122d7","level":"SHOULD","text":"Implementation SHOULD use the filter as early as possible to gain as much performance gain possible (memory allocation, internal metric fetching, etc).","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"72679565ad09","level":"SHOULD","text":"If the batch of Metric Points includes resource information, `Produce` SHOULD require a resource as a parameter.","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"406c0cad6156","level":"MAY","text":"`Produce` does not have any other required parameters, however, OpenTelemetry SDK authors MAY choose to add required or optional parameters (e.g. timeout).","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"c6094066d61e","level":"SHOULD","text":"`Produce` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"c9a637279fa3","level":"MAY","text":"When the `Produce` operation fails, the `MetricProducer` MAY return successfully collected results and a failed reasons list to the caller.","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"81a6b7776e13","level":"SHOULD","text":"If a batch of Metric Points can include `InstrumentationScope` information, `Produce` SHOULD include a single InstrumentationScope which identifies the `MetricProducer`.","section":"specification/metrics/sdk.md#produce-batch","sectionTitle":"Produce batch","status":"Mixed","source":"spec"},{"id":"b29593e695b0","level":"MAY","text":"Implementors MAY choose the best idiomatic design for their language.","section":"specification/metrics/sdk.md#pull-metric-exporter","sectionTitle":"Pull Metric Exporter","status":"Mixed","source":"spec"},{"id":"b41bb9eeff7f","level":"MAY","text":"If the pull exporter is modeled as MetricReader, implementors MAY name the MetricExporter interface as PushMetricExporter to prevent naming confusion.","section":"specification/metrics/sdk.md#pull-metric-exporter","sectionTitle":"Pull Metric Exporter","status":"Mixed","source":"spec"},{"id":"ed2577c70fa0","level":"MAY","text":"This MAY be accomplished by pairing the exporter with a periodic exporting MetricReader.","section":"specification/metrics/sdk.md#push-metric-exporter","sectionTitle":"Push Metric Exporter","status":"Mixed","source":"spec"},{"id":"96cf452c9e9e","level":"SHOULD","text":"The Metrics SDK SHOULD support SDK self-observability.","section":"specification/metrics/sdk.md#self-observability","sectionTitle":"Self-observability","status":"Mixed","source":"spec"},{"id":"4635f37cd317","level":"MUST","text":"`Shutdown` MUST be called only once for each `MeterProvider` instance.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"69d59464b208","level":"SHOULD","text":"SDKs SHOULD return a valid no-op Meter for these calls, if possible.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"0d36439a91d4","level":"SHOULD","text":"`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"0ca07f123307","level":"SHOULD","text":"`Shutdown` SHOULD complete or abort within some timeout.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"324a7ba85933","level":"MAY","text":"`Shutdown` MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"4ce8bffc3a06","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the shutdown timeout configurable.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"0d646088c587","level":"MUST","text":"`Shutdown` MUST be implemented at least by invoking `Shutdown` on all registered MetricReader and MetricExporter instances.","section":"specification/metrics/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"c596ab8d7a68","level":"MUST","text":"`Shutdown` MUST be called only once for each `MetricReader` instance.","section":"specification/metrics/sdk.md#shutdown-1","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"aad212583f88","level":"SHOULD","text":"SDKs SHOULD return some failure for these calls, if possible.","section":"specification/metrics/sdk.md#shutdown-1","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"aa26527d0780","level":"SHOULD","text":"`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/metrics/sdk.md#shutdown-1","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"41e98363a3d7","level":"SHOULD","text":"`Shutdown` SHOULD complete or abort within some timeout.","section":"specification/metrics/sdk.md#shutdown-1","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"739ce57e238b","level":"MAY","text":"`Shutdown` MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.","section":"specification/metrics/sdk.md#shutdown-1","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"8c4f8f70f541","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the shutdown timeout configurable.","section":"specification/metrics/sdk.md#shutdown-1","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"95044280224a","level":"SHOULD","text":"Shutdown SHOULD be called only once for each `MetricExporter` instance.","section":"specification/metrics/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"057583262d9b","level":"SHOULD NOT","text":"`Shutdown` SHOULD NOT block indefinitely (e.g. if it attempts to flush the data and the destination is unavailable).","section":"specification/metrics/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"42e7adf344cf","level":"MAY","text":"OpenTelemetry SDK authors MAY decide if they want to make the shutdown timeout configurable.","section":"specification/metrics/sdk.md#shutdown-2","sectionTitle":"Shutdown","status":"Mixed","source":"spec"},{"id":"49fed364e259","level":"MUST","text":"This reservoir MUST use a uniformly-weighted sampling algorithm based on the number of samples the reservoir has seen so far to determine if the offered measurements should be sampled.","section":"specification/metrics/sdk.md#simplefixedsizeexemplarreservoir","sectionTitle":"SimpleFixedSizeExemplarReservoir","status":"Mixed","source":"spec"},{"id":"42dfeb5e0559","level":"SHOULD","text":"Any stateful portion of sampling computation SHOULD be reset every collection cycle.","section":"specification/metrics/sdk.md#simplefixedsizeexemplarreservoir","sectionTitle":"SimpleFixedSizeExemplarReservoir","status":"Mixed","source":"spec"},{"id":"317172af55ef","level":"MAY","text":"This Exemplar reservoir MAY take a configuration parameter for the size of the reservoir.","section":"specification/metrics/sdk.md#simplefixedsizeexemplarreservoir","sectionTitle":"SimpleFixedSizeExemplarReservoir","status":"Mixed","source":"spec"},{"id":"10deb1c98f19","level":"MAY","text":"If no size configuration is provided, the default size MAY be the number of possible concurrent threads (e.g., number of CPUs) to help reduce contention.","section":"specification/metrics/sdk.md#simplefixedsizeexemplarreservoir","sectionTitle":"SimpleFixedSizeExemplarReservoir","status":"Mixed","source":"spec"},{"id":"bbabed2d8c06","level":"SHOULD","text":"Otherwise, a default size of `1` SHOULD be used.","section":"specification/metrics/sdk.md#simplefixedsizeexemplarreservoir","sectionTitle":"SimpleFixedSizeExemplarReservoir","status":"Mixed","source":"spec"},{"id":"cce8eca3e22b","level":"MUST","text":"For delta aggregations, the start timestamp MUST equal the previous collection interval's timestamp, or the creation time of the instrument if this is the first collection interval for the instrument.","section":"specification/metrics/sdk.md#start-timestamps","sectionTitle":"Start timestamps","status":"Mixed","source":"spec"},{"id":"412fc07accb1","level":"MUST","text":"This implies that all data points with delta temporality aggregation for an instrument MUST share the same start timestamp.","section":"specification/metrics/sdk.md#start-timestamps","sectionTitle":"Start timestamps","status":"Mixed","source":"spec"},{"id":"704294813b63","level":"MUST","text":"Cumulative timeseries MUST use a consistent start timestamp for all collection intervals.","section":"specification/metrics/sdk.md#start-timestamps","sectionTitle":"Start timestamps","status":"Mixed","source":"spec"},{"id":"f2b9dc2ecbc8","level":"SHOULD","text":"For synchronous instruments, the start timestamp SHOULD be the time of the first measurement for the series.","section":"specification/metrics/sdk.md#start-timestamps","sectionTitle":"Start timestamps","status":"Mixed","source":"spec"},{"id":"014cf1cd07ae","level":"SHOULD","text":"For asynchronous instrument, the start timestamp SHOULD be:","section":"specification/metrics/sdk.md#start-timestamps","sectionTitle":"Start timestamps","status":"Mixed","source":"spec"},{"id":"5716177ff417","level":"MUST","text":"The SDK MUST accept the following stream configuration parameters:","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"c9b3dc49e1cf","level":"SHOULD","text":"`name`: The metric stream name that SHOULD be used.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"db0470ee9e08","level":"SHOULD","text":"In order to avoid conflicts, if a `name` is provided the View SHOULD have an instrument selector that selects at most one instrument.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"ea21f2b1d7f2","level":"MAY","text":"If the Instrument selection criteria for a View with a stream configuration `name` parameter can select more than one instrument (i.e. wildcards) the SDK MAY fail fast in accordance with initialization error handling principles.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"3c590e6e9900","level":"MUST NOT","text":"Therefore, the stream configuration parameter needs to be structured to accept a `name`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"83234ece8170","level":"MUST","text":"If the user does not provide a `name` value, name from the Instrument the View matches MUST be used by default.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"bd4242fdc172","level":"MUST NOT","text":"The `name` provided via stream configuration is NOT REQUIRED to conform to the instrument name syntax, and the SDK MUST NOT validate it against that syntax.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"ec6c93dd11ed","level":"SHOULD","text":"`description`: The metric stream description that SHOULD be used.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"41b451ae04cb","level":"MUST NOT","text":"Therefore, the stream configuration parameter needs to be structured to accept a `description`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"b3f3359d1064","level":"MUST","text":"If the user does not provide a `description` value, the description from the Instrument a View matches MUST be used by default.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"a941d5482340","level":"MUST","text":"The allow-list contains attribute keys that identify the attributes that MUST be kept, and all other attributes MUST be ignored.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"110b6c44b297","level":"MAY","text":"Implementations MAY accept additional attribute filtering functionality for this parameter.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"1fba79cfca1a","level":"MUST NOT","text":"Therefore, the stream configuration parameter needs to be structured to accept `attributekeys`, but MUST NOT obligate a user to provide them.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"195b51214e28","level":"SHOULD","text":"If the user does not provide any value, the SDK SHOULD use the `Attributes` advisory parameter configured on the instrument instead.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"1958df9f74cf","level":"MUST","text":"If the `Attributes` advisory parameter is absent, all attributes MUST be kept.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"0d5ebd1da260","level":"SHOULD","text":"Additionally, implementations SHOULD support configuring an exclude-list of attribute keys.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"fe744ea4669c","level":"MUST","text":"The exclude-list contains attribute keys that identify the attributes that MUST be excluded, all other attributes MUST be kept.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"a3544c80dde5","level":"MAY","text":"If an attribute key is both included and excluded, the SDK MAY fail fast in accordance with initialization error handling principles.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"93d04a2e6d46","level":"SHOULD","text":"SDK documentation SHOULD inform users that attributes excluded from a metric stream by View configuration may still be exported on Exemplars as filtered attributes, and describe how to disable or otherwise configure Exemplar sampling.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"9c536db50b54","level":"MUST NOT","text":"Therefore, the stream configuration parameter needs to be structured to accept an `aggregation`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"52401c4efaef","level":"MUST","text":"If the user does not provide an `aggregation` value, the `MeterProvider` MUST apply a default aggregation configurable on the basis of instrument type according to the MetricReader instance.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"dcbafa1b083e","level":"MUST NOT","text":"Therefore, the stream configuration parameter needs to be structured to accept an `exemplarreservoir`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"642f5289856d","level":"MUST","text":"If the user does not provide an `exemplar_reservoir` value, the `MeterProvider` MUST apply a default exemplar reservoir.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"70f7bd5e8d2f","level":"MUST NOT","text":"Therefore, the stream configuration parameter needs to be structured to accept an `aggregationcardinalitylimit`, but MUST NOT obligate a user to provide one.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"81fd5ce625b5","level":"MUST","text":"If the user does not provide an `aggregationcardinalitylimit` value, the `MeterProvider` MUST apply the default aggregation cardinality limit the `MetricReader` is configured with.","section":"specification/metrics/sdk.md#stream-configuration","sectionTitle":"Stream configuration","status":"Mixed","source":"spec"},{"id":"856a5d4b9c06","level":"MUST","text":"The implementation MUST maintain reasonable minimum and maximum scale parameters that the automatic scale parameter will not exceed.","section":"specification/metrics/sdk.md#support-a-minimum-and-maximum-scale","sectionTitle":"Support a minimum and maximum scale","status":"Mixed","source":"spec"},{"id":"c96e768e6cef","level":"MUST","text":"Aggregators for synchronous instruments with cumulative temporality MUST continue to export all attribute sets that were observed prior to the beginning of overflow.","section":"specification/metrics/sdk.md#synchronous-instrument-cardinality-limits","sectionTitle":"Synchronous instrument cardinality limits","status":"Mixed","source":"spec"},{"id":"152b251cd6d0","level":"MAY","text":"Aggregators of synchronous instruments with delta aggregation temporality MAY choose an arbitrary subset of attribute sets to output to maintain the stated cardinality limit.","section":"specification/metrics/sdk.md#synchronous-instrument-cardinality-limits","sectionTitle":"Synchronous instrument cardinality limits","status":"Mixed","source":"spec"},{"id":"b83b22705b88","level":"MUST","text":"Regardless of aggregation temporality, the SDK MUST ensure that every Measurement is reflected in exactly one Aggregator, which is either an Aggregator associated with the correct attribute set or an aggregator associated with the overflow attribute set.","section":"specification/metrics/sdk.md#synchronous-instrument-cardinality-limits","sectionTitle":"Synchronous instrument cardinality limits","status":"Mixed","source":"spec"},{"id":"b9c4b6803b21","level":"MUST NOT","text":"Measurements MUST NOT be double-counted or dropped during an overflow.","section":"specification/metrics/sdk.md#synchronous-instrument-cardinality-limits","sectionTitle":"Synchronous instrument cardinality limits","status":"Mixed","source":"spec"},{"id":"266ae55374bd","level":"SHOULD","text":"When the histogram contains not more than one value in either of the positive or negative ranges, the implementation SHOULD use the maximum scale.","section":"specification/metrics/sdk.md#use-the-maximum-scale-for-single-measurements","sectionTitle":"Use the maximum scale for single measurements","status":"Mixed","source":"spec"},{"id":"e74ae8992395","level":"MUST","text":"The SDK MUST provide functionality for a user to create Views for a `MeterProvider`.","section":"specification/metrics/sdk.md#view","sectionTitle":"View","status":"Mixed","source":"spec"},{"id":"0715ed04d9a5","level":"MUST","text":"This functionality MUST accept as inputs the Instrument selection criteria and the resulting stream configuration.","section":"specification/metrics/sdk.md#view","sectionTitle":"View","status":"Mixed","source":"spec"},{"id":"e1366699d15f","level":"MUST","text":"The SDK MUST provide the means to register Views with a `MeterProvider`.","section":"specification/metrics/sdk.md#view","sectionTitle":"View","status":"Mixed","source":"spec"},{"id":"9a9d4275d875","level":"MAY","text":"A `MeterProvider` MAY accept a `viewmatchingmode` parameter which controls how multiple matching Views are applied to an Instrument.","section":"specification/metrics/sdk.md#view-matching-mode","sectionTitle":"View matching mode","status":"Mixed","source":"spec"},{"id":"96ff766e7dd4","level":"MUST","text":"A `MeterProvider` that accepts this parameter MUST support the following values:","section":"specification/metrics/sdk.md#view-matching-mode","sectionTitle":"View matching mode","status":"Mixed","source":"spec"},{"id":"1f993a1e5714","level":"MUST","text":"If `viewmatchingmode` is not specified, the SDK MUST use `independent`.","section":"specification/metrics/sdk.md#view-matching-mode","sectionTitle":"View matching mode","status":"Mixed","source":"spec"},{"id":"76f43cbbac32","level":"MUST","text":"Any other value MUST be treated as unsupported.","section":"specification/metrics/sdk.md#view-matching-mode","sectionTitle":"View matching mode","status":"Mixed","source":"spec"},{"id":"9ba04aa4fdcb","level":"MUST","text":"If an unsupported value is provided, the SDK MUST either fail fast during initialization in accordance with the error handling principles, or emit a warning, ignore the value, and use `independent`.","section":"specification/metrics/sdk.md#view-matching-mode","sectionTitle":"View matching mode","status":"Mixed","source":"spec"},{"id":"83fd415d4711","level":"MUST NOT","text":"Instrumentation authors MUST NOT directly reference any SDK package of any kind, only the API.","section":"specification/overview.md#sdk","sectionTitle":"SDK","status":"Unspecified","source":"spec"},{"id":"5f25638e7f42","level":"SHOULD","text":"Both the collector and the client libraries SHOULD autogenerate semantic convention keys and enum values into constants (or language idiomatic equivalent).","section":"specification/overview.md#semantic-conventions","sectionTitle":"Semantic Conventions","status":"Unspecified","source":"spec"},{"id":"0bcf4f571b55","level":"MUST","text":"The YAML files MUST be used as the source of truth for generation.","section":"specification/overview.md#semantic-conventions","sectionTitle":"Semantic Conventions","status":"Unspecified","source":"spec"},{"id":"c90403ee4760","level":"SHOULD","text":"Each language implementation SHOULD provide language-specific support to the code generator.","section":"specification/overview.md#semantic-conventions","sectionTitle":"Semantic Conventions","status":"Unspecified","source":"spec"},{"id":"fdea69580f21","level":"MUST","text":"Represents all the information that identifies Span in the Trace and MUST be propagated to child Spans and across process boundaries.","section":"specification/overview.md#spancontext","sectionTitle":"SpanContext","status":"Unspecified","source":"spec"},{"id":"f7b163654c58","level":"MUST","text":"A message representing a `Mapping` MUST have at least one of the following process attributes:","section":"specification/profiles/mappings.md#attributes","sectionTitle":"Attributes","status":"Alpha","source":"spec"},{"id":"d1386b85a6dc","level":"SHOULD","text":"If possible all the above listed attributes SHOULD be present in a `Mapping`.","section":"specification/profiles/mappings.md#attributes","sectionTitle":"Attributes","status":"Alpha","source":"spec"},{"id":"8cd37632d743","level":"RECOMMENDED","text":"To promote interoperability, it is RECOMMENDED for `process.executable.buildid.htlhash` to be present in every `Mapping`.","section":"specification/profiles/mappings.md#attributes","sectionTitle":"Attributes","status":"Alpha","source":"spec"},{"id":"83141f96794e","level":"MAY","text":"Span context references: Samples MAY include a `Link` (span ID and trace ID), enabling direct linking between a profile sample and the trace/span during which it was captured.","section":"specification/profiles/README.md#data-format","sectionTitle":"Data Format","status":"Alpha","source":"spec"},{"id":"b5bb4bd4de81","level":"MUST","text":"Correlation with other signals: Profiles MUST be linkable to logs, metrics and traces through shared resource context and, where applicable, direct trace/span references.","section":"specification/profiles/README.md#design-goals","sectionTitle":"Design goals","status":"Alpha","source":"spec"},{"id":"c5e4bd60b01a","level":"MUST","text":"The following configuration options MUST be available to configure the OTLP exporter.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"5a8e4f10b9cc","level":"MUST","text":"Each configuration option MUST be overridable by a signal specific option.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"360f7109ab51","level":"MUST","text":"The implementation MUST honor the following URL components:","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"e0e2a0644e43","level":"MAY","text":"The implementation MAY ignore all other URL components.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"c127ba93dbe5","level":"MUST","text":"When using `OTELEXPORTEROTLP_ENDPOINT`, exporters MUST construct per-signal URLs as described below.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"5795de6f8b0f","level":"SHOULD","text":"The option SHOULD accept any form allowed by the underlying gRPC client implementation.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"52079b296e9e","level":"MUST","text":"Additionally, the option MUST accept a URL with a scheme of either `http` or `https`.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"601c9769b9e4","level":"SHOULD","text":"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.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"a34decba329b","level":"MAY","text":"Implementations MAY choose to not implement the `insecure` option if it is not required or supported by the underlying gRPC client implementation.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"da201d2bf00e","level":"MUST","text":"Options MUST be one of: `grpc`, `http/protobuf`, `http/json`.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"e3ff909860b0","level":"SHOULD","text":"[1]: SDKs SHOULD default endpoint variables to use `http` scheme unless they have good reasons to choose `https` scheme for the default (e.g., for backward compatibility reasons in a stable SDK release).","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"b4d01fcbf5f6","level":"SHOULD","text":"However, if they are already implemented, they SHOULD continue to be supported as they were part of a stable release of the specification.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"e72c6fe1c704","level":"SHOULD","text":"[4]: The default protocol SHOULD be `http/protobuf`, unless there are strong reasons for SDKs to select `grpc` as the default.","section":"specification/protocol/exporter.md#configuration-options","sectionTitle":"Configuration Options","status":"Stable","source":"spec"},{"id":"d38aa873a19d","level":"MUST","text":"Based on the environment variables above, the OTLP/HTTP exporter MUST construct URLs for each signal as follow:","section":"specification/protocol/exporter.md#endpoint-urls-for-otlphttp","sectionTitle":"Endpoint URLs for OTLP/HTTP","status":"Stable","source":"spec"},{"id":"92f0e9009229","level":"MUST","text":"For the per-signal variables (`OTELEXPORTEROTLP<signal>ENDPOINT`), the URL MUST be used as-is without any modification.","section":"specification/protocol/exporter.md#endpoint-urls-for-otlphttp","sectionTitle":"Endpoint URLs for OTLP/HTTP","status":"Stable","source":"spec"},{"id":"e679a889d838","level":"MUST","text":"The only exception is that if an URL contains no path part, the root path `/` MUST be used (see Example 2).","section":"specification/protocol/exporter.md#endpoint-urls-for-otlphttp","sectionTitle":"Endpoint URLs for OTLP/HTTP","status":"Stable","source":"spec"},{"id":"568879f6e66f","level":"MUST NOT","text":"An SDK MUST NOT modify the URL in ways other than specified above.","section":"specification/protocol/exporter.md#endpoint-urls-for-otlphttp","sectionTitle":"Endpoint URLs for OTLP/HTTP","status":"Stable","source":"spec"},{"id":"d328707f953d","level":"MUST","text":"Transient errors MUST be handled with a retry strategy.","section":"specification/protocol/exporter.md#retry","sectionTitle":"Retry","status":"Stable","source":"spec"},{"id":"0c19c35f039e","level":"MUST","text":"This retry strategy MUST implement an exponential back-off with jitter to avoid overwhelming the destination until the network is restored or the destination has recovered.","section":"specification/protocol/exporter.md#retry","sectionTitle":"Retry","status":"Stable","source":"spec"},{"id":"81c18107c2d8","level":"MUST","text":"SDKs SHOULD support both `grpc` and `http/protobuf` transports and MUST support at least one of them.","section":"specification/protocol/exporter.md#specify-protocol","sectionTitle":"Specify Protocol","status":"Stable","source":"spec"},{"id":"9a44e070a1f0","level":"SHOULD","text":"If they support only one, it SHOULD be `http/protobuf`.","section":"specification/protocol/exporter.md#specify-protocol","sectionTitle":"Specify Protocol","status":"Stable","source":"spec"},{"id":"1b5bf1d33025","level":"MAY","text":"They also MAY support `http/json`.","section":"specification/protocol/exporter.md#specify-protocol","sectionTitle":"Specify Protocol","status":"Stable","source":"spec"},{"id":"fd6ed2549d12","level":"SHOULD","text":"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).","section":"specification/protocol/exporter.md#specify-protocol","sectionTitle":"Specify Protocol","status":"Stable","source":"spec"},{"id":"4c7934fd5e84","level":"MUST","text":"All attribute values MUST be considered strings.","section":"specification/protocol/exporter.md#specifying-headers-via-environment-variables","sectionTitle":"Specifying headers via environment variables","status":"Stable","source":"spec"},{"id":"77ac73d21439","level":"SHOULD","text":"OpenTelemetry protocol exporters SHOULD emit a User-Agent header to at a minimum identify the exporter, the language of its implementation, and the version of the exporter.","section":"specification/protocol/exporter.md#user-agent","sectionTitle":"User Agent","status":"Stable","source":"spec"},{"id":"e0ba10c70737","level":"SHOULD","text":"The format of the header SHOULD follow [RFC 7231][rfc-7231].","section":"specification/protocol/exporter.md#user-agent","sectionTitle":"User Agent","status":"Stable","source":"spec"},{"id":"6fdc0f239b2a","level":"MAY","text":"Exporters MAY expose a configuration option to add a product identifier to the User-Agent header.","section":"specification/protocol/exporter.md#user-agent","sectionTitle":"User Agent","status":"Stable","source":"spec"},{"id":"80fd454cfcee","level":"SHOULD","text":"The resulting User-Agent SHOULD include the exporter's default User-Agent string.","section":"specification/protocol/exporter.md#user-agent","sectionTitle":"User Agent","status":"Stable","source":"spec"},{"id":"117a250a6977","level":"MUST","text":"The metric exporter MUST support the environment variables defined in the OTLP Exporter specification.","section":"specification/protocol/file-exporter.md#exporter-configuration","sectionTitle":"Exporter configuration","status":"Development","source":"spec"},{"id":"c25a83691f0f","level":"SHOULD","text":"If a language provides a mechanism to automatically configure a span or logs processor to pair with the associated exporter (e.g., using the `OTELTRACESEXPORTER` environment variable), by default the OpenTelemetry Protocol File Exporter SHOULD be paired with a batching processor.","section":"specification/protocol/file-exporter.md#exporter-configuration","sectionTitle":"Exporter configuration","status":"Development","source":"spec"},{"id":"1bdc1bbc7c90","level":"MUST","text":"| Requirement | Name | Description | Default | |-------------|----------------------------|--------------------------------------------------------------------------------------------------------|---------| | MUST | output stream (or similar) | Configure output stream.","section":"specification/protocol/file-exporter.md#programmatic-configuration","sectionTitle":"Programmatic configuration","status":"Development","source":"spec"},{"id":"1cb0150ad07a","level":"SHOULD","text":"This SHOULD include the possibility to configure the output stream to a file. | stdout |","section":"specification/protocol/file-exporter.md#programmatic-configuration","sectionTitle":"Programmatic configuration","status":"Development","source":"spec"},{"id":"6a6700605bbe","level":"MUST NOT","text":"The keywords \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in the [specification][] are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.","section":"specification/README.md#notation-conventions-and-compliance","sectionTitle":"Notation Conventions and Compliance","status":"Unspecified","source":"spec"},{"id":"a73ef5c225bd","level":"MUST NOT","text":"An implementation of the [specification][] is not compliant if it fails to satisfy one or more of the \"MUST\", \"MUST NOT\", \"REQUIRED\", requirements defined in the [specification][].","section":"specification/README.md#notation-conventions-and-compliance","sectionTitle":"Notation Conventions and Compliance","status":"Unspecified","source":"spec"},{"id":"a3128f60df3c","level":"MUST NOT","text":"Conversely, an implementation of the [specification][] is compliant if it satisfies all the \"MUST\", \"MUST NOT\", \"REQUIRED\", requirements defined in the [specification][].","section":"specification/README.md#notation-conventions-and-compliance","sectionTitle":"Notation Conventions and Compliance","status":"Unspecified","source":"spec"},{"id":"5b452223b1d1","level":"MAY","text":"The official acronym used by the OpenTelemetry project is \"OTel\". \"OT\" MAY be used only as a part of a longer acronym, such as OTCA (OpenTelemetry Certified Associate).","section":"specification/README.md#project-naming","sectionTitle":"Project Naming","status":"Unspecified","source":"spec"},{"id":"f2e808b32c1b","level":"SHOULD NOT","text":"SDKs SHOULD NOT update their merge algorithm until full Entity SDK support is provided.","section":"specification/resource/data-model.md#merging-resources","sectionTitle":"Merging Resources","status":"Development","source":"spec"},{"id":"0653e7553138","level":"SHOULD","text":"As such, a merge SHOULD preserve any identity that already existed on a Resource while adding in new identifying information or descriptive attributes.","section":"specification/resource/data-model.md#merging-resources","sectionTitle":"Merging Resources","status":"Development","source":"spec"},{"id":"f6b024a2b90b","level":"MUST","text":"| Field | Type | Description | | ----- | ---- | ----------- | | Entities | set\\<Entity\\> | Defines the set of Entities associated with this resource.<p>Entity is defined here | | Attributes | map\\<string, attribute value\\> | Additional Attributes that identify the resource.<p>MUST not change during the lifetime of the resource.<p>Follows OpenTelemetry attribute definition. |","section":"specification/resource/data-model.md#resource-data-model","sectionTitle":"Resource Data Model","status":"Development","source":"spec"},{"id":"643dd261b8fe","level":"SHOULD","text":"> [!TIP] > Observability signals SHOULD be actionable.","section":"specification/resource/README.md#navigation","sectionTitle":"Navigation","status":"Unspecified","source":"spec"},{"id":"b541c7523a4b","level":"MUST","text":"It MUST identify the observed entity for which telemetry is being produced.","section":"specification/resource/README.md#overview","sectionTitle":"Overview","status":"Unspecified","source":"spec"},{"id":"0115daf40105","level":"SHOULD","text":"It SHOULD allow users to determine where that entity resides within their infrastructure.","section":"specification/resource/README.md#overview","sectionTitle":"Overview","status":"Unspecified","source":"spec"},{"id":"fdbfb186d5ff","level":"MUST","text":"The interface MUST provide a way to create a new resource.","section":"specification/resource/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"25535ed5d262","level":"MUST","text":"When both `Entities` and `Attributes` are provided in the create method, the system MUST behave as if a Resource is created with just `Attributes` and then merges with another Resource created with just `Entities`.","section":"specification/resource/sdk.md#create","sectionTitle":"Create","status":"Stable","source":"spec"},{"id":"1224188cfefa","level":"MUST","text":"Custom resource detectors related to generic platforms (e.g. Docker, Kubernetes) or vendor specific environments (e.g. EKS, AKS, GKE) MUST be implemented as packages separate from the SDK.","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"f91c958685ee","level":"MUST","text":"Resource detector packages MUST provide a method that returns a resource.","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"498e9f68c7db","level":"MAY","text":"Resource detector packages MAY detect resource information from multiple possible sources and merge the result using the `Merge` operation described above.","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"79c7694e2080","level":"MUST NOT","text":"Note the failure to detect any resource information MUST NOT be considered an error, whereas an error that occurs during an attempt to detect resource information SHOULD be considered an error.","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"af0d5c8aa707","level":"MUST","text":"Resource detectors that populate resource attributes according to OpenTelemetry semantic conventions MUST ensure that the resource has a Schema URL set to a value that matches the semantic conventions.","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"f85cf65deed6","level":"SHOULD","text":"Empty Schema URL SHOULD be used if the detector does not populate the resource with any known attributes that have a semantic convention or if the detector does not know what attributes it will populate (e.g. the detector that reads the attributes from environment values will not know what Schema URL to use).","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"df47d49cc4f5","level":"MUST","text":"If multiple detectors are combined and the detectors use different non-empty Schema URL it MUST be an error since it is impossible to merge such resources.","section":"specification/resource/sdk.md#detecting-resource-information-from-the-environment","sectionTitle":"Detecting resource information from the environment","status":"Stable","source":"spec"},{"id":"2d9257aa8e6a","level":"MUST","text":"The interface MUST provide a way for an old resource and an updating resource to be merged into a new resource.","section":"specification/resource/sdk.md#merge","sectionTitle":"Merge","status":"Stable","source":"spec"},{"id":"e52d059910b9","level":"MUST","text":"If either resource contains `Entities` then merge behavior with Entities MUST be used, otherwise merge behavior without Entities MUST be used.","section":"specification/resource/sdk.md#merge","sectionTitle":"Merge","status":"Stable","source":"spec"},{"id":"d2218bf548af","level":"MUST","text":"When either Resource contains entities, the merge operation MUST follow the resource data model's merge algorithm.","section":"specification/resource/sdk.md#merge-behavior-with-entities","sectionTitle":"Merge behavior with entities","status":"Stable","source":"spec"},{"id":"7a735129e1be","level":"MUST","text":"The resulting `SchemaURL` MUST match the behavior defined in the merge algorithm.","section":"specification/resource/sdk.md#merge-behavior-with-entities","sectionTitle":"Merge behavior with entities","status":"Stable","source":"spec"},{"id":"a23733abae34","level":"MUST","text":"The resulting resource MUST have all attributes that are on any of the two input resources.","section":"specification/resource/sdk.md#merge-behavior-without-entities","sectionTitle":"Merge behavior without Entities","status":"Stable","source":"spec"},{"id":"8ceaea51f881","level":"MUST","text":"If a key exists on both the old and updating resource, the value of the updating resource MUST be picked (even if the updated value is empty).","section":"specification/resource/sdk.md#merge-behavior-without-entities","sectionTitle":"Merge behavior without Entities","status":"Stable","source":"spec"},{"id":"5d0f55e9affd","level":"SHOULD","text":"Resource detectors SHOULD have a unique name for reference in configuration.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"3b234a5e706a","level":"SHOULD","text":"Names SHOULD be snake case and consist of lowercase alphanumeric and `_` characters, which ensures they conform to declarative configuration property name requirements.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"6eb7d615cac1","level":"SHOULD","text":"Resource detector names SHOULD reflect the root namespace of attributes they populate.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"85425eeac8ad","level":"SHOULD","text":"Resource detectors which populate attributes from multiple root namespaces SHOULD choose a name which appropriately conveys their purpose.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"1011a8f4e516","level":"SHOULD","text":"An SDK which identifies multiple resource detectors with the same name SHOULD report an error.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"98145773b24a","level":"SHOULD","text":"In order to limit collisions, resource detectors SHOULD document their name in a manner which is easily discoverable.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"41ce38710f16","level":"SHOULD","text":"`service`: Populates `service.name` from the OTELSERVICENAME environment variable and SHOULD fall back to language- or platform-specific sources (for example `spring.application.name`, a JAR manifest, or a Composer/package manifest, at the discretion of the specific SDK); populates `service.instance.id` as defined here.","section":"specification/resource/sdk.md#resource-detector-name","sectionTitle":"Resource detector name","status":"Stable","source":"spec"},{"id":"5bcae0f8ef41","level":"MUST","text":"The SDK MUST allow for creation of `Resources` and for associating them with telemetry.","section":"specification/resource/sdk.md#resource-sdk","sectionTitle":"Resource SDK","status":"Stable","source":"spec"},{"id":"ab930e031f33","level":"MUST","text":"When associated with a `TracerProvider`, all `Span`s produced by any `Tracer` from the provider MUST be associated with this `Resource`.","section":"specification/resource/sdk.md#resource-sdk","sectionTitle":"Resource SDK","status":"Stable","source":"spec"},{"id":"a7f4df21220f","level":"MUST","text":"When entities are enabled and present for the Resource, this list MUST include all attributes, including those associated with entities.","section":"specification/resource/sdk.md#retrieve-attributes","sectionTitle":"Retrieve attributes","status":"Stable","source":"spec"},{"id":"dc03c428e636","level":"SHOULD","text":"The SDK SHOULD provide a way to retrieve the entities associated with a resource.","section":"specification/resource/sdk.md#retrieve-entities","sectionTitle":"Retrieve entities","status":"Stable","source":"spec"},{"id":"5c4352ac0376","level":"SHOULD","text":"The SDK SHOULD provide a way to retrieve attributes which are NOT associated with an entity in the resource.","section":"specification/resource/sdk.md#retrieve-unassociated-attributes","sectionTitle":"Retrieve unassociated attributes","status":"Stable","source":"spec"},{"id":"bcda2dd4ded3","level":"MUST","text":"The SDK MUST provide access to a Resource with at least the attributes listed at Semantic Attributes with SDK-provided Default Value.","section":"specification/resource/sdk.md#sdk-provided-resource-attributes","sectionTitle":"SDK-provided resource attributes","status":"Stable","source":"spec"},{"id":"a7ea23872216","level":"MUST","text":"This resource MUST be associated with a `TracerProvider`, `MeterProvider`, or `LoggerProvider` if another resource was not explicitly specified.","section":"specification/resource/sdk.md#sdk-provided-resource-attributes","sectionTitle":"SDK-provided resource attributes","status":"Stable","source":"spec"},{"id":"6d02b6fa5092","level":"MUST","text":"The SDK MUST extract information from the `OTELRESOURCEATTRIBUTES` environment variable and merge this, as the secondary resource, with any resource information provided by the user, i.e. the user provided resource information has higher priority.","section":"specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable","sectionTitle":"Specifying resource information via an environment variable","status":"Stable","source":"spec"},{"id":"a64d4c606a81","level":"MUST","text":"All attribute values MUST be considered strings.","section":"specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable","sectionTitle":"Specifying resource information via an environment variable","status":"Stable","source":"spec"},{"id":"9245ae72cca3","level":"MUST","text":"The `,` and `=` characters in keys and values MUST be percent encoded.","section":"specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable","sectionTitle":"Specifying resource information via an environment variable","status":"Stable","source":"spec"},{"id":"4def772f464b","level":"MAY","text":"Other characters MAY be percent-encoded, e.g. values outside the ANSI characters set.","section":"specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable","sectionTitle":"Specifying resource information via an environment variable","status":"Stable","source":"spec"},{"id":"1b9c219bcbc3","level":"SHOULD","text":"In case of any error, e.g. failure during the decoding process, the entire environment variable value SHOULD be discarded and an error SHOULD be reported following the Error Handling principles.","section":"specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable","sectionTitle":"Specifying resource information via an environment variable","status":"Stable","source":"spec"},{"id":"f0f51d033bd6","level":"SHOULD","text":"In this case the MAJOR version number of the schema SHOULD be increased in the new version.","section":"specification/schemas/file_format_v1.0.0.md#all-section","sectionTitle":"all Section","status":"Development","source":"spec"},{"id":"863b6614c1c9","level":"MUST","text":"Any change to this number MUST follow the OTEP process and be published in the specification.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"f33058ce94f7","level":"SHOULD","text":"As the schema file format evolves over time the format version number SHOULD change according to the following rules:","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"b1451e2ff576","level":"SHOULD","text":"PATCH number SHOULD be increased when the file format changes in a way that does not affect the existing consumers of the file.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"d909bcffd9f6","level":"SHOULD","text":"MINOR number SHOULD be increased if a new setting is added to the file format in a backward compatible manner. \"Backward compatible\" in this context means that consumers that are aware of the new MINOR number can consume the file of a particular MINOR version number or of any MINOR version number lower than that, provided that MAJOR version numbers are the same.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"eec61b69b548","level":"SHOULD NOT","text":"Consumers which support reading up to a particular MINOR version number SHOULD NOT attempt to consume files with higher MINOR version numbers.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"e25855638c7c","level":"SHOULD","text":"MAJOR number SHOULD be increased if the file format is changed in an incompatible way.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"d1530990b1cd","level":"SHOULD NOT","text":"Consumers of the schema file SHOULD NOT attempt to interpret the schema file if the MAJOR version number is different (higher or lower) than what the consumer supports.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"46f73a2e6c49","level":"SHOULD NOT","text":"Consumers of the schema file SHOULD NOT attempt to interpret the schema file if the MINOR version number is higher than what the consumer supports.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"32873dc67967","level":"MAY","text":"Consumers MAY ignore the PATCH number.","section":"specification/schemas/file_format_v1.0.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"ab4d2abd8a53","level":"SHOULD","text":"In this case the MAJOR version number of the schema SHOULD be increased in the new version.","section":"specification/schemas/file_format_v1.1.0.md#all-section","sectionTitle":"all Section","status":"Development","source":"spec"},{"id":"8bb4e5160db6","level":"MUST","text":"Any change to this number MUST be published in the specification.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"25847add9329","level":"SHOULD","text":"As the schema file format evolves over time the format version number SHOULD change according to the following rules:","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"ce1c8ef460a9","level":"SHOULD","text":"PATCH number SHOULD be increased when the file format changes in a way that does not affect the existing consumers of the file.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"8ea9e565b0f0","level":"SHOULD","text":"MINOR number SHOULD be increased if a new setting is added to the file format in a backward compatible manner. \"Backward compatible\" in this context means that consumers that are aware of the new MINOR number can consume the file of a particular MINOR version number or of any MINOR version number lower than that, provided that MAJOR version numbers are the same.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"f729cdea2c0b","level":"SHOULD NOT","text":"Consumers which support reading up to a particular MINOR version number SHOULD NOT attempt to consume files with higher MINOR version numbers.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"b1aeee27323c","level":"SHOULD","text":"MAJOR number SHOULD be increased if the file format is changed in an incompatible way.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"88e275b40359","level":"SHOULD NOT","text":"Consumers of the schema file SHOULD NOT attempt to interpret the schema file if the MAJOR version number is different (higher or lower) than what the consumer supports.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"84789e2ba9c9","level":"SHOULD NOT","text":"Consumers of the schema file SHOULD NOT attempt to interpret the schema file if the MINOR version number is higher than what the consumer supports.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"25948cf81451","level":"MAY","text":"Consumers MAY ignore the PATCH number.","section":"specification/schemas/file_format_v1.1.0.md#schema-file-format-number","sectionTitle":"Schema File Format Number","status":"Development","source":"spec"},{"id":"66a2556800cb","level":"MUST","text":"Every time a new semantic-conventions version is released a corresponding new schema MUST be released simultaneously.","section":"specification/schemas/README.md#opentelemetry-schema","sectionTitle":"OpenTelemetry Schema","status":"Stable","source":"spec"},{"id":"b1ed9a0c830a","level":"MUST","text":"The fetcher MUST follow the HTTP standard and honour the redirect response and fetch the file from the redirected URL.","section":"specification/schemas/README.md#schema-url","sectionTitle":"Schema URL","status":"Stable","source":"spec"},{"id":"2cdf82fe24d0","level":"MUST","text":"The schema file that corresponds to the new version MUST be retrievable at a new URL.","section":"specification/schemas/README.md#schema-url","sectionTitle":"Schema URL","status":"Stable","source":"spec"},{"id":"881c599e7b72","level":"MUST","text":"Any new transformation types MUST be proposed and added in the future to the schema file format when there is an evidence that they are necessary for the evolution of OpenTelemetry.","section":"specification/schemas/README.md#what-is-out-of-scope","sectionTitle":"What is Out of Scope","status":"Stable","source":"spec"},{"id":"a548bbfd3835","level":"SHOULD","text":"SDKs that implement self-observability metrics SHOULD follow these conventions.","section":"specification/self-observability.md#sdk-self-observability-metrics","sectionTitle":"SDK Self-Observability Metrics","status":"Development","source":"spec"},{"id":"b732a440eb52","level":"SHOULD","text":"OpenTelemetry SDKs SHOULD emit self-observability (\"internal\") telemetry about their own behavior (for example, metrics, logs, and other signals describing the state of processors, exporters, and metric readers) to help operators monitor the health of the OpenTelemetry pipeline itself.","section":"specification/self-observability.md#self-observability","sectionTitle":"Self-Observability","status":"Development","source":"spec"},{"id":"5f7b90996133","level":"MUST","text":"Semantic conventions MUST provide the following attributes:","section":"specification/semantic-conventions.md#in-development-reserved-attributes","sectionTitle":"In-development Reserved Attributes","status":"Development","source":"spec"},{"id":"34f11d666a6d","level":"MUST","text":"Semantic conventions MUST provide the following attributes:","section":"specification/semantic-conventions.md#reserved-attributes","sectionTitle":"Reserved Attributes","status":"Development","source":"spec"},{"id":"feb2d8efb3b3","level":"MUST","text":"Semantic conventions MUST provide the following events:","section":"specification/semantic-conventions.md#reserved-attributes","sectionTitle":"Reserved Attributes","status":"Development","source":"spec"},{"id":"da793315de82","level":"SHOULD","text":"Stable telemetry-producing instrumentations (stable instrumentations for short) SHOULD be clearly labeled so by any means the instrumentations authors consider idiomatic for their language, e.g. via version numbers, artifact names, documentation, etc.","section":"specification/telemetry-stability.md#stable-instrumentations","sectionTitle":"Stable Instrumentations","status":"Development","source":"spec"},{"id":"ab2a55418c2b","level":"SHOULD NOT","text":"Stable instrumentations authored by OpenTelemetry SHOULD NOT produce telemetry that is not described by OpenTelemetry semantic conventions.","section":"specification/telemetry-stability.md#stable-instrumentations","sectionTitle":"Stable Instrumentations","status":"Development","source":"spec"},{"id":"23db11f9f1d5","level":"MUST NOT","text":"If, however, this rule is broken the instrumentations MUST NOT change such telemetry, regardless of whether they are fixed-schema producers or schema-file driven producers.","section":"specification/telemetry-stability.md#stable-instrumentations","sectionTitle":"Stable Instrumentations","status":"Development","source":"spec"},{"id":"47bd9a9bc7ef","level":"SHOULD","text":"Unstable telemetry-producing instrumentations (unstable instrumentations for short) SHOULD be clearly labeled so by any means the instrumentations authors consider idiomatic for their language, e.g. via version numbers, artifact names, documentation, etc.","section":"specification/telemetry-stability.md#unstable-instrumentations","sectionTitle":"Unstable Instrumentations","status":"Development","source":"spec"},{"id":"dbc4b859615b","level":"MAY","text":"The produced telemetry MAY specify a Schema URL if the telemetry data conforms to a particular Schema.","section":"specification/telemetry-stability.md#unstable-instrumentations","sectionTitle":"Unstable Instrumentations","status":"Development","source":"spec"},{"id":"482e0ef62246","level":"MAY","text":"Unstable instrumentations authored by OpenTelemetry MAY produce additional telemetry that is not described by OpenTelemetry semantic conventions.","section":"specification/telemetry-stability.md#unstable-instrumentations","sectionTitle":"Unstable Instrumentations","status":"Development","source":"spec"},{"id":"3dabfe9f2ae2","level":"MUST","text":"A `Span` MUST have the ability to add events.","section":"specification/trace/api.md#add-events","sectionTitle":"Add Events","status":"Stable","source":"spec"},{"id":"18abcce80928","level":"MUST","text":"The Span interface MUST provide:","section":"specification/trace/api.md#add-events","sectionTitle":"Add Events","status":"Stable","source":"spec"},{"id":"c802dda88f55","level":"MAY","text":"This MAY be called `AddEvent`.","section":"specification/trace/api.md#add-events","sectionTitle":"Add Events","status":"Stable","source":"spec"},{"id":"0d744b258758","level":"SHOULD","text":"Events SHOULD preserve the order in which they are recorded.","section":"specification/trace/api.md#add-events","sectionTitle":"Add Events","status":"Stable","source":"spec"},{"id":"d4b0933af5e7","level":"MUST","text":"A `Span` MUST have the ability to add `Link`s associated with it after its creation - see Links.","section":"specification/trace/api.md#add-link","sectionTitle":"Add Link","status":"Stable","source":"spec"},{"id":"2643160e3911","level":"MUST","text":"However, there is one important exception to this general rule, and that is related to propagation of a `SpanContext`: The API MUST return a non-recording `Span` with the `SpanContext` in the parent `Context` (whether explicitly given or implicit current).","section":"specification/trace/api.md#behavior-of-the-api-in-the-absence-of-an-installed-sdk","sectionTitle":"Behavior of the API in the absence of an installed SDK","status":"Stable","source":"spec"},{"id":"fa670c3b3b28","level":"SHOULD","text":"If the `Span` in the parent `Context` is already non-recording, it SHOULD be returned directly without instantiating a new `Span`.","section":"specification/trace/api.md#behavior-of-the-api-in-the-absence-of-an-installed-sdk","sectionTitle":"Behavior of the API in the absence of an installed SDK","status":"Stable","source":"spec"},{"id":"6ede538a012b","level":"MUST","text":"If the parent `Context` contains no `Span`, an empty non-recording Span MUST be returned instead (i.e., having a `SpanContext` with all-zero Span and Trace IDs, empty Tracestate, and unsampled TraceFlags).","section":"specification/trace/api.md#behavior-of-the-api-in-the-absence-of-an-installed-sdk","sectionTitle":"Behavior of the API in the absence of an installed SDK","status":"Stable","source":"spec"},{"id":"d5fe45b7ae30","level":"MUST","text":"TracerProvider - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/trace/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"15c11134ea3e","level":"MUST","text":"Tracer - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/trace/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"0bfcc2bfdda0","level":"MUST","text":"Span - all methods MUST be documented that implementations need to be safe for concurrent use by default.","section":"specification/trace/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"9bd911385674","level":"MUST","text":"Event - Events are immutable and MUST be safe for concurrent use by default.","section":"specification/trace/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"4975c1652623","level":"SHOULD","text":"Link - Links are immutable and SHOULD be safe for concurrent use by default.","section":"specification/trace/api.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"b81e59131085","level":"MUST","text":"The API MUST provide the following functionality to interact with a `Context` instance:","section":"specification/trace/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"3e5838cdedb6","level":"SHOULD NOT","text":"The functionality listed above is necessary because API users SHOULD NOT have access to the Context Key used by the Tracing API implementation.","section":"specification/trace/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"fe0fca19d573","level":"SHOULD","text":"If the language has support for implicitly propagated `Context` (see here), the API SHOULD also provide the following functionality:","section":"specification/trace/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"a0f7d5c60f5e","level":"MAY","text":"All the above functionalities operate solely on the context API, and they MAY be exposed as either static methods on the trace module, or as static methods on a class inside the trace module.","section":"specification/trace/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"dc0b1801ea46","level":"SHOULD","text":"This functionality SHOULD be fully implemented in the API when possible.","section":"specification/trace/api.md#context-interaction","sectionTitle":"Context Interaction","status":"Stable","source":"spec"},{"id":"553d50b02c7b","level":"SHOULD","text":"To help users avoid performing computationally expensive operations when creating `Span`s, a `Tracer` SHOULD provide this `Enabled` API.","section":"specification/trace/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"19ff3898b87d","level":"MUST","text":"Parameters can be added in the future, therefore, the API MUST be structured in a way for parameters to be added.","section":"specification/trace/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"0d61eb1d857b","level":"MUST","text":"This API MUST return a language idiomatic boolean type.","section":"specification/trace/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"33670245342a","level":"SHOULD","text":"The API SHOULD be documented that instrumentation authors needs to call this API each time they create a new `Span` to ensure they have the most up-to-date response.","section":"specification/trace/api.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"79eb9a7aed6a","level":"SHOULD","text":"Implementations SHOULD ignore all subsequent calls to `End` and any other Span methods, i.e. the Span becomes non-recording by being ended (there might be exceptions when Tracer is streaming events and has no mutable state associated with the `Span`).","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"c5cf2281498c","level":"MAY","text":"Language SIGs MAY provide methods other than `End` in the API that also end the span to support language-specific features like `with` statements in Python.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"0c5d298595a9","level":"MUST","text":"However, all API implementations of such methods MUST internally call the `End` method and be documented to do so.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"c24f7a77bd35","level":"MUST NOT","text":"`End` MUST NOT have any effects on child spans.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"bacb7f120969","level":"MUST NOT","text":"`End` MUST NOT inactivate the `Span` in any `Context` it is active in.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"460deedd38a0","level":"MUST","text":"It MUST still be possible to use an ended span as parent via a Context it is contained in.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"d8b3a2c7cd00","level":"MUST","text":"Also, any mechanisms for putting the Span into a Context MUST still work after the Span was ended.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"856733940585","level":"MUST","text":"If omitted, this MUST be treated equivalent to passing the current time.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"68273a325b59","level":"MUST NOT","text":"This operation itself MUST NOT perform blocking I/O on the calling thread.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"14c8141cce0c","level":"SHOULD","text":"Any locking used needs be minimized and SHOULD be removed entirely if possible.","section":"specification/trace/api.md#end","sectionTitle":"End","status":"Stable","source":"spec"},{"id":"53e69e2182d5","level":"MUST","text":"This API MUST accept the following parameters:","section":"specification/trace/api.md#get-a-tracer","sectionTitle":"Get a Tracer","status":"Stable","source":"spec"},{"id":"1809a0ea5b64","level":"SHOULD","text":"`name` (required): This name SHOULD uniquely identify the instrumentation scope, such as the instrumentation library (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name.","section":"specification/trace/api.md#get-a-tracer","sectionTitle":"Get a Tracer","status":"Stable","source":"spec"},{"id":"6b54576f372a","level":"MUST","text":"In case an invalid name (null or empty string) is specified, a working Tracer implementation MUST be returned as a fallback rather than returning null or throwing an exception, its `name` property SHOULD be set to an empty string, and a message reporting that the specified value is invalid SHOULD be logged.","section":"specification/trace/api.md#get-a-tracer","sectionTitle":"Get a Tracer","status":"Stable","source":"spec"},{"id":"5fd92ee202b2","level":"MUST NOT","text":"Implementations MUST NOT require users to repeatedly obtain a `Tracer` again with the same identity to pick up configuration changes.","section":"specification/trace/api.md#get-a-tracer","sectionTitle":"Get a Tracer","status":"Stable","source":"spec"},{"id":"eb3d9a956908","level":"MUST","text":"The Span interface MUST provide:","section":"specification/trace/api.md#get-context","sectionTitle":"Get Context","status":"Stable","source":"spec"},{"id":"a7268d2ad699","level":"MUST","text":"The returned value MUST be the same for the entire Span lifetime.","section":"specification/trace/api.md#get-context","sectionTitle":"Get Context","status":"Stable","source":"spec"},{"id":"c2b7d3df29e8","level":"MAY","text":"This MAY be called `GetContext`.","section":"specification/trace/api.md#get-context","sectionTitle":"Get Context","status":"Stable","source":"spec"},{"id":"b99d83e7b010","level":"SHOULD","text":"After a `Span` is ended, it SHOULD become non-recording and `IsRecording` SHOULD always return `false`.","section":"specification/trace/api.md#isrecording","sectionTitle":"IsRecording","status":"Stable","source":"spec"},{"id":"ac3ccefabeb6","level":"SHOULD NOT","text":"`IsRecording` SHOULD NOT take any parameters.","section":"specification/trace/api.md#isrecording","sectionTitle":"IsRecording","status":"Stable","source":"spec"},{"id":"db54eb8a92d8","level":"SHOULD","text":"This flag SHOULD be used to avoid expensive computations of a Span attributes or events in case when a Span is definitely not recorded.","section":"specification/trace/api.md#isrecording","sectionTitle":"IsRecording","status":"Stable","source":"spec"},{"id":"bed49e0c5f97","level":"MUST","text":"An API called `IsRemote`, that returns a boolean value, which is `true` if the SpanContext was propagated from a remote parent, MUST be provided.","section":"specification/trace/api.md#isremote","sectionTitle":"IsRemote","status":"Stable","source":"spec"},{"id":"d49e6ca908cb","level":"MUST","text":"When extracting a `SpanContext` through the Propagators API, `IsRemote` MUST return true, whereas for the SpanContext of any child spans it MUST return false.","section":"specification/trace/api.md#isremote","sectionTitle":"IsRemote","status":"Stable","source":"spec"},{"id":"3965d3932411","level":"MUST","text":"An API called `IsValid`, that returns a boolean value, which is `true` if the SpanContext has a non-zero TraceID and a non-zero SpanID, MUST be provided.","section":"specification/trace/api.md#isvalid","sectionTitle":"IsValid","status":"Stable","source":"spec"},{"id":"bfbee075d475","level":"MUST","text":"A user MUST have the ability to record links to other `SpanContext`s.","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"6e8ede4aa1df","level":"MUST","text":"The API MUST provide:","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"f5f28a9eddb4","level":"MAY","text":"This MAY be called `AddLink`.","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"92b88bbb2c06","level":"SHOULD","text":"Implementations SHOULD record links containing `SpanContext` with empty `TraceId` or `SpanId` (all zeros) as long as either the attribute set or `TraceState` is non-empty.","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"262287880b41","level":"MAY","text":"The Span interface MAY provide:","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"394e6cbeeeb2","level":"SHOULD","text":"Span SHOULD preserve the order in which `Link`s are set.","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"ee57854a0509","level":"MUST","text":"The API documentation MUST state that adding links at span creation is preferred to calling `AddLink` later, for contexts that are available during span creation, because head sampling decisions can only consider information present during span creation.","section":"specification/trace/api.md#link","sectionTitle":"Link","status":"Stable","source":"spec"},{"id":"eaced28f15cf","level":"SHOULD","text":"To facilitate recording an exception languages SHOULD provide a `RecordException` method if the language uses exceptions.","section":"specification/trace/api.md#record-exception","sectionTitle":"Record Exception","status":"Stable","source":"spec"},{"id":"61dd8fa2ecf0","level":"MUST","text":"The method MUST record an exception as an `Event` with the conventions outlined in the exceptions document.","section":"specification/trace/api.md#record-exception","sectionTitle":"Record Exception","status":"Stable","source":"spec"},{"id":"153da8d5e249","level":"SHOULD","text":"The minimum required argument SHOULD be no more than only an exception object.","section":"specification/trace/api.md#record-exception","sectionTitle":"Record Exception","status":"Stable","source":"spec"},{"id":"61f43b45a9ff","level":"MUST","text":"If `RecordException` is provided, the method MUST accept an optional parameter to provide any additional event attributes (this SHOULD be done in the same way as for the `AddEvent` method).","section":"specification/trace/api.md#record-exception","sectionTitle":"Record Exception","status":"Stable","source":"spec"},{"id":"d9ae29993f0d","level":"MUST","text":"The API MUST allow retrieving the `TraceId` and `SpanId` in the following forms:","section":"specification/trace/api.md#retrieving-the-traceid-and-spanid","sectionTitle":"Retrieving the TraceId and SpanId","status":"Stable","source":"spec"},{"id":"3da83dcee2cb","level":"MUST","text":"Hex - returns the lowercase hex encoded `TraceId` (result MUST be a 32-hex-character lowercase string) or `SpanId` (result MUST be a 16-hex-character lowercase string).","section":"specification/trace/api.md#retrieving-the-traceid-and-spanid","sectionTitle":"Retrieving the TraceId and SpanId","status":"Stable","source":"spec"},{"id":"72c2864c972c","level":"MUST","text":"Binary - returns the binary representation of the `TraceId` (result MUST be a 16-byte array) or `SpanId` (result MUST be an 8-byte array).","section":"specification/trace/api.md#retrieving-the-traceid-and-spanid","sectionTitle":"Retrieving the TraceId and SpanId","status":"Stable","source":"spec"},{"id":"887abed4a408","level":"SHOULD NOT","text":"The API SHOULD NOT expose details about how they are internally stored.","section":"specification/trace/api.md#retrieving-the-traceid-and-spanid","sectionTitle":"Retrieving the TraceId and SpanId","status":"Stable","source":"spec"},{"id":"4a49e2b716b0","level":"MUST","text":"A `Span` MUST have the ability to set `Attributes` associated with it.","section":"specification/trace/api.md#set-attributes","sectionTitle":"Set Attributes","status":"Stable","source":"spec"},{"id":"241f9ec60e82","level":"MUST","text":"The Span interface MUST provide:","section":"specification/trace/api.md#set-attributes","sectionTitle":"Set Attributes","status":"Stable","source":"spec"},{"id":"26887d7a7d78","level":"MAY","text":"This MAY be called `SetAttribute`.","section":"specification/trace/api.md#set-attributes","sectionTitle":"Set Attributes","status":"Stable","source":"spec"},{"id":"c408f92a8fe4","level":"MAY","text":"The Span interface MAY provide:","section":"specification/trace/api.md#set-attributes","sectionTitle":"Set Attributes","status":"Stable","source":"spec"},{"id":"aa4f3e5a0416","level":"SHOULD","text":"Setting an attribute with the same key as an existing attribute SHOULD overwrite the existing attribute's value.","section":"specification/trace/api.md#set-attributes","sectionTitle":"Set Attributes","status":"Stable","source":"spec"},{"id":"b92d71372020","level":"MUST","text":"`Description` MUST only be used with the `Error` `StatusCode` value.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"693b4cae31a2","level":"MUST","text":"The Span interface MUST provide:","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"7a4905cb7b93","level":"SHOULD","text":"This SHOULD be called `SetStatus`.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"ebf8d26516cb","level":"MUST","text":"`Description` MUST be IGNORED for `StatusCode` `Ok` & `Unset` values.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"2566261747c6","level":"SHOULD","text":"The status code SHOULD remain unset, except for the following circumstances:","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"3ef50139d00b","level":"SHOULD","text":"An attempt to set value `Unset` SHOULD be ignored.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"6c252661e74c","level":"SHOULD","text":"When the status is set to `Error` by Instrumentation Libraries, the `Description` SHOULD be documented and predictable.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"a26fecfd2610","level":"SHOULD","text":"For operations not covered by the semantic conventions, Instrumentation Libraries SHOULD publish their own conventions, including possible values of `Description` and what they mean.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"571fc394ed62","level":"SHOULD NOT","text":"Generally, Instrumentation Libraries SHOULD NOT set the status code to `Ok`, unless explicitly configured to do so.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"e13db4206006","level":"SHOULD","text":"Instrumentation Libraries SHOULD leave the status code as `Unset` unless there is an error, as described above.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"72b946e53729","level":"SHOULD","text":"When span status is set to `Ok` it SHOULD be considered final and any further attempts to change it SHOULD be ignored.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"874c0634a41c","level":"SHOULD","text":"Analysis tools SHOULD respond to an `Ok` status by suppressing any errors they would otherwise generate.","section":"specification/trace/api.md#set-status","sectionTitle":"Set Status","status":"Stable","source":"spec"},{"id":"c52fa31fe5da","level":"SHOULD","text":"The span name SHOULD be the most general string that identifies a (statistically) interesting class of Spans, rather than individual Span instances while still being human-readable.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"82204fea1dee","level":"SHOULD","text":"Generality SHOULD be prioritized over human-readability.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"6c49f04e317e","level":"SHOULD","text":"A `Span`'s start time SHOULD be set to the current time on span creation.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"21c167fdfb39","level":"SHOULD","text":"After the `Span` is created, it SHOULD be possible to change its name, set its `Attribute`s, add `Event`s, and set the `Status`.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"517166bba183","level":"MUST NOT","text":"These MUST NOT be changed after the `Span`'s end time has been set.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"3e785cb590b2","level":"SHOULD NOT","text":"To prevent misuse, implementations SHOULD NOT provide access to a `Span`'s attributes besides its `SpanContext`.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"14b6d6d52269","level":"MUST NOT","text":"However, alternative implementations MUST NOT allow callers to create `Span`s directly.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"515783071a8a","level":"MUST","text":"All `Span`s MUST be created via a `Tracer`.","section":"specification/trace/api.md#span","sectionTitle":"Span","status":"Stable","source":"spec"},{"id":"9c0991926682","level":"MUST NOT","text":"There MUST NOT be any API for creating a `Span` other than with a `Tracer`.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"e8811fa2aa54","level":"MUST NOT","text":"In languages with implicit `Context` propagation, `Span` creation MUST NOT set the newly created `Span` as the active `Span` in the current `Context` by default, but this functionality MAY be offered additionally as a separate operation.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"ce5aa63980ad","level":"MUST","text":"The API MUST accept the following parameters:","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"f35a86fcecbf","level":"MAY","text":"The API MAY also have an option for implicitly using the current Context as parent as a default behavior.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"1018a44acee6","level":"MUST NOT","text":"This API MUST NOT accept a `Span` or `SpanContext` as parent, only a full `Context`.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"86813c3cc25a","level":"MUST","text":"The semantic parent of the Span MUST be determined according to the rules described in Determining the Parent Span from a Context.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"ffb63511f69d","level":"MUST","text":"The API documentation MUST state that adding attributes at span creation is preferred to calling `SetAttribute` later, as samplers can only consider information already present during span creation.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"ce2196565b6b","level":"SHOULD","text":"This argument SHOULD only be set when span creation time has already passed.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"502d3184d283","level":"MUST NOT","text":"If API is called at a moment of a Span logical start, API user MUST NOT explicitly set this argument.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"890d3d365833","level":"MUST","text":"Implementations MUST provide an option to create a `Span` as a root span, and MUST generate a new `TraceId` for each root span created.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"a284ddad9120","level":"MUST","text":"For a Span with a parent, the `TraceId` MUST be the same as the parent.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"8e3c9cd05ccc","level":"MUST","text":"Also, the child span MUST inherit all `TraceState` values of its parent by default.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"d1d7d86d7476","level":"MUST","text":"Any span that is created MUST also be ended.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"72e69768ccc7","level":"MAY","text":"API implementations MAY leak memory or other resources (including, for example, CPU time for periodic work that iterates all spans) if the user forgot to end the span.","section":"specification/trace/api.md#span-creation","sectionTitle":"Span Creation","status":"Stable","source":"spec"},{"id":"d3d14c75c16d","level":"MUST","text":"Start and end time as well as Event's timestamps MUST be recorded at a time of a calling of corresponding API.","section":"specification/trace/api.md#span-lifetime","sectionTitle":"Span lifetime","status":"Stable","source":"spec"},{"id":"c691b4e4d532","level":"MUST","text":"The API MUST implement methods to create a `SpanContext`.","section":"specification/trace/api.md#spancontext","sectionTitle":"SpanContext","status":"Stable","source":"spec"},{"id":"950e4ed8b794","level":"SHOULD","text":"These methods SHOULD be the only way to create a `SpanContext`.","section":"specification/trace/api.md#spancontext","sectionTitle":"SpanContext","status":"Stable","source":"spec"},{"id":"dc8ea31c89e2","level":"SHOULD NOT","text":"This functionality MUST be fully implemented in the API, and SHOULD NOT be overridable.","section":"specification/trace/api.md#spancontext","sectionTitle":"SpanContext","status":"Stable","source":"spec"},{"id":"f58c6da92e3a","level":"SHOULD","text":"In order for `SpanKind` to be meaningful, callers SHOULD arrange that a single Span does not serve more than one purpose.","section":"specification/trace/api.md#spankind","sectionTitle":"SpanKind","status":"Stable","source":"spec"},{"id":"59983c83983e","level":"SHOULD NOT","text":"For example, a server-side span SHOULD NOT be used to describe outgoing remote procedure call.","section":"specification/trace/api.md#spankind","sectionTitle":"SpanKind","status":"Stable","source":"spec"},{"id":"7ab368a3f770","level":"MUST","text":"During `Span` creation, a user MUST have the ability to record links to other `Span`s.","section":"specification/trace/api.md#specifying-links","sectionTitle":"Specifying links","status":"Stable","source":"spec"},{"id":"fec8869d4979","level":"MUST","text":"The `Tracer` MUST provide functions to:","section":"specification/trace/api.md#tracer-operations","sectionTitle":"Tracer operations","status":"Stable","source":"spec"},{"id":"03488ea1670f","level":"SHOULD","text":"The `Tracer` SHOULD provide functions to:","section":"specification/trace/api.md#tracer-operations","sectionTitle":"Tracer operations","status":"Stable","source":"spec"},{"id":"f0b0c6ac6a2b","level":"SHOULD","text":"Thus, the API SHOULD provide a way to set/register and access a global default `TracerProvider`.","section":"specification/trace/api.md#tracerprovider","sectionTitle":"TracerProvider","status":"Stable","source":"spec"},{"id":"29f702b18971","level":"SHOULD","text":"Thus, implementations of `TracerProvider` SHOULD allow creating an arbitrary number of `TracerProvider` instances.","section":"specification/trace/api.md#tracerprovider","sectionTitle":"TracerProvider","status":"Stable","source":"spec"},{"id":"858f782af5cc","level":"MUST","text":"The `TracerProvider` MUST provide the following functions:","section":"specification/trace/api.md#tracerprovider-operations","sectionTitle":"TracerProvider operations","status":"Stable","source":"spec"},{"id":"e21336b87bfb","level":"MUST","text":"Tracing API MUST provide at least the following operations on `TraceState`:","section":"specification/trace/api.md#tracestate","sectionTitle":"TraceState","status":"Stable","source":"spec"},{"id":"a4fc64fb6b4b","level":"MUST","text":"These operations MUST follow the rules described in the W3C Trace Context specification.","section":"specification/trace/api.md#tracestate","sectionTitle":"TraceState","status":"Stable","source":"spec"},{"id":"87f4aff768ce","level":"MUST","text":"All mutating operations MUST return a new `TraceState` with the modifications applied.","section":"specification/trace/api.md#tracestate","sectionTitle":"TraceState","status":"Stable","source":"spec"},{"id":"7c298175f06d","level":"MUST","text":"`TraceState` MUST at all times be valid according to rules specified in W3C Trace Context specification.","section":"specification/trace/api.md#tracestate","sectionTitle":"TraceState","status":"Stable","source":"spec"},{"id":"7033e9c6a321","level":"MUST","text":"Every mutating operations MUST validate input parameters.","section":"specification/trace/api.md#tracestate","sectionTitle":"TraceState","status":"Stable","source":"spec"},{"id":"49551e3c5bf5","level":"MUST NOT","text":"If invalid value is passed the operation MUST NOT return `TraceState` containing invalid data and MUST follow the general error handling guidelines.","section":"specification/trace/api.md#tracestate","sectionTitle":"TraceState","status":"Stable","source":"spec"},{"id":"17d87d75d08e","level":"MUST","text":"The API MUST provide an operation for wrapping a `SpanContext` with an object implementing the `Span` interface.","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"77ee2e7308f1","level":"SHOULD NOT","text":"If a new type is required for supporting this operation, it SHOULD NOT be exposed publicly if possible (e.g. by only exposing a function that returns something with the Span interface type).","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"a993235110f6","level":"SHOULD","text":"If a new type is required to be publicly exposed, it SHOULD be named `NonRecordingSpan`.","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"0ef2613a949e","level":"MUST","text":"`GetContext` MUST return the wrapped `SpanContext`.","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"be0f0e556647","level":"MUST","text":"`IsRecording` MUST return `false` to signal that events, attributes and other elements are not being recorded, i.e. they are being dropped.","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"6084dcc6dbd6","level":"MUST","text":"The remaining functionality of `Span` MUST be defined as no-op operations.","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"443eb97578a2","level":"SHOULD NOT","text":"This functionality MUST be fully implemented in the API, and SHOULD NOT be overridable.","section":"specification/trace/api.md#wrapping-a-spancontext-in-a-span","sectionTitle":"Wrapping a SpanContext in a Span","status":"Stable","source":"spec"},{"id":"2189a033c318","level":"MUST","text":"An event representing an exception MUST have an event name `exception`.","section":"specification/trace/exceptions.md#attributes","sectionTitle":"Attributes","status":"Stable","source":"spec"},{"id":"37bd6d638661","level":"SHOULD","text":"Additionally, the following attributes SHOULD be filled out:","section":"specification/trace/exceptions.md#attributes","sectionTitle":"Attributes","status":"Stable","source":"spec"},{"id":"5cf58d365f2d","level":"SHOULD","text":"An exception SHOULD be recorded as an `Event` on the span during which it occurred if and only if it remains unhandled when the span ends and causes the span status to be set to ERROR.","section":"specification/trace/exceptions.md#recording-an-exception","sectionTitle":"Recording an Exception","status":"Stable","source":"spec"},{"id":"46b02209e866","level":"MUST","text":"The name of the event MUST be `\"exception\"`.","section":"specification/trace/exceptions.md#recording-an-exception","sectionTitle":"Recording an Exception","status":"Stable","source":"spec"},{"id":"42f822d9c4bf","level":"SHOULD","text":"Documentation SHOULD warn users about this.","section":"specification/trace/sdk_exporters/stdout.md#span-exporter---standard-output","sectionTitle":"Span Exporter - Standard output","status":"Stable","source":"spec"},{"id":"87ced252720e","level":"MAY","text":"OpenTelemetry SDK authors MAY choose the best idiomatic name for their language.","section":"specification/trace/sdk_exporters/stdout.md#span-exporter---standard-output","sectionTitle":"Span Exporter - Standard output","status":"Stable","source":"spec"},{"id":"08a45dafa4e2","level":"SHOULD","text":"If a language provides a mechanism to automatically configure a Span processor to pair with the associated exporter (e.g., using the `OTELTRACESEXPORTER` environment variable), by default the standard output exporter SHOULD be paired with a simple processor.","section":"specification/trace/sdk_exporters/stdout.md#span-exporter---standard-output","sectionTitle":"Span Exporter - Standard output","status":"Stable","source":"spec"},{"id":"2f2fdab8d841","level":"MUST","text":"OpenTelemetry Span `Attribute`(s) MUST be reported as `tags` to Zipkin.","section":"specification/trace/sdk_exporters/zipkin.md#attribute","sectionTitle":"Attribute","status":"Deprecated","source":"spec"},{"id":"61c043e08bd8","level":"MUST","text":"Primitive types MUST be converted to string using en-US culture settings.","section":"specification/trace/sdk_exporters/zipkin.md#attribute","sectionTitle":"Attribute","status":"Deprecated","source":"spec"},{"id":"980e97cee4e7","level":"MUST","text":"Boolean values MUST use lower case strings `\"true\"` and `\"false\"`.","section":"specification/trace/sdk_exporters/zipkin.md#attribute","sectionTitle":"Attribute","status":"Deprecated","source":"spec"},{"id":"8476a38fcc4f","level":"MUST","text":"Array values MUST be serialized to string like a JSON list as mentioned in semantic conventions.","section":"specification/trace/sdk_exporters/zipkin.md#attribute","sectionTitle":"Attribute","status":"Deprecated","source":"spec"},{"id":"b94b6b3eb56f","level":"MUST","text":"Events MUST be converted to the Annotations with the names which will include attribute values like this:","section":"specification/trace/sdk_exporters/zipkin.md#events","sectionTitle":"Events","status":"Deprecated","source":"spec"},{"id":"98a64defdd0c","level":"MUST","text":"Existing stable Zipkin exporters MUST > continue to be supported for at least one year after the artifact is deprecated, > following the SDK stability guarantees. > Implementing a Zipkin exporter is not required for new SDKs. > > Users may use Zipkin exporter > collector component or zipkin-otel > Zipkin server module.","section":"specification/trace/sdk_exporters/zipkin.md#opentelemetry-to-zipkin-transformation","sectionTitle":"OpenTelemetry to Zipkin Transformation","status":"Deprecated","source":"spec"},{"id":"a06c3c71bc10","level":"MUST","text":"If a particular generic transformation rule and the rule in this document contradict then the rule in this document MUST be used.","section":"specification/trace/sdk_exporters/zipkin.md#opentelemetry-to-zipkin-transformation","sectionTitle":"OpenTelemetry to Zipkin Transformation","status":"Deprecated","source":"spec"},{"id":"090f472a5e79","level":"SHOULD","text":"If Zipkin `SpanKind` resolves to either `SpanKind.CLIENT` or `SpanKind.PRODUCER` then the service SHOULD specify remote endpoint otherwise Zipkin won't treat the Span as a dependency.","section":"specification/trace/sdk_exporters/zipkin.md#otlp---zipkin","sectionTitle":"OTLP -> Zipkin","status":"Deprecated","source":"spec"},{"id":"50ea17c590ab","level":"SHOULD","text":"For performance considerations, Zipkin fields that can be absent SHOULD be omitted from the payload when they are empty in the OpenTelemetry `Span`.","section":"specification/trace/sdk_exporters/zipkin.md#request-payload","sectionTitle":"Request Payload","status":"Deprecated","source":"spec"},{"id":"c22bbe5966f5","level":"MUST","text":"Zipkin service name MUST be set to the value of the resource attribute: `service.name`.","section":"specification/trace/sdk_exporters/zipkin.md#service-name","sectionTitle":"Service name","status":"Deprecated","source":"spec"},{"id":"62a160cf644b","level":"MUST","text":"If no `service.name` is contained in a Span's Resource, it MUST be populated from the default `Resource`.","section":"specification/trace/sdk_exporters/zipkin.md#service-name","sectionTitle":"Service name","status":"Deprecated","source":"spec"},{"id":"5db96a1167b2","level":"MUST NOT","text":"Note that the attribute `service.namespace` MUST NOT be used for the Zipkin service name and should be sent as a Zipkin tag.","section":"specification/trace/sdk_exporters/zipkin.md#service-name","sectionTitle":"Service name","status":"Deprecated","source":"spec"},{"id":"3e3541b5767b","level":"MUST","text":"Span `Status` MUST be reported as a key-value pair in `tags` to Zipkin, unless it is `UNSET`.","section":"specification/trace/sdk_exporters/zipkin.md#status","sectionTitle":"Status","status":"Deprecated","source":"spec"},{"id":"d2f97ef0e576","level":"MUST NOT","text":"In the latter case it MUST NOT be reported.","section":"specification/trace/sdk_exporters/zipkin.md#status","sectionTitle":"Status","status":"Deprecated","source":"spec"},{"id":"4cf3e2ade3c6","level":"MUST NOT","text":"MUST NOT be set if the code is `UNSET`. | | Description | `error` | Description of the `Status`.","section":"specification/trace/sdk_exporters/zipkin.md#status","sectionTitle":"Status","status":"Deprecated","source":"spec"},{"id":"916a72d6c690","level":"MUST","text":"MUST be set if the code is `ERROR`, use an empty string if Description has no value.","section":"specification/trace/sdk_exporters/zipkin.md#status","sectionTitle":"Status","status":"Deprecated","source":"spec"},{"id":"1d51021beab4","level":"MUST NOT","text":"MUST NOT be set for `OK` and `UNSET` codes. |","section":"specification/trace/sdk_exporters/zipkin.md#status","sectionTitle":"Status","status":"Deprecated","source":"spec"},{"id":"8bb39568cd69","level":"SHOULD","text":"If a boolean version (`{\"error\":false}` or `{\"error\":\"false\"}`) is present, it SHOULD be removed.","section":"specification/trace/sdk_exporters/zipkin.md#status","sectionTitle":"Status","status":"Deprecated","source":"spec"},{"id":"ccdef37d0300","level":"MUST","text":"Zipkin times like `timestamp`, `duration` and `annotation.timestamp` MUST be reported in microseconds as whole numbers.","section":"specification/trace/sdk_exporters/zipkin.md#unit-of-time","sectionTitle":"Unit of Time","status":"Deprecated","source":"spec"},{"id":"5a805d6898e8","level":"MUST","text":"Readable span: A function receiving this as argument MUST be able to access all information that was added to the span, as listed in the API spec for Span.","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"20377c9eed3b","level":"MUST","text":"A function receiving this as argument MUST be able to access the `InstrumentationScope` [since 1.10.0] and `Resource` information (implicitly) associated with the span.","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"69adca8c99a0","level":"MUST","text":"For backwards compatibility it MUST also be able to access the `InstrumentationLibrary` [deprecated since 1.10.0] having the same name and version values as the `InstrumentationScope`.","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"4b52de1f8597","level":"MUST","text":"A function receiving this as argument MUST be able to reliably determine whether the Span has ended (some languages might implement this by having an end timestamp of `null`, others might have an explicit `hasEnded` boolean).","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"c6668105122a","level":"MUST","text":"Counts for attributes, events and links dropped due to collection limits MUST be available for exporters to report as described in the exporters specification.","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"0d419524601b","level":"MUST","text":"As an exception to the authoritative set of span properties defined in the API spec, implementations MAY choose not to expose (and store) the full parent Context of the Span but they MUST expose at least the full parent SpanContext.","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"201d395e7eeb","level":"MUST","text":"It MUST be possible for functions being called with this to somehow obtain the same `Span` instance and type that the span creation API returned (or will return) to the user (for example, the `Span` could be one of the parameters passed to such a function, or a getter could be provided).","section":"specification/trace/sdk.md#additional-span-interfaces","sectionTitle":"Additional Span Interfaces","status":"Stable","source":"spec"},{"id":"f5b0c66927b9","level":"MUST","text":"Description MUST be `AlwaysOffSampler`.","section":"specification/trace/sdk.md#alwaysoff","sectionTitle":"AlwaysOff","status":"Stable","source":"spec"},{"id":"d8e383bb2a0e","level":"MUST","text":"Description MUST be `AlwaysOnSampler`.","section":"specification/trace/sdk.md#alwayson","sectionTitle":"AlwaysOn","status":"Stable","source":"spec"},{"id":"abac9a27d082","level":"MUST","text":"Based on the decision from the wrapped root sampler, `AlwaysRecord` MUST behave as follows:","section":"specification/trace/sdk.md#alwaysrecord","sectionTitle":"AlwaysRecord","status":"Stable","source":"spec"},{"id":"d21921de4c41","level":"MUST","text":"The processor MUST synchronize calls to `Span Exporter`'s `Export` to make sure that they are not invoked concurrently.","section":"specification/trace/sdk.md#batching-processor","sectionTitle":"Batching processor","status":"Stable","source":"spec"},{"id":"550ffcffdd26","level":"SHOULD","text":"The processor SHOULD export a batch when any of the following happens AND the previous export call has returned:","section":"specification/trace/sdk.md#batching-processor","sectionTitle":"Batching processor","status":"Stable","source":"spec"},{"id":"7f22c53e06e9","level":"MAY","text":"If the queue is empty when an export is triggered, the processor MAY export an empty batch OR skip the export and consider it to be completed immediately.","section":"specification/trace/sdk.md#batching-processor","sectionTitle":"Batching processor","status":"Stable","source":"spec"},{"id":"834d552c1ffb","level":"MUST","text":"The standard OpenTelemetry SDK MUST implement both simple and batch processors, as described below.","section":"specification/trace/sdk.md#built-in-span-processors","sectionTitle":"Built-in span processors","status":"Stable","source":"spec"},{"id":"dd96fca987d2","level":"SHOULD","text":"When a ProbabilitySampler Sampler makes a decision for a non-root Span using TraceID randomness when the Trace random flag was not set, the SDK SHOULD issue a warning statement in its log with a compatibility warning.","section":"specification/trace/sdk.md#compatibility-warnings-for-probabilitysampler","sectionTitle":"Compatibility warnings for `ProbabilitySampler`","status":"Stable","source":"spec"},{"id":"fb18c0bae88e","level":"SHOULD","text":"When this sampler observes a non-empty parent span context, meaning when it is used not as a root sampler, the SDK SHOULD emit a warning such as:","section":"specification/trace/sdk.md#compatibility-warnings-for-traceidratiobased-sampler","sectionTitle":"Compatibility warnings for `TraceIdRatioBased` sampler","status":"Stable","source":"spec"},{"id":"875a2aab77d4","level":"MAY","text":"In such a scenario, this sampler can also detect the use of a `ProbabilitySampler` by inspecting Tracestate for OpenTelemetry tracestate (`ot=...`) with `th` or `rv` subkeys, in which case the warning MAY be more direct:","section":"specification/trace/sdk.md#compatibility-warnings-for-traceidratiobased-sampler","sectionTitle":"Compatibility warnings for `TraceIdRatioBased` sampler","status":"Stable","source":"spec"},{"id":"9fab04a83139","level":"SHOULD","text":"For the zero case a `ComposableAlwaysOff` instance SHOULD be returned instead.","section":"specification/trace/sdk.md#composableprobability","sectionTitle":"ComposableProbability","status":"Stable","source":"spec"},{"id":"3d061937626f","level":"MUST","text":"Tracer Provider - Tracer creation, `ForceFlush` and `Shutdown` MUST be safe to be called concurrently.","section":"specification/trace/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"98d5e413b84b","level":"MUST","text":"Sampler - `ShouldSample` and `GetDescription` MUST be safe to be called concurrently.","section":"specification/trace/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"60b97f1ddf87","level":"MUST","text":"Span processor - all methods MUST be safe to be called concurrently.","section":"specification/trace/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"2554604cc8c7","level":"MUST","text":"Span Exporter - `ForceFlush` and `Shutdown` MUST be safe to be called concurrently.","section":"specification/trace/sdk.md#concurrency-requirements","sectionTitle":"Concurrency requirements","status":"Stable","source":"spec"},{"id":"2c4030c1198e","level":"MUST","text":"Configuration ( i.e., SpanProcessors, IdGenerator, SpanLimits, `Sampler`, and (Development) TracerConfigurator) MUST be owned by the `TracerProvider`.","section":"specification/trace/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"873cd444ba87","level":"MAY","text":"The configuration MAY be applied at the time of `TracerProvider` creation if appropriate.","section":"specification/trace/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"38adb3c3b22d","level":"MAY","text":"The TracerProvider MAY provide methods to update the configuration.","section":"specification/trace/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"3a592b856a13","level":"MUST NOT","text":"If configuration is updated (e.g., adding a `SpanProcessor`), the updated configuration MUST also apply to all already returned `Tracers` (i.e. it MUST NOT matter whether a `Tracer` was obtained from the `TracerProvider` before or after the configuration change).","section":"specification/trace/sdk.md#configuration","sectionTitle":"Configuration","status":"Stable","source":"spec"},{"id":"58e57cb1bdc9","level":"MUST NOT","text":"SDKs and Samplers MUST NOT overwrite explicit randomness in an OpenTelemetry TraceState value.","section":"specification/trace/sdk.md#do-not-overwrite-explicit-randomness","sectionTitle":"Do not overwrite explicit randomness","status":"Stable","source":"spec"},{"id":"381e0d544952","level":"MUST","text":"`Enabled` MUST return `false` when either:","section":"specification/trace/sdk.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"b2f26c8bf46a","level":"SHOULD","text":"Otherwise, it SHOULD return `true`.","section":"specification/trace/sdk.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"1884e5663341","level":"MAY","text":"It MAY return `false` to support additional optimizations and features.","section":"specification/trace/sdk.md#enabled","sectionTitle":"Enabled","status":"Stable","source":"spec"},{"id":"5e489d61b9a4","level":"MUST NOT","text":"Export() MUST NOT block indefinitely, there MUST be a reasonable upper limit after which the call must time out with an error result (`Failure`).","section":"specification/trace/sdk.md#exportbatch","sectionTitle":"`Export(batch)`","status":"Stable","source":"spec"},{"id":"ea29a5753a86","level":"SHOULD NOT","text":"The default SDK's Span Processors SHOULD NOT implement retry logic, as the required logic is likely to depend heavily on the specific protocol and backend the spans are being sent to.","section":"specification/trace/sdk.md#exportbatch","sectionTitle":"`Export(batch)`","status":"Stable","source":"spec"},{"id":"ba62722aac05","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/trace/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"f21cc42919b7","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/trace/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"ad8cf7547ea3","level":"MUST","text":"`ForceFlush` MUST invoke `ForceFlush` on all registered `SpanProcessors`.","section":"specification/trace/sdk.md#forceflush","sectionTitle":"ForceFlush","status":"Stable","source":"spec"},{"id":"42e47dfdfe78","level":"SHOULD","text":"This is a hint to ensure that any tasks associated with `Spans` for which the `SpanProcessor` had already received events prior to the call to `ForceFlush` SHOULD be completed as soon as possible, preferably before returning from this method.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"b0e777dd51a0","level":"SHOULD","text":"In particular, if any `SpanProcessor` has any associated exporter, it SHOULD try to call the exporter's `Export` with all spans for which this was not already done and then invoke `ForceFlush` on it.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"3b2088d6934b","level":"MUST","text":"The built-in SpanProcessors MUST do so.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"d36dbab45ddf","level":"MUST","text":"If a timeout is specified (see below), the SpanProcessor MUST prioritize honoring the timeout over finishing all calls.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"0371a962cdce","level":"MAY","text":"It MAY skip or abort some or all Export or ForceFlush calls it has made to achieve this goal.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"cd9389f05c4f","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"155e01b60a91","level":"SHOULD","text":"`ForceFlush` SHOULD only be called in cases where it is absolutely necessary, such as when using some FaaS providers that may suspend the process after an invocation, but before the `SpanProcessor` exports the completed spans.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"2fb64609b653","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/trace/sdk.md#forceflush-1","sectionTitle":"ForceFlush()","status":"Stable","source":"spec"},{"id":"1863adaa4466","level":"SHOULD","text":"This is a hint to ensure that the export of any `Spans` the exporter has received prior to the call to `ForceFlush` SHOULD be completed as soon as possible, preferably before returning from this method.","section":"specification/trace/sdk.md#forceflush-2","sectionTitle":"`ForceFlush()`","status":"Stable","source":"spec"},{"id":"4bedb2d7f2a2","level":"SHOULD","text":"`ForceFlush` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/trace/sdk.md#forceflush-2","sectionTitle":"`ForceFlush()`","status":"Stable","source":"spec"},{"id":"990f78aeea27","level":"SHOULD","text":"`ForceFlush` SHOULD only be called in cases where it is absolutely necessary, such as when using some FaaS providers that may suspend the process after an invocation, but before the exporter exports the completed spans.","section":"specification/trace/sdk.md#forceflush-2","sectionTitle":"`ForceFlush()`","status":"Stable","source":"spec"},{"id":"eadaa0f68d25","level":"SHOULD","text":"`ForceFlush` SHOULD complete or abort within some timeout.","section":"specification/trace/sdk.md#forceflush-2","sectionTitle":"`ForceFlush()`","status":"Stable","source":"spec"},{"id":"7c511e8e436a","level":"MAY","text":"Description MAY change over time, for example, if the sampler supports dynamic configuration or otherwise adjusts its parameters.","section":"specification/trace/sdk.md#getdescription","sectionTitle":"GetDescription","status":"Stable","source":"spec"},{"id":"a2b8729c5e2e","level":"SHOULD NOT","text":"Callers SHOULD NOT cache the returned value.","section":"specification/trace/sdk.md#getdescription","sectionTitle":"GetDescription","status":"Stable","source":"spec"},{"id":"214e04dcd7c6","level":"MAY","text":"Parent context, threshold, incoming trace state, and trace flag information MAY be precomputed so that ComposableSamplers do not repeatedly probe the Context for this information.","section":"specification/trace/sdk.md#getsamplingintent","sectionTitle":"GetSamplingIntent","status":"Stable","source":"spec"},{"id":"7d09a59dbe2e","level":"MUST NOT","text":"Note: ComposableSamplers MUST NOT modify the parameters passed to delegate GetSamplingIntent methods, as they are considered read-only state.","section":"specification/trace/sdk.md#getsamplingintent","sectionTitle":"GetSamplingIntent","status":"Stable","source":"spec"},{"id":"501985898974","level":"MUST NOT","text":"ComposableSamplers MUST NOT modify the OpenTelemetry TraceState (i.e., the `ot` sub-key of TraceState).","section":"specification/trace/sdk.md#getsamplingintent","sectionTitle":"GetSamplingIntent","status":"Stable","source":"spec"},{"id":"0f8404130303","level":"SHOULD","text":"The calling CompositeSampler SHOULD update the threshold of the outgoing TraceState, as described above.","section":"specification/trace/sdk.md#getsamplingintent","sectionTitle":"GetSamplingIntent","status":"Stable","source":"spec"},{"id":"8bace8929e11","level":"MUST","text":"The explicit randomness values MUST not be modified.","section":"specification/trace/sdk.md#getsamplingintent","sectionTitle":"GetSamplingIntent","status":"Stable","source":"spec"},{"id":"a955fcac1b9f","level":"MUST","text":"The SDK MUST by default randomly generate both the `TraceId` and the `SpanId`.","section":"specification/trace/sdk.md#id-generators","sectionTitle":"ID Generators","status":"Stable","source":"spec"},{"id":"816e42d695b9","level":"MUST","text":"The SDK MUST provide a mechanism for customizing the way IDs are generated for both the `TraceId` and the `SpanId`.","section":"specification/trace/sdk.md#id-generators","sectionTitle":"ID Generators","status":"Stable","source":"spec"},{"id":"4f8710c4abff","level":"MUST","text":"The SDK MAY provide this functionality by allowing custom implementations of an interface like the Java example below (name of the interface MAY be `IdGenerator`, name of the methods MUST be consistent with SpanContext), which provides extension points for two methods, one to generate a `SpanId` and one for `TraceId`.","section":"specification/trace/sdk.md#id-generators","sectionTitle":"ID Generators","status":"Stable","source":"spec"},{"id":"f472d5445ce0","level":"MUST NOT","text":"Additional `IdGenerator` implementing vendor-specific protocols such as AWS X-Ray trace ID generator MUST NOT be maintained or distributed as part of the OpenTelemetry Core packages.","section":"specification/trace/sdk.md#id-generators","sectionTitle":"ID Generators","status":"Stable","source":"spec"},{"id":"2d80c91ae137","level":"SHOULD","text":"If the SDK uses an `IdGenerator` extension point, the SDK SHOULD allow the extension to determine whether the Random flag is set when new IDs are generated.","section":"specification/trace/sdk.md#idgenerator-randomness","sectionTitle":"IdGenerator randomness","status":"Stable","source":"spec"},{"id":"7a07a849d93a","level":"SHOULD","text":"Custom implementations of the `IdGenerator` SHOULD identify themselves appropriately when all generated TraceID values meet the [W3C Trace Context Level 2 randomness requirements][W3CCONTEXTTRACEID], so that the Trace `random` flag will be set in the associated Trace contexts.","section":"specification/trace/sdk.md#idgenerator-randomness-1","sectionTitle":"IdGenerator randomness","status":"Stable","source":"spec"},{"id":"1b81febf7bb1","level":"MUST","text":"The `SpanProcessor` interface MUST declare the following methods:","section":"specification/trace/sdk.md#interface-definition","sectionTitle":"Interface definition","status":"Stable","source":"spec"},{"id":"47b701172bf8","level":"SHOULD","text":"The `SpanProcessor` interface SHOULD declare the following methods:","section":"specification/trace/sdk.md#interface-definition","sectionTitle":"Interface definition","status":"Stable","source":"spec"},{"id":"b8b3e96f6c56","level":"MUST","text":"The exporter MUST support three functions: Export, Shutdown, and ForceFlush.","section":"specification/trace/sdk.md#interface-definition-1","sectionTitle":"Interface Definition","status":"Stable","source":"spec"},{"id":"5378245bcb84","level":"MUST","text":"The end timestamp MUST have been computed (the `OnEnding` method duration is not included in the span duration).","section":"specification/trace/sdk.md#onending","sectionTitle":"OnEnding","status":"Stable","source":"spec"},{"id":"0b18305943f3","level":"MUST","text":"The Span object MUST still be mutable (i.e., `SetAttribute`, `AddLink`, `AddEvent` can be called) while `OnEnding` is called.","section":"specification/trace/sdk.md#onending","sectionTitle":"OnEnding","status":"Stable","source":"spec"},{"id":"7a4655bf7fde","level":"MUST","text":"This method MUST be called synchronously within the `Span.End()` API, therefore it should not block or throw an exception.","section":"specification/trace/sdk.md#onending","sectionTitle":"OnEnding","status":"Stable","source":"spec"},{"id":"cdf3002eb2b2","level":"MUST","text":"The SDK MUST guarantee that the span can no longer be modified by any other thread before invoking `OnEnding` of the first `SpanProcessor`.","section":"specification/trace/sdk.md#onending","sectionTitle":"OnEnding","status":"Stable","source":"spec"},{"id":"73f75a46c8f2","level":"MUST","text":"This method MUST be called synchronously within the `Span.End()` API, therefore it should not block or throw an exception.","section":"specification/trace/sdk.md#onendspan","sectionTitle":"OnEnd(Span)","status":"Stable","source":"spec"},{"id":"aa6dea7def8e","level":"SHOULD","text":"It SHOULD be possible to keep a reference to this span object and updates to the span SHOULD be reflected in it.","section":"specification/trace/sdk.md#onstart","sectionTitle":"OnStart","status":"Stable","source":"spec"},{"id":"3613d2e5c613","level":"SHOULD","text":"For all span contexts, OpenTelemetry samplers SHOULD presume that TraceIDs meet the W3C Trace Context Level 2 randomness requirements, unless an explicit randomness value is present in the [`rv` sub-key of the OpenTelemetry TraceState][OTELRVALUE].","section":"specification/trace/sdk.md#presumption-of-traceid-randomness","sectionTitle":"Presumption of TraceID randomness","status":"Stable","source":"spec"},{"id":"7103ffd8cb85","level":"MUST","text":"The `ProbabilitySampler` sampler MUST ignore the parent `SampledFlag`.","section":"specification/trace/sdk.md#probabilitysampler","sectionTitle":"ProbabilitySampler","status":"Stable","source":"spec"},{"id":"25b9b5beb0f3","level":"SHOULD","text":"When (R >= T), the OpenTelemetry TraceState SHOULD be modified to include the key-value `th:T` for rejection threshold value (T), as specified for the [OpenTelemetry TraceState `th` sub-key][TRACESTATEHANDLING].","section":"specification/trace/sdk.md#probabilitysampler-sampler-algorithm","sectionTitle":"`ProbabilitySampler` sampler algorithm","status":"Stable","source":"spec"},{"id":"9473ee6a456c","level":"SHOULD","text":"For root span contexts, the SDK SHOULD set the `Random` flag in the trace flags when it generates TraceIDs that meet the [W3C Trace Context Level 2 randomness requirements][W3CCONTEXTTRACEID].","section":"specification/trace/sdk.md#random-trace-flag","sectionTitle":"Random trace flag","status":"Stable","source":"spec"},{"id":"b3be51b33018","level":"MUST","text":"The sampling algorithm MUST be deterministic.","section":"specification/trace/sdk.md#requirements-for-traceidratiobased-sampler-algorithm","sectionTitle":"Requirements for `TraceIdRatioBased` sampler algorithm","status":"Stable","source":"spec"},{"id":"4f94592fb19e","level":"MUST","text":"A trace identified by a given `TraceId` is sampled or not independent of language, time, etc. To achieve this, implementations MUST use a deterministic hash of the `TraceId` when computing the sampling decision.","section":"specification/trace/sdk.md#requirements-for-traceidratiobased-sampler-algorithm","sectionTitle":"Requirements for `TraceIdRatioBased` sampler algorithm","status":"Stable","source":"spec"},{"id":"2aebd11e653a","level":"MUST","text":"A `TraceIdRatioBased` sampler with a given sampling probability MUST also sample all traces that any `TraceIdRatioBased` sampler with a lower sampling probability would sample.","section":"specification/trace/sdk.md#requirements-for-traceidratiobased-sampler-algorithm","sectionTitle":"Requirements for `TraceIdRatioBased` sampler algorithm","status":"Stable","source":"spec"},{"id":"0872d7619fcd","level":"MAY","text":"Root Samplers MAY insert an explicit randomness value into the OpenTelemetry TraceState value in cases where an explicit randomness value is not already set.","section":"specification/trace/sdk.md#root-samplers-set-explicit-randomness-for-non-random-traceids","sectionTitle":"Root samplers set explicit randomness for non-random TraceIDs","status":"Stable","source":"spec"},{"id":"46e400dfbb91","level":"MUST","text":"Span Processor MUST receive only those spans which have this field set to `true`.","section":"specification/trace/sdk.md#sampling","sectionTitle":"Sampling","status":"Stable","source":"spec"},{"id":"0c72d6596d51","level":"SHOULD NOT","text":"However, Span Exporter SHOULD NOT receive them unless the `Sampled` flag was also set.","section":"specification/trace/sdk.md#sampling","sectionTitle":"Sampling","status":"Stable","source":"spec"},{"id":"6b5698ede917","level":"SHOULD NOT","text":"Span Exporters MUST receive those spans which have `Sampled` flag set to true and they SHOULD NOT receive the ones that do not.","section":"specification/trace/sdk.md#sampling","sectionTitle":"Sampling","status":"Stable","source":"spec"},{"id":"b8acca2b5461","level":"MUST NOT","text":"The flag combination `SampledFlag == true` and `IsRecording == false` could cause gaps in the distributed trace, and because of this the OpenTelemetry SDK MUST NOT allow this combination.","section":"specification/trace/sdk.md#sampling","sectionTitle":"Sampling","status":"Stable","source":"spec"},{"id":"887117c329b0","level":"MUST","text":"When asked to create a Span, the SDK MUST act as if doing the following in order:","section":"specification/trace/sdk.md#sdk-span-creation","sectionTitle":"SDK Span creation","status":"Stable","source":"spec"},{"id":"1a94666b469c","level":"MAY","text":"A non-recording span MAY be implemented using the same mechanism as when a `Span` is created without an SDK installed or as described in wrapping a SpanContext in a Span.","section":"specification/trace/sdk.md#sdk-span-creation","sectionTitle":"SDK Span creation","status":"Stable","source":"spec"},{"id":"e045ea173584","level":"SHOULD","text":"The Tracing SDK SHOULD support SDK self-observability.","section":"specification/trace/sdk.md#self-observability","sectionTitle":"Self-observability","status":"Stable","source":"spec"},{"id":"2218ca9b534f","level":"MUST","text":"If the parent `SpanContext` contains a valid `TraceId`, they MUST always match.","section":"specification/trace/sdk.md#shouldsample","sectionTitle":"ShouldSample","status":"Stable","source":"spec"},{"id":"ccbfff4c5f13","level":"MUST NOT","text":"`RECORD_ONLY` - `IsRecording` will be `true`, but the `Sampled` flag MUST NOT be set.","section":"specification/trace/sdk.md#shouldsample","sectionTitle":"ShouldSample","status":"Stable","source":"spec"},{"id":"fcaebf9d8d34","level":"MUST","text":"`RECORDANDSAMPLE` - `IsRecording` will be `true` and the `Sampled` flag MUST be set.","section":"specification/trace/sdk.md#shouldsample","sectionTitle":"ShouldSample","status":"Stable","source":"spec"},{"id":"39d23bbde080","level":"SHOULD","text":"If the sampler returns an empty `Tracestate` here, the `Tracestate` will be cleared, so samplers SHOULD normally return the passed-in `Tracestate` if they do not intend to change it.","section":"specification/trace/sdk.md#shouldsample","sectionTitle":"ShouldSample","status":"Stable","source":"spec"},{"id":"1e550c5700d6","level":"MUST","text":"`Shutdown` MUST be called only once for each `TracerProvider` instance.","section":"specification/trace/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"e7f9fc795ba7","level":"SHOULD","text":"SDKs SHOULD return a valid no-op Tracer for these calls, if possible.","section":"specification/trace/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"83d5782da83a","level":"SHOULD","text":"`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/trace/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"4672aa2b9b70","level":"SHOULD","text":"`Shutdown` SHOULD complete or abort within some timeout.","section":"specification/trace/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"490b3b793dc1","level":"MUST","text":"`Shutdown` MUST be implemented at least by invoking `Shutdown` within all internal processors.","section":"specification/trace/sdk.md#shutdown","sectionTitle":"Shutdown","status":"Stable","source":"spec"},{"id":"466e082761c6","level":"SHOULD","text":"`Shutdown` SHOULD be called only once for each `SpanProcessor` instance.","section":"specification/trace/sdk.md#shutdown-1","sectionTitle":"Shutdown()","status":"Stable","source":"spec"},{"id":"ea76d59440f5","level":"SHOULD","text":"SDKs SHOULD ignore these calls gracefully, if possible.","section":"specification/trace/sdk.md#shutdown-1","sectionTitle":"Shutdown()","status":"Stable","source":"spec"},{"id":"37c32da314d2","level":"SHOULD","text":"`Shutdown` SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.","section":"specification/trace/sdk.md#shutdown-1","sectionTitle":"Shutdown()","status":"Stable","source":"spec"},{"id":"b1aead1413f8","level":"MUST","text":"`Shutdown` MUST include the effects of `ForceFlush`.","section":"specification/trace/sdk.md#shutdown-1","sectionTitle":"Shutdown()","status":"Stable","source":"spec"},{"id":"45bd42f931cf","level":"SHOULD","text":"`Shutdown` SHOULD complete or abort within some timeout.","section":"specification/trace/sdk.md#shutdown-1","sectionTitle":"Shutdown()","status":"Stable","source":"spec"},{"id":"87d2a3746f8b","level":"MUST","text":"The processor MUST synchronize calls to `Span Exporter`'s `Export` to make sure that they are not invoked concurrently.","section":"specification/trace/sdk.md#simple-processor","sectionTitle":"Simple processor","status":"Stable","source":"spec"},{"id":"1b806b28f13e","level":"MUST","text":"Each implementation MUST document the concurrency characteristics the SDK requires of the exporter.","section":"specification/trace/sdk.md#span-exporter","sectionTitle":"Span Exporter","status":"Stable","source":"spec"},{"id":"e3e17b8949ff","level":"MUST","text":"Span attributes MUST adhere to the common rules of attribute limits.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"c24984603e4e","level":"MAY","text":"SDK Spans MAY also discard links and events that would increase the number of elements of each collection beyond the configured limit.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"7bd36c1c2e09","level":"MUST","text":"If the SDK implements the limits above it MUST provide a way to change these limits, via a configuration to the TracerProvider, by allowing users to configure individual limits like in the Java example bellow.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"0ff523cd341c","level":"SHOULD","text":"The name of the configuration options SHOULD be `EventCountLimit` and `LinkCountLimit`.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"f4828f026bf2","level":"SHOULD","text":"The options MAY be bundled in a class, which then SHOULD be called `SpanLimits`.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"868ea96f164c","level":"MAY","text":"Implementations MAY provide additional configuration such as `AttributePerEventCountLimit` and `AttributePerLinkCountLimit`.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"610c0386188b","level":"SHOULD","text":"There SHOULD be a message printed in the SDK's log to indicate to the user that an attribute, event, or link was discarded due to such a limit.","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"10a28a38f0bd","level":"MUST","text":"To prevent excessive logging, the message MUST be printed at most once per span (i.e., not per discarded attribute, event, or link).","section":"specification/trace/sdk.md#span-limits","sectionTitle":"Span Limits","status":"Stable","source":"spec"},{"id":"0f499d3dda78","level":"MUST","text":"SDK MUST allow to end each pipeline with individual exporter.","section":"specification/trace/sdk.md#span-processor","sectionTitle":"Span processor","status":"Stable","source":"spec"},{"id":"5514b0a6a222","level":"MUST","text":"SDK MUST allow users to implement and configure custom processors.","section":"specification/trace/sdk.md#span-processor","sectionTitle":"Span processor","status":"Stable","source":"spec"},{"id":"4f6617c50a59","level":"SHOULD","text":"For root span contexts, the SDK SHOULD implement the TraceID randomness requirements of the [W3C Trace Context Level 2][W3CCONTEXTTRACEID] Candidate Recommendation when generating TraceID values.","section":"specification/trace/sdk.md#traceid-randomness","sectionTitle":"TraceID randomness","status":"Stable","source":"spec"},{"id":"859a094e70ef","level":"SHALL NOT","text":"OpenTelemetry SDK implementors SHALL NOT remove or modify the behavior of the original `TraceIdRatioBased` sampler until at least January 1,","section":"specification/trace/sdk.md#traceidratiobased","sectionTitle":"TraceIdRatioBased","status":"Stable","source":"spec"},{"id":"bbad7e41fa8e","level":"MUST","text":"The `TraceIdRatioBased` MUST ignore the parent `SampledFlag`.","section":"specification/trace/sdk.md#traceidratiobased","sectionTitle":"TraceIdRatioBased","status":"Stable","source":"spec"},{"id":"b86bc9415dd0","level":"MUST","text":"Description MUST return a string of the form `\"TraceIdRatioBased{RATIO}\"` with `RATIO` replaced with the Sampler instance's trace sampling ratio represented as a decimal number.","section":"specification/trace/sdk.md#traceidratiobased","sectionTitle":"TraceIdRatioBased","status":"Stable","source":"spec"},{"id":"3a68f054072d","level":"SHOULD","text":"The precision of the number SHOULD follow implementation language standards and SHOULD be high enough to identify when Samplers have different ratios.","section":"specification/trace/sdk.md#traceidratiobased","sectionTitle":"TraceIdRatioBased","status":"Stable","source":"spec"},{"id":"5caddc1ac10e","level":"MUST","text":"Status: Development - `Tracer` MUST behave according to the TracerConfig computed during Tracer creation.","section":"specification/trace/sdk.md#tracer","sectionTitle":"Tracer","status":"Stable","source":"spec"},{"id":"dcdef94468b5","level":"MUST","text":"If the `TracerProvider` supports updating the TracerConfigurator, then upon update the `Tracer` MUST be updated to behave according to the new `TracerConfig`.","section":"specification/trace/sdk.md#tracer","sectionTitle":"Tracer","status":"Stable","source":"spec"},{"id":"3410d114f3e9","level":"SHOULD","text":"It SHOULD only be possible to create `Tracer` instances through a `TracerProvider` (see API).","section":"specification/trace/sdk.md#tracer-creation","sectionTitle":"Tracer Creation","status":"Stable","source":"spec"},{"id":"7b6fc4e560fa","level":"MUST","text":"The `TracerProvider` MUST implement the Get a Tracer API.","section":"specification/trace/sdk.md#tracer-creation","sectionTitle":"Tracer Creation","status":"Stable","source":"spec"},{"id":"e41baf607e86","level":"MUST","text":"The input provided by the user MUST be used to create an `InstrumentationScope` instance which is stored on the created `Tracer`.","section":"specification/trace/sdk.md#tracer-creation","sectionTitle":"Tracer Creation","status":"Stable","source":"spec"},{"id":"fe598c9b266b","level":"MUST","text":"Status: Development - The `TracerProvider` MUST compute the relevant TracerConfig using the configured TracerConfigurator, and create a `Tracer` whose behavior conforms to that `TracerConfig`.","section":"specification/trace/sdk.md#tracer-creation","sectionTitle":"Tracer Creation","status":"Stable","source":"spec"},{"id":"1b064f58a303","level":"SHOULD","text":"If not explicitly set, the `enabled` parameter SHOULD default to `true` ( i.e. `Tracer`s are enabled by default).","section":"specification/trace/sdk.md#tracerconfig","sectionTitle":"TracerConfig","status":"Stable","source":"spec"},{"id":"8e443e543f81","level":"MUST","text":"If a `Tracer` is disabled, it MUST behave equivalently to a No-op Tracer.","section":"specification/trace/sdk.md#tracerconfig","sectionTitle":"TracerConfig","status":"Stable","source":"spec"},{"id":"52d3cc4b7985","level":"MUST","text":"The value of `enabled` MUST be used to resolve whether a `Tracer` is Enabled.","section":"specification/trace/sdk.md#tracerconfig","sectionTitle":"TracerConfig","status":"Stable","source":"spec"},{"id":"0b8bc0d4e336","level":"MUST","text":"However, the changes MUST be eventually visible.","section":"specification/trace/sdk.md#tracerconfig","sectionTitle":"TracerConfig","status":"Stable","source":"spec"},{"id":"5db4449ebe50","level":"MUST","text":"The function MUST accept the following parameter:","section":"specification/trace/sdk.md#tracerconfigurator","sectionTitle":"TracerConfigurator","status":"Stable","source":"spec"},{"id":"c065a703c07b","level":"MUST","text":"The function MUST return the relevant `TracerConfig`, or some signal indicating that the default TracerConfig should be used.","section":"specification/trace/sdk.md#tracerconfigurator","sectionTitle":"TracerConfigurator","status":"Stable","source":"spec"},{"id":"d2184bbd143c","level":"MAY","text":"This signal MAY be nil, null, empty, or an instance of the default `TracerConfig` depending on what is idiomatic in the language.","section":"specification/trace/sdk.md#tracerconfigurator","sectionTitle":"TracerConfigurator","status":"Stable","source":"spec"},{"id":"9b8924780025","level":"MAY","text":"However, implementations MAY provide shorthand or helper functions to accommodate common use cases:","section":"specification/trace/sdk.md#tracerconfigurator","sectionTitle":"TracerConfigurator","status":"Stable","source":"spec"},{"id":"e4849c107c58","level":"MUST","text":"Values of `rv` MUST be exactly 14 lower-case hexadecimal digits:","section":"specification/trace/tracestate-handling.md#explicit-randomness-value-rv","sectionTitle":"Explicit randomness value `rv`","status":"Development","source":"spec"},{"id":"074127d5c2d7","level":"SHOULD NOT","text":"Explicit randomness values SHOULD NOT be erased from the OpenTelemetry TraceState or modified once associated with a new TraceID, so that sampling decisions made using the explicit randomness value are consistent across signals.","section":"specification/trace/tracestate-handling.md#explicit-randomness-value-rv","sectionTitle":"Explicit randomness value `rv`","status":"Development","source":"spec"},{"id":"e8e84646db14","level":"MUST","text":"Specific keys used by OTel concerns MUST be defined as part of the Specification, and hence it is forbidden to use any key that has not been defined in the Specification itself.","section":"specification/trace/tracestate-handling.md#key","sectionTitle":"Key","status":"Development","source":"spec"},{"id":"1ca152562196","level":"MUST","text":"Set values MUST be either updated or added to the `ot` entry in `TraceState`, in order to preserve existing values belonging to other OTel concerns.","section":"specification/trace/tracestate-handling.md#setting-values","sectionTitle":"Setting values","status":"Development","source":"spec"},{"id":"457d598e6288","level":"MUST","text":"When setting TraceState values that are part of the OTel ecosystem, they MUST all be contained in a single entry using the `ot` key, with the value being a semicolon separated list of key-value pairs such as:","section":"specification/trace/tracestate-handling.md#tracestate-handling","sectionTitle":"TraceState Handling","status":"Development","source":"spec"},{"id":"c158d86a60d8","level":"MUST NOT","text":"The complete list length MUST NOT exceed 256 characters, as defined by the TraceState value section, and the used keys MUST be unique.","section":"specification/trace/tracestate-handling.md#tracestate-handling","sectionTitle":"TraceState Handling","status":"Development","source":"spec"},{"id":"a7925dd47799","level":"MUST NOT","text":"Instrumentation libraries and clients MUST NOT use this entry, and they MUST instead use their own entry.","section":"specification/trace/tracestate-handling.md#tracestate-handling","sectionTitle":"TraceState Handling","status":"Development","source":"spec"},{"id":"ebee181bf66d","level":"MUST NOT","text":"Although it has no maximum allowed length, it is recommended to use short values, as the entire list of key-values MUST NOT exceed 256 characters.","section":"specification/trace/tracestate-handling.md#value","sectionTitle":"Value","status":"Development","source":"spec"},{"id":"92ec5b56d44c","level":"MUST","text":"For this, two values MUST be present:","section":"specification/trace/tracestate-probability-sampling.md#decision-algorithm","sectionTitle":"Decision algorithm","status":"Development","source":"spec"},{"id":"9a0264f20d7c","level":"SHOULD","text":"To avoid inconsistency during this transition, users SHOULD follow this guidance until all Trace SDKs in a system have been upgraded to modern Trace randomness requirements based on W3C Trace Context Level 2.","section":"specification/trace/tracestate-probability-sampling.md#migration-to-consistent-probability-samplers","sectionTitle":"Migration to consistent probability samplers","status":"Development","source":"spec"},{"id":"7688301476ff","level":"MUST","text":"Maintainers of the official OpenTelemetry SDKs as well as maintainers of alternative SDKs MUST keep their implementations up to date and compatible with the latest version of the OpenTelemetry API.","section":"specification/upgrading.md#sdk-implementors","sectionTitle":"SDK Implementors","status":"Unspecified","source":"spec"},{"id":"df93ef8d615c","level":"MUST NOT","text":"Backward-incompatible changes to API packages MUST NOT be made unless the major version number is incremented.","section":"specification/versioning-and-stability.md#api-stability","sectionTitle":"API Stability","status":"Stable","source":"spec"},{"id":"5a3840f59c09","level":"MUST","text":"All existing API calls MUST continue to compile and function against all future minor versions of the same major version.","section":"specification/versioning-and-stability.md#api-stability","sectionTitle":"API Stability","status":"Stable","source":"spec"},{"id":"2155f32ade24","level":"SHOULD","text":"Languages which ship binary artifacts SHOULD offer ABI compatibility for API packages.","section":"specification/versioning-and-stability.md#api-stability","sectionTitle":"API Stability","status":"Stable","source":"spec"},{"id":"2e373965151a","level":"MUST","text":"Major versions of the API MUST be supported for a minimum of three years after the release of the next major API version.","section":"specification/versioning-and-stability.md#api-support","sectionTitle":"API support","status":"Stable","source":"spec"},{"id":"60e59ed19fe6","level":"MUST","text":"API stability, as defined above, MUST be maintained.","section":"specification/versioning-and-stability.md#api-support","sectionTitle":"API support","status":"Stable","source":"spec"},{"id":"42b326fa93fb","level":"MUST","text":"Bug and security fixes MUST be backported.","section":"specification/versioning-and-stability.md#api-support","sectionTitle":"API support","status":"Stable","source":"spec"},{"id":"ae63d135ffb3","level":"NOT RECOMMENDED","text":"Additional feature development is NOT RECOMMENDED.","section":"specification/versioning-and-stability.md#api-support","sectionTitle":"API support","status":"Stable","source":"spec"},{"id":"d3f2120d9c39","level":"MUST","text":"Contrib packages available when the API is versioned MUST continue to be maintained for the duration of LTS.","section":"specification/versioning-and-stability.md#api-support","sectionTitle":"API support","status":"Stable","source":"spec"},{"id":"9253d8e3535f","level":"SHOULD","text":"Plugins, instrumentation, and other contrib packages SHOULD be kept up to date and compatible with the latest versions of the API, SDK, and Semantic Conventions.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"f522b9ac68b2","level":"SHOULD","text":"If a release of the API, SDK, or Semantic Conventions contains changes which are relevant to a contrib package, that package SHOULD be updated and released in a timely fashion.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"c1d2b8f6b202","level":"SHOULD","text":"Public portions of contrib packages (constructors, configuration, interfaces) SHOULD remain backward compatible.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"a7f50a28b919","level":"SHOULD","text":"Languages which ship binary artifacts SHOULD offer ABI compatibility for contrib packages.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"713b30f4d46c","level":"MAY","text":"Exception: Contrib packages MAY break stability when a required downstream dependency breaks stability.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"efcda4ec1a37","level":"RECOMMENDED","text":"However, it is strongly RECOMMENDED that older contrib packages remain stable.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"433c14288b8a","level":"SHOULD","text":"A new, incompatible version of an integration SHOULD be released as a separate contrib package, rather than break the existing contrib package.","section":"specification/versioning-and-stability.md#contrib-stability","sectionTitle":"Contrib Stability","status":"Stable","source":"spec"},{"id":"7dfbeccf0cd5","level":"MAY","text":"Signals MAY eventually be replaced.","section":"specification/versioning-and-stability.md#deprecated","sectionTitle":"Deprecated","status":"Stable","source":"spec"},{"id":"94c57b018190","level":"MUST NOT","text":"Signals MUST NOT be marked as deprecated unless the replacement is stable.","section":"specification/versioning-and-stability.md#deprecated","sectionTitle":"Deprecated","status":"Stable","source":"spec"},{"id":"26aaf01837d3","level":"MUST","text":"Deprecated code MUST abide by the same support guarantees as stable code.","section":"specification/versioning-and-stability.md#deprecated","sectionTitle":"Deprecated","status":"Stable","source":"spec"},{"id":"8a0271d9fded","level":"MUST","text":"It MUST always be possible to upgrade to the latest minor version of the OpenTelemetry SDK, without creating compilation or runtime errors.","section":"specification/versioning-and-stability.md#design-goals","sectionTitle":"Design goals","status":"Stable","source":"spec"},{"id":"75da1bd541b0","level":"MUST","text":"Code written against older versions of the API MUST work with all newer versions of the API.","section":"specification/versioning-and-stability.md#design-goals","sectionTitle":"Design goals","status":"Stable","source":"spec"},{"id":"7411276163ad","level":"MUST","text":"This means that an implementation wishing to release stable tracing today MUST ensure that in-development metrics are factored out in such a way that breaking changes to metrics API do not destabilize the trace API packages.","section":"specification/versioning-and-stability.md#design-goals","sectionTitle":"Design goals","status":"Stable","source":"spec"},{"id":"b2b85e8c91d6","level":"MAY","text":"While signals are in development, breaking changes and performance issues MAY occur.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"c7b66c835ec0","level":"SHOULD NOT","text":"Components SHOULD NOT be expected to be feature-complete.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"df6624cf2e5f","level":"MAY","text":"In some cases, the signal in Development MAY be discarded and removed entirely.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"b0ae1eca672e","level":"SHOULD NOT","text":"Long-term dependencies SHOULD NOT be taken against signals in Development.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"a70177aaf23d","level":"MUST","text":"OpenTelemetry clients MUST be designed in a manner that allows signals in Development to be created without breaking the stability guarantees of existing signals.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"377d450e5a50","level":"MUST NOT","text":"OpenTelemetry clients MUST NOT be designed in a manner that breaks existing users when a signal transitions from Development to Stable.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"dddc9ba21550","level":"MUST NOT","text":"Terms which denote stability, such as \"development\", MUST NOT be used as part of a directory or import name.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"520c9f73b051","level":"MAY","text":"Package version numbers MAY include a suffix, such as -alpha, -beta, -rc, or -development, to differentiate packages in different statuses.","section":"specification/versioning-and-stability.md#development","sectionTitle":"Development","status":"Stable","source":"spec"},{"id":"627f7ff09bc6","level":"MAY","text":"An existing API/SDK call MAY be extended without incrementing the major version number if the particular language allows to do it in a backward-compatible manner.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"a0786cd9a735","level":"MAY","text":"Similarly, existing SDK plugin interfaces MAY be extended with new methods without incrementing the major version number if the particular language allows to do it in a backward-compatible manner (e.g. by providing default implementations).","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"9f1f2724e672","level":"MUST","text":"Hereby, backwards-compatible means that end user's code that implements the plugin interfaces MUST continue to be possible to use with newer versions of the SDK without making changes to the end user's code.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"1df8d5a20220","level":"MUST","text":"For languages that commonly share code via binary artifacts, e.g. Java, backwards-compatible means that end user's code that implements plugin interfaces MUST continue to be possible to use with newer minor or patch versions without recompiling the end user's code.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"eaed744d62b0","level":"SHOULD","text":"If this backward compatible addition of methods to interfaces is not possible for a language, the language maintainers SHOULD still implement the addition using backwards-compatible workarounds without incrementing the major version.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"9ab9ffc2d730","level":"MAY","text":"Additionally, a Stable signal's API/SDK MAY be extended by adding new methods to existing Stable APIs.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"898f1bc5e38d","level":"SHOULD","text":"Language implementations SHOULD have a mechanism to do so, such that:","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"b2c2822e7db7","level":"SHOULD","text":"New in Development methods SHOULD require opt-in, so that the user is made aware of the risk associated with using the development API.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"0f44a327d6c6","level":"SHOULD","text":"Language maintainers SHOULD choose the idiomatic way for their language.","section":"specification/versioning-and-stability.md#extending-apisdk-abstractions","sectionTitle":"Extending API/SDK abstractions","status":"Stable","source":"spec"},{"id":"794fe21c2234","level":"SHOULD","text":"Each language implementation SHOULD define how the removal of a supported language/runtime version affects its versioning.","section":"specification/versioning-and-stability.md#language-version-support","sectionTitle":"Language version support","status":"Stable","source":"spec"},{"id":"7ef169c80a03","level":"SHOULD","text":"As a rule of thumb, it SHOULD follow the conventions in the given ecosystem.","section":"specification/versioning-and-stability.md#language-version-support","sectionTitle":"Language version support","status":"Stable","source":"spec"},{"id":"fa21a33d322f","level":"MUST","text":"Major version bumps MUST occur when there is a breaking change to a stable interface or a deprecated signal is removed.","section":"specification/versioning-and-stability.md#major-version-bump","sectionTitle":"Major version bump","status":"Stable","source":"spec"},{"id":"b41f23d1dd65","level":"SHOULD NOT","text":"Major version bumps SHOULD NOT occur for changes which do not result in a drop in support of some form.","section":"specification/versioning-and-stability.md#major-version-bump","sectionTitle":"Major version bump","status":"Stable","source":"spec"},{"id":"7122042b5746","level":"MUST","text":"A stable version of both tracing and metrics MUST be released in at least four languages.","section":"specification/versioning-and-stability.md#opentelemetry-ga","sectionTitle":"OpenTelemetry GA","status":"Stable","source":"spec"},{"id":"e66117e318b0","level":"MUST","text":"CI/CD, performance, and integration tests MUST be implemented for these languages.","section":"specification/versioning-and-stability.md#opentelemetry-ga","sectionTitle":"OpenTelemetry GA","status":"Stable","source":"spec"},{"id":"4b9302366d8f","level":"MAY","text":"Security and bug fixes MAY only be applied to the latest minor version.","section":"specification/versioning-and-stability.md#patch-version-bump","sectionTitle":"Patch version bump","status":"Stable","source":"spec"},{"id":"3c823878c183","level":"MUST","text":"The release MUST make a major version bump when this happens.","section":"specification/versioning-and-stability.md#removed","sectionTitle":"Removed","status":"Stable","source":"spec"},{"id":"c88a99078700","level":"MUST","text":"Public portions of SDK packages MUST remain backward compatible.","section":"specification/versioning-and-stability.md#sdk-stability","sectionTitle":"SDK Stability","status":"Stable","source":"spec"},{"id":"b232a57fd717","level":"SHOULD","text":"Languages which ship binary artifacts SHOULD offer ABI compatibility for SDK packages.","section":"specification/versioning-and-stability.md#sdk-stability","sectionTitle":"SDK Stability","status":"Stable","source":"spec"},{"id":"7a1eb6614a51","level":"SHOULD","text":"Changes to telemetry produced by OpenTelemetry instrumentation SHOULD avoid breaking analysis tools, such as dashboards and alerts.","section":"specification/versioning-and-stability.md#semantic-conventions-stability","sectionTitle":"Semantic Conventions Stability","status":"Stable","source":"spec"},{"id":"a6c7d01fbd77","level":"MAY","text":"The list of telemetry fields which are covered by stability guarantees MAY be extended.","section":"specification/versioning-and-stability.md#semantic-conventions-stability","sectionTitle":"Semantic Conventions Stability","status":"Stable","source":"spec"},{"id":"d504b84aba8a","level":"MUST","text":"All such changes MUST be described in the OpenTelemetry Schema File Format and published in this repository.","section":"specification/versioning-and-stability.md#semantic-conventions-stability","sectionTitle":"Semantic Conventions Stability","status":"Stable","source":"spec"},{"id":"a835fd0cd029","level":"MUST NOT","text":"These resource attributes MUST NOT be ever changed.","section":"specification/versioning-and-stability.md#semantic-conventions-stability","sectionTitle":"Semantic Conventions Stability","status":"Stable","source":"spec"},{"id":"fccc6f24f990","level":"MAY","text":"Other types of changes MAY be introduced in the future versions of this specification.","section":"specification/versioning-and-stability.md#semantic-conventions-stability","sectionTitle":"Semantic Conventions Stability","status":"Stable","source":"spec"},{"id":"07eb310ac6fb","level":"MAY","text":"Once a signal in Development has gone through rigorous testing, it MAY transition to Stable.","section":"specification/versioning-and-stability.md#stable","sectionTitle":"Stable","status":"Stable","source":"spec"},{"id":"131c6529cc36","level":"MAY","text":"Long-term dependencies MAY now be taken against this signal.","section":"specification/versioning-and-stability.md#stable","sectionTitle":"Stable","status":"Stable","source":"spec"},{"id":"83e229e35400","level":"MAY","text":"All signal components MAY become stable together, or MAY transition to stability component-by-component.","section":"specification/versioning-and-stability.md#stable","sectionTitle":"Stable","status":"Stable","source":"spec"},{"id":"faf6f1cd317b","level":"MUST","text":"The API MUST become stable before the other components.","section":"specification/versioning-and-stability.md#stable","sectionTitle":"Stable","status":"Stable","source":"spec"},{"id":"b7122d8c568a","level":"MUST","text":"Once a signal component is marked as stable, the following rules MUST apply until the end of that signal’s existence.","section":"specification/versioning-and-stability.md#stable","sectionTitle":"Stable","status":"Stable","source":"spec"},{"id":"c73f010a8768","level":"MUST","text":"OpenTelemetry clients MUST follow Semantic Versioning 2.0.0, with the following clarifications.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"6b989cf78911","level":"MUST","text":"For the purposes of versioning, all code within a component MUST treated as if it were part of a single package, and versioned with the same version number, except for Contrib, which may be a collection of packages versioned separately.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"994a442a1dad","level":"MUST","text":"All stable API packages MUST version together, across all signals.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"7068ef5f23e4","level":"MUST NOT","text":"Stable signals MUST NOT have separate version numbers.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"f4e285a63eb5","level":"MUST","text":"SDK packages for all signals MUST version together, across all signals.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"d180bdb83948","level":"MUST NOT","text":"Signals MUST NOT have separate version numbers.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"8cd75b5a217c","level":"MAY","text":"Each contrib package MAY have its own version number.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"34493d18a447","level":"MAY","text":"For example, the latest version of `opentelemetry-python-api` MAY be at v1.2.3 while the latest version of `opentelemetry-python-sdk` is at v2.3.1.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"5dd3009f9753","level":"MAY","text":"In these cases, signals in Development MAY version independently from stable signals, in order to retain a 0.X version number.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"b46b1eebc5c0","level":"MUST","text":"When a signal becomes stable, the version MUST be bumped to match the other stable signals in the release.","section":"specification/versioning-and-stability.md#version-numbers","sectionTitle":"Version numbers","status":"Stable","source":"spec"},{"id":"663da2f26ce4","level":"MUST","text":"Each language implementation MUST take these versioning and stability requirements, and produce a language-specific document which details how these requirements will be met.","section":"specification/versioning-and-stability.md#versioning-and-stability-for-opentelemetry-clients","sectionTitle":"Versioning and stability for OpenTelemetry clients","status":"Stable","source":"spec"},{"id":"1561f00de942","level":"MUST","text":"This document MUST be placed in the root of each repository and named `VERSIONING` or `VERSIONING.md`.","section":"specification/versioning-and-stability.md#versioning-and-stability-for-opentelemetry-clients","sectionTitle":"Versioning and stability for OpenTelemetry clients","status":"Stable","source":"spec"},{"id":"ad0e1109c35f","level":"SHOULD","text":"If the server disconnects without returning a response, the client SHOULD retry and send the same request.","section":"docs/specification.md#all-other-responses","sectionTitle":"All Other Responses","status":"Unspecified","source":"proto"},{"id":"202bb85d5576","level":"SHOULD","text":"The client SHOULD implement an exponential backoff strategy between retries to avoid overwhelming the server.","section":"docs/specification.md#all-other-responses","sectionTitle":"All Other Responses","status":"Unspecified","source":"proto"},{"id":"6d61205822b4","level":"MUST","text":"If the processing of the request fails because the request contains data that cannot be decoded or is otherwise invalid and such failure is permanent, then the server MUST respond with `HTTP 400 Bad Request`.","section":"docs/specification.md#bad-data","sectionTitle":"Bad Data","status":"Unspecified","source":"proto"},{"id":"7765d355cf7a","level":"SHOULD","text":"The `Status.details` field in the response SHOULD contain a BadRequest that describes the bad data.","section":"docs/specification.md#bad-data","sectionTitle":"Bad Data","status":"Unspecified","source":"proto"},{"id":"9e6ad2680dcf","level":"MUST NOT","text":"The client MUST NOT retry the request when it receives `HTTP 400 Bad Request` response.","section":"docs/specification.md#bad-data","sectionTitle":"Bad Data","status":"Unspecified","source":"proto"},{"id":"cdd9713b08be","level":"MUST","text":"The client and the server MUST set \"Content-Type: application/x-protobuf\" request and response headers when sending binary Protobuf encoded payload.","section":"docs/specification.md#binary-protobuf-encoding","sectionTitle":"Binary Protobuf Encoding","status":"Unspecified","source":"proto"},{"id":"6e0e331ee033","level":"SHOULD NOT","text":"Given that, senders SHOULD NOT create empty envelopes (OTLP payloads that contain zero spans, zero metric points or zero log records), receivers MAY ignore empty envelopes, and implementations that receive and send (forward) OTLP payloads MAY drop empty envelopes.","section":"docs/specification.md#empty-telemetry-envelopes","sectionTitle":"Empty Telemetry Envelopes","status":"Unspecified","source":"proto"},{"id":"7755499adfce","level":"SHOULD","text":"Retryable errors indicate that telemetry data processing failed, and the client SHOULD record the error and may retry exporting the same data.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"0c9b4360692d","level":"MUST NOT","text":"Non-retryable errors indicate that telemetry data processing failed, and the client MUST NOT retry sending the same telemetry data.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"a81346e68fab","level":"MUST","text":"The client MUST drop the telemetry data.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"baa3b0a35b8c","level":"SHOULD","text":"The client SHOULD maintain a counter of such dropped data.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"763cae139fe3","level":"SHOULD","text":"The server SHOULD indicate retryable errors using code Unavailable and MAY supply additional details via status using RetryInfo.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"140d29bc9187","level":"MAY","text":"To indicate non-retryable errors, the server is recommended to use code InvalidArgument and MAY supply additional details via status using BadRequest.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"63d06ca19d75","level":"MAY","text":"The server MAY use other gRPC codes to indicate retryable and non-retryable errors if those other gRPC codes are more appropriate for a particular erroneous situation.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"7afd7ee777b5","level":"SHOULD","text":"The client SHOULD interpret gRPC status codes as retryable or non-retryable according to the following table:","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"2447b0a69514","level":"SHOULD","text":"When retrying, the client SHOULD implement an exponential backoff strategy.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"6f30428861eb","level":"SHOULD","text":"The client SHOULD interpret `RESOURCEEXHAUSTED` code as retryable only if the server signals that the recovery from resource exhaustion is possible.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"f1869b6ec015","level":"SHOULD","text":"If no such status is returned, then the `RESOURCEEXHAUSTED` code SHOULD be treated as non-retryable.","section":"docs/specification.md#failures","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"be866f093f6c","level":"MUST","text":"If the processing of the request fails, the server MUST respond with appropriate `HTTP 4xx` or `HTTP 5xx` status code.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"e23242488145","level":"MUST","text":"The response body for all `HTTP 4xx` and `HTTP 5xx` responses MUST be a Protobuf-encoded Status message that describes the problem.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"e456029cf216","level":"MAY","text":"This specification does not use `Status.code` field and the server MAY omit `Status.code` field.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"91fe1ccb971e","level":"MAY","text":"The clients are not expected to alter their behavior based on `Status.code` field but MAY record it for troubleshooting purposes.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"cc67547e44e2","level":"SHOULD","text":"The `Status.message` field SHOULD contain a developer-facing error message as defined in `Status` message schema.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"b7a1efe32391","level":"MAY","text":"The server MAY include `Status.details` field with additional details.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"6a20dbd9ed52","level":"SHOULD","text":"The server SHOULD use HTTP response status codes to indicate retryable and non-retryable errors for a particular erroneous situation.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"96eeeb033fb6","level":"SHOULD","text":"The client SHOULD honour HTTP response status codes as retryable or non-retryable.","section":"docs/specification.md#failures-1","sectionTitle":"Failures","status":"Unspecified","source":"proto"},{"id":"791dc6e21cb5","level":"SHOULD","text":"If the server receives an empty request (a request that does not carry any telemetry data) the server SHOULD respond with success.","section":"docs/specification.md#full-success","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"9033d2ac0525","level":"MUST","text":"On success, the server response MUST be a Export\\<signal>ServiceResponse message (`ExportTraceServiceResponse` for traces, `ExportMetricsServiceResponse` for metrics, `ExportLogsServiceResponse` for logs and `ExportProfilesServiceResponse` for profiles).","section":"docs/specification.md#full-success","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"0cbbf5b96819","level":"MUST","text":"The server MUST leave the `partial_success` field unset in case of a successful response.","section":"docs/specification.md#full-success","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"a44799bf997f","level":"SHOULD","text":"If the server receives an empty request (a request that does not carry any telemetry data) the server SHOULD respond with success.","section":"docs/specification.md#full-success-1","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"18eacb87c96b","level":"MUST","text":"On success, the server MUST respond with `HTTP 200 OK`.","section":"docs/specification.md#full-success-1","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"a4e99b335616","level":"MUST","text":"The response body MUST be a Protobuf-encoded Export\\<signal>ServiceResponse message (`ExportTraceServiceResponse` for traces, `ExportMetricsServiceResponse` for metrics, `ExportLogsServiceResponse` for logs and `ExportProfilesServiceResponse` for profiles).","section":"docs/specification.md#full-success-1","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"433f51dae46a","level":"MUST","text":"The server MUST leave the `partial_success` field unset in case of a successful response.","section":"docs/specification.md#full-success-1","sectionTitle":"Full Success","status":"Unspecified","source":"proto"},{"id":"b689c2004f2a","level":"MUST","text":"When possible, the interoperability MUST be ensured between all versions of OTLP that are not declared obsolete.","section":"docs/specification.md#future-versions-and-interoperability","sectionTitle":"Future Versions and Interoperability","status":"Unspecified","source":"proto"},{"id":"049729d35c4c","level":"SHOULD","text":"Such capabilities SHOULD be discovered by client and server implementations after establishing the underlying transport.","section":"docs/specification.md#future-versions-and-interoperability","sectionTitle":"Future Versions and Interoperability","status":"Unspecified","source":"proto"},{"id":"da56f1b4d7fb","level":"SHOULD","text":"The exact discovery mechanism SHOULD be described in future OTEPs, which define the new capabilities and typically can be implemented by making a discovery request/response message exchange from the client to server.","section":"docs/specification.md#future-versions-and-interoperability","sectionTitle":"Future Versions and Interoperability","status":"Unspecified","source":"proto"},{"id":"7f3586b02f67","level":"MUST","text":"The implementation which supports a new, optional capability MUST adjust its behavior to match the expectation of a peer that does not support a particular capability.","section":"docs/specification.md#future-versions-and-interoperability","sectionTitle":"Future Versions and Interoperability","status":"Unspecified","source":"proto"},{"id":"2b61da0e7a14","level":"MUST","text":"Values of enum fields MUST be encoded as integer values.","section":"docs/specification.md#json-protobuf-encoding","sectionTitle":"JSON Protobuf Encoding","status":"Unspecified","source":"proto"},{"id":"429a5360bcd0","level":"MUST NOT","text":"Unlike the standard Protobuf JSON Mapping, which allows values of enum fields to be encoded as either integer values or as enum name strings, only integer enum values are allowed in OTLP JSON Protobuf Encoding; the enum name strings MUST NOT be used.","section":"docs/specification.md#json-protobuf-encoding","sectionTitle":"JSON Protobuf Encoding","status":"Unspecified","source":"proto"},{"id":"a661cbf2482e","level":"MUST","text":"OTLP/JSON receivers MUST ignore message fields with unknown names and MUST unmarshal the message as if the unknown field was not present in the payload.","section":"docs/specification.md#json-protobuf-encoding","sectionTitle":"JSON Protobuf Encoding","status":"Unspecified","source":"proto"},{"id":"55875e9df46c","level":"MUST","text":"The client and the server MUST set \"Content-Type: application/json\" request and response headers when sending JSON Protobuf encoded payload.","section":"docs/specification.md#json-protobuf-encoding","sectionTitle":"JSON Protobuf Encoding","status":"Unspecified","source":"proto"},{"id":"72810c81af2c","level":"SHOULD","text":"In such a situation, the client SHOULD implement queuing, acknowledgment handling, and retrying logic per destination.","section":"docs/specification.md#multi-destination-exporting","sectionTitle":"Multi-Destination Exporting","status":"Unspecified","source":"proto"},{"id":"2eaa0dc42143","level":"SHOULD","text":"The queues SHOULD reference shared, immutable data to be sent, thus minimizing the memory overhead caused by having multiple queues.","section":"docs/specification.md#multi-destination-exporting","sectionTitle":"Multi-Destination Exporting","status":"Unspecified","source":"proto"},{"id":"60481ca80f63","level":"MAY","text":"After sending the request the client MAY wait until the response is received from the server.","section":"docs/specification.md#otlpgrpc-concurrent-requests","sectionTitle":"OTLP/gRPC Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"12bed09895a2","level":"SHOULD","text":"The implementations that need to achieve high throughput SHOULD support concurrent Unary calls to achieve higher throughput.","section":"docs/specification.md#otlpgrpc-concurrent-requests","sectionTitle":"OTLP/gRPC Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"74a330985c86","level":"SHOULD","text":"The client SHOULD send new requests without waiting for the response to the earlier sent requests, essentially creating a pipeline of requests that are currently in flight that are not acknowledged.","section":"docs/specification.md#otlpgrpc-concurrent-requests","sectionTitle":"OTLP/gRPC Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"aed0dd698a7d","level":"SHOULD","text":"The number of concurrent requests SHOULD be configurable.","section":"docs/specification.md#otlpgrpc-concurrent-requests","sectionTitle":"OTLP/gRPC Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"1bbf9a42480a","level":"SHOULD","text":"The client implementation SHOULD expose an option to turn on and off the waiting during a shutdown.","section":"docs/specification.md#otlpgrpc-concurrent-requests","sectionTitle":"OTLP/gRPC Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"7db7f9280c1a","level":"SHOULD","text":"If the client is unable to deliver a certain request (e.g. a timer expired while waiting for acknowledgements) the client SHOULD record the fact that the data was not delivered.","section":"docs/specification.md#otlpgrpc-concurrent-requests","sectionTitle":"OTLP/gRPC Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"798662a38010","level":"MUST","text":"The server MUST enforce a message size limit when receiving the request, including after decompression, to mitigate possible excessive memory usage caused by a misconfigured or malicious client sending an oversized request.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"0425f5ab89c7","level":"RECOMMENDED","text":"However, it is RECOMMENDED to use 64 MiB as the default limit.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"c4bba088ac27","level":"SHOULD","text":"Implementations SHOULD allow this limit to be configured.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"2cd0a1373a81","level":"MUST","text":"If the limit is exceeded, the gRPC server implementations MUST report a `RESOURCE_EXHAUSTED` code as a non-retryable error.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"da9594bb0e22","level":"SHOULD","text":"The client SHOULD limit the size of the request message, including before compression, to avoid overwhelming the server.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"88e7048eabd7","level":"RECOMMENDED","text":"It is RECOMMENDED to use 64 MiB as the default limit.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"1c28381e1736","level":"MUST NOT","text":"If the limit is exceeded, the client MUST NOT make the request and SHOULD record the fact that the request was discarded.","section":"docs/specification.md#otlpgrpc-request","sectionTitle":"OTLP/gRPC Request","status":"Unspecified","source":"proto"},{"id":"c4f36af1c56c","level":"MUST","text":"The response MUST be the appropriate message (see below for the specific message to use in the Full Success, Partial Success and Failure cases).","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"98622b1245dc","level":"MUST","text":"The client MUST enforce a message size limit when receiving the response, including after decompression, to mitigate possible excessive memory usage caused by a misconfigured or malicious server. gRPC client implementations typically enforce a default incoming message size limit of 4 MiB, which is acceptable to use.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"bb8a8566a41f","level":"SHOULD","text":"Implementations SHOULD allow this limit to be configured.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"a01e367c74f8","level":"MUST","text":"If the limit is exceeded, the client MUST treat the response as a non-retryable error.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"ee070ad7e477","level":"MUST","text":"The server MUST limit the size of the response message, including before compression, to avoid overwhelming the client.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"5637f912db43","level":"RECOMMENDED","text":"It is RECOMMENDED to use 4 MiB as the default limit.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"d6ff823139f1","level":"SHOULD","text":"For a Partial Success response that would otherwise exceed the limit, the server SHOULD reduce the response size without changing response semantics if it is possible and practical.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"2dad989018e4","level":"MAY","text":"To do so, the server MAY decrease the verbosity of optional diagnostic fields, such as `partialsuccess.errormessage`, or omit optional diagnostic fields.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"f166b109255d","level":"MUST","text":"If the response still cannot fit within the limit, the server MUST fail the request with the `RESOURCE_EXHAUSTED` code as a non-retryable error.","section":"docs/specification.md#otlpgrpc-response","sectionTitle":"OTLP/gRPC Response","status":"Unspecified","source":"proto"},{"id":"e7b30f800394","level":"SHOULD","text":"If the server is unable to keep up with the pace of data it receives from the client then it SHOULD signal that fact to the client.","section":"docs/specification.md#otlpgrpc-throttling","sectionTitle":"OTLP/gRPC Throttling","status":"Unspecified","source":"proto"},{"id":"040ce8b37414","level":"MUST","text":"The client MUST then throttle itself to avoid overwhelming the server.","section":"docs/specification.md#otlpgrpc-throttling","sectionTitle":"OTLP/gRPC Throttling","status":"Unspecified","source":"proto"},{"id":"e38dc19223a8","level":"SHOULD","text":"To signal backpressure when using gRPC transport, the server SHOULD return an error with code Unavailable and MAY supply additional details via status using RetryInfo.","section":"docs/specification.md#otlpgrpc-throttling","sectionTitle":"OTLP/gRPC Throttling","status":"Unspecified","source":"proto"},{"id":"c2ecf9007d1a","level":"SHOULD","text":"When the client receives this signal, it SHOULD follow the recommendations outlined in documentation for RetryInfo:","section":"docs/specification.md#otlpgrpc-throttling","sectionTitle":"OTLP/gRPC Throttling","status":"Unspecified","source":"proto"},{"id":"fa31d7251b22","level":"SHOULD","text":"The server SHOULD choose a `retrydelay` value that is big enough to give the server time to recover yet is not too big to cause the client to drop data while being throttled.","section":"docs/specification.md#otlpgrpc-throttling","sectionTitle":"OTLP/gRPC Throttling","status":"Unspecified","source":"proto"},{"id":"c2bae063819c","level":"MAY","text":"Implementations MAY use HTTP/1.1 or HTTP/2 transports.","section":"docs/specification.md#otlphttp","sectionTitle":"OTLP/HTTP","status":"Unspecified","source":"proto"},{"id":"8ee2d6697343","level":"SHOULD","text":"Implementations that use HTTP/2 transport SHOULD fallback to HTTP/1.1 transport if HTTP/2 connection cannot be established.","section":"docs/specification.md#otlphttp","sectionTitle":"OTLP/HTTP","status":"Unspecified","source":"proto"},{"id":"2fcaead72e55","level":"MAY","text":"To achieve higher total throughput, the client MAY send requests using several parallel HTTP connections.","section":"docs/specification.md#otlphttp-concurrent-requests","sectionTitle":"OTLP/HTTP Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"358002694a73","level":"SHOULD","text":"In that case, the maximum number of parallel connections SHOULD be configurable.","section":"docs/specification.md#otlphttp-concurrent-requests","sectionTitle":"OTLP/HTTP Concurrent Requests","status":"Unspecified","source":"proto"},{"id":"9847c5c2f1b1","level":"SHOULD","text":"If the client cannot connect to the server, the client SHOULD retry the connection using an exponential backoff strategy between retries.","section":"docs/specification.md#otlphttp-connection","sectionTitle":"OTLP/HTTP Connection","status":"Unspecified","source":"proto"},{"id":"0aa53f0aa0a2","level":"SHOULD","text":"The client SHOULD keep the connection alive between requests.","section":"docs/specification.md#otlphttp-connection","sectionTitle":"OTLP/HTTP Connection","status":"Unspecified","source":"proto"},{"id":"4a1597308830","level":"SHOULD","text":"Server implementations SHOULD accept OTLP/HTTP with binary-encoded Protobuf payload and OTLP/HTTP with JSON-encoded Protobuf payload requests on the same port and multiplex the requests to the corresponding payload decoder based on the \"Content-Type\" request header.","section":"docs/specification.md#otlphttp-connection","sectionTitle":"OTLP/HTTP Connection","status":"Unspecified","source":"proto"},{"id":"1f16201fc705","level":"MAY","text":"Server implementations MAY accept OTLP/gRPC and OTLP/HTTP requests on the same port and multiplex the connections to the corresponding transport handler based on the \"Content-Type\" request header.","section":"docs/specification.md#otlphttp-connection","sectionTitle":"OTLP/HTTP Connection","status":"Unspecified","source":"proto"},{"id":"c698026f0e13","level":"MUST","text":"The client MAY gzip the content and in that case MUST include \"Content-Encoding: gzip\" request header.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"3513454b952c","level":"MAY","text":"The client MAY include \"Accept-Encoding: gzip\" request header if it can receive gzip-encoded responses.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"057fa0542461","level":"MAY","text":"Non-default URL paths for requests MAY be configured on the client and server sides.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"a108bc1f192a","level":"MUST","text":"The server MUST limit the size of the request body when parsing it, including after decompression, to mitigate possible excessive memory usage caused by a misconfigured or malicious client sending an oversized request.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"d77519bece31","level":"RECOMMENDED","text":"It is RECOMMENDED to use 64 MiB as the default limit.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"5351485b02eb","level":"SHOULD","text":"Implementations SHOULD allow this limit to be configured.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"7325ab0a4bf0","level":"MUST","text":"If the limit is exceeded, the server MUST respond with `HTTP 413 Content Too Large`.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"47da22ad0d71","level":"SHOULD","text":"The client SHOULD limit the size of the request body, including before compression, to avoid overwhelming the server.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"fe6a814db33b","level":"MUST NOT","text":"If the limit is exceeded, the client MUST NOT make the request and SHOULD record the fact that the request was discarded.","section":"docs/specification.md#otlphttp-request","sectionTitle":"OTLP/HTTP Request","status":"Unspecified","source":"proto"},{"id":"022fe0d18fad","level":"MUST","text":"The response body MUST be the appropriate serialized Protobuf message (see below for the specific message to use in the Full Success, Partial Success and Failure cases).","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"3d822ca9e09d","level":"MUST","text":"The client MUST limit the size of the response body when parsing it, including after decompression, to mitigate possible excessive memory usage caused by a misconfigured or malicious server.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"2150708f187d","level":"RECOMMENDED","text":"It is RECOMMENDED to use 4 MiB as the default limit.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"ad2839b4b324","level":"SHOULD","text":"Implementations SHOULD allow this limit to be configured.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"40b67c74dd3f","level":"MUST","text":"If the limit is exceeded, the client MUST treat the response as a non-retryable error and SHOULD record the fact that the response was discarded.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"0a595dab1736","level":"MUST","text":"The server MUST limit the size of the response body, including before compression, to avoid overwhelming the client.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"48acd5652810","level":"SHOULD","text":"For a Partial Success response that would otherwise exceed the limit, the server SHOULD reduce the response size without changing response semantics if it is possible and practical.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"914103e59a9d","level":"MAY","text":"To do so, the server MAY decrease the verbosity of optional diagnostic fields, such as `partialsuccess.errormessage`, or omit optional diagnostic fields.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"d0ae447ed85e","level":"MUST","text":"If the response still cannot fit within the limit, the server MUST fail the request with `HTTP 500 Internal Server Error`.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"2e28a776b8e5","level":"MUST","text":"The server MUST set \"Content-Type: application/x-protobuf\" header if the response body is binary-encoded Protobuf payload.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"5b8dc0f2e00f","level":"MUST","text":"The server MUST set \"Content-Type: application/json\" if the response is JSON-encoded Protobuf payload.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"cd853668d1c6","level":"MUST","text":"The server MUST use the same \"Content-Type\" in the response as it received in the request.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"d310e8b42e1a","level":"MAY","text":"If the request header \"Accept-Encoding: gzip\" is present in the request the server MAY gzip-encode the response and set \"Content-Encoding: gzip\" response header.","section":"docs/specification.md#otlphttp-response","sectionTitle":"OTLP/HTTP Response","status":"Unspecified","source":"proto"},{"id":"46b087e62ba2","level":"SHOULD","text":"If the server receives more requests than the client is allowed or the server is overloaded, the server SHOULD respond with `HTTP 429 Too Many Requests` or `HTTP 503 Service Unavailable` and MAY include \"Retry-After\" header to indicate how long the client ought to wait before retrying.","section":"docs/specification.md#otlphttp-throttling","sectionTitle":"OTLP/HTTP Throttling","status":"Unspecified","source":"proto"},{"id":"b5f699b2a08c","level":"SHOULD","text":"The client SHOULD honour the value specified in the \"Retry-After\" header if it is present.","section":"docs/specification.md#otlphttp-throttling","sectionTitle":"OTLP/HTTP Throttling","status":"Unspecified","source":"proto"},{"id":"85d8d55a5e90","level":"SHOULD","text":"If the client receives a retryable error code (see table above) and the \"Retry-After\" header is not present in the response, then the client SHOULD implement an exponential backoff strategy between retries.","section":"docs/specification.md#otlphttp-throttling","sectionTitle":"OTLP/HTTP Throttling","status":"Unspecified","source":"proto"},{"id":"015ef8e6751e","level":"MUST","text":"If the request is only partially accepted (i.e. when the server accepts only parts of the data and rejects the rest), the server response MUST be the same Export\\<signal>ServiceResponse message as in the Full Success case.","section":"docs/specification.md#partial-success","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"744c4c80ee49","level":"MUST","text":"Additionally, the server MUST initialize the `partialsuccess` field (`ExportTracePartialSuccess` message for traces, `ExportMetricsPartialSuccess` message for metrics, `ExportLogsPartialSuccess` message for logs and `ExportProfilesPartialSuccess` for profiles), and it MUST set the respective `rejectedspans`, `rejecteddatapoints`, `rejectedlogrecords` or `rejected_profiles` field with the number of spans/data points/log records/profiles it rejected.","section":"docs/specification.md#partial-success","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"d2cc4c5c6e6f","level":"SHOULD","text":"The server SHOULD populate the `error_message` field with a human-readable error message in English.","section":"docs/specification.md#partial-success","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"ed0ecad66b62","level":"MAY","text":"Servers MAY also use the `partialsuccess` field to convey warnings/suggestions to clients even when the server fully accepts the request.","section":"docs/specification.md#partial-success","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"b2cf2a4ad2a2","level":"MUST","text":"In such cases, the `rejected<signal>` field MUST have a value of `0`, and the `error_message` field MUST be non-empty.","section":"docs/specification.md#partial-success","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"c65daba85b62","level":"MUST NOT","text":"The client MUST NOT retry the request when it receives a partial success response where the `partial_success` is populated.","section":"docs/specification.md#partial-success","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"d54b28aab1b0","level":"MUST","text":"If the request is only partially accepted (i.e. when the server accepts only parts of the data and rejects the rest), the server MUST respond with `HTTP 200 OK`.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"e2abd8f4a9e5","level":"MUST","text":"The response body MUST be the same Export\\<signal>ServiceResponse message as in the Full Success case.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"92d9a92fa00d","level":"MUST","text":"Additionally, the server MUST initialize the `partialsuccess` field (`ExportTracePartialSuccess` message for traces, `ExportMetricsPartialSuccess` message for metrics, `ExportLogsPartialSuccess` message for logs and `ExportProfilesPartialSuccess` for profiles), and it MUST set the respective `rejectedspans`, `rejecteddatapoints`, `rejectedlogrecords` or `rejected_profiles` field with the number of spans/data points/log records it rejected.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"f60387312310","level":"SHOULD","text":"The server SHOULD populate the `error_message` field with a human-readable error message in English.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"76a1eb6496f3","level":"MAY","text":"Servers MAY also use the `partialsuccess` field to convey warnings/suggestions to clients even when it fully accepts the request.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"4cdcb5c5ee7c","level":"MUST","text":"In such cases, the `rejected<signal>` field MUST have a value of `0`, and the `error_message` field MUST be non-empty.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"acec7880315c","level":"MUST NOT","text":"The client MUST NOT retry the request when it receives a partial success response where the `partial_success` is populated.","section":"docs/specification.md#partial-success-1","sectionTitle":"Partial Success","status":"Unspecified","source":"proto"},{"id":"4db2d864c27c","level":"MUST","text":"All server components MUST support the following transport compression options:","section":"docs/specification.md#protocol-details","sectionTitle":"Protocol Details","status":"Unspecified","source":"proto"},{"id":"136ecb0249bf","level":"SHOULD","text":"The requests that receive a response status code listed in following table SHOULD be retried.","section":"docs/specification.md#retryable-response-codes","sectionTitle":"Retryable Response Codes","status":"Unspecified","source":"proto"},{"id":"eba77fc8b2d8","level":"MUST NOT","text":"All other `4xx` or `5xx` response status codes MUST NOT be retried.","section":"docs/specification.md#retryable-response-codes","sectionTitle":"Retryable Response Codes","status":"Unspecified","source":"proto"},{"id":"206ca6d52b5c","level":"SHOULD","text":"Encoders SHOULD ensure `string` fields contain valid UTF-8.","section":"docs/specification.md#utf-8-string-handling","sectionTitle":"UTF-8 String Handling","status":"Unspecified","source":"proto"},{"id":"298bf54b957c","level":"SHOULD","text":"Decoders SHOULD be prepared to receive non-compliant strings from permissive runtimes and SHOULD replace invalid UTF-8 sequences (code units) with the Unicode replacement character (`U+FFFD`).","section":"docs/specification.md#utf-8-string-handling","sectionTitle":"UTF-8 String Handling","status":"Unspecified","source":"proto"},{"id":"a7f7c5da13ed","level":"MAY","text":"Intermediary nodes (such as the OpenTelemetry Collector) are not required to perform in-line UTF-8 validation on `string` fields and MAY pass them through without inspection.","section":"docs/specification.md#utf-8-string-handling","sectionTitle":"UTF-8 String Handling","status":"Unspecified","source":"proto"},{"id":"e97f1e02fe05","level":"MAY","text":"Intermediary components MAY provide optional, configurable validation or sanitization.","section":"docs/specification.md#utf-8-string-handling","sectionTitle":"UTF-8 String Handling","status":"Unspecified","source":"proto"}]}