From 8d31b225e311c3f63d43ee84af6b5f5ca7a3e803 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 7 Jan 2022 12:17:54 -0800 Subject: [PATCH 01/22] Add more sample code for exponential histogram boundaries; mention subnormal values --- specification/metrics/datamodel.md | 59 +++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index ea99ae2ba81..d19dd3217df 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -622,6 +622,21 @@ func GetExponent(value float64) int32 { } ``` +Implementations are permitted to round subnormal values up to the +smallest normal value, which may permit the use of a built-in function: + +```golang + +func GetExponent(value float64) int { + // Note: Frexp() rounds submnormal values to the smallest normal + // value and returns an exponent corresponding to fractions in the + // range [0.5, 1), whereas we want [1, 2), so subtract 1 from the + // exponent. + _, exp := math.Frexp(value) + return exp - 1 +} +``` + ##### Negative Scale: Extract and Shift the Exponent For negative scales, the index of a value equals the normalized @@ -633,19 +648,51 @@ correct rounding for the negative indices. This may be written as: return GetExponent(value) >> -scale ``` +The reverse mapping function is: + +```golang + return math.Ldexp(1, index << -scale) +``` + +Note that the reverse mapping function is expected to produce +subnormal values even when the mapping function rounds them into +normal values, since the lower boundary of the bucket containing the +smallest normal value may be subnormal. For example, at scale -4 the +smallest normal value `0x1p-1022` falls into a bucket with lower +boundary `0x1p-1024`. + ##### All Scales: Use the Logarithm Function -For any scale, use of the built-in natural logarithm -function. A multiplicative factor equal to `2**scale / ln(2)` -proves useful (where `ln()` is the natural logarithm), for example: +For any scale, use the built-in natural logarithm function. A +multiplicative factor equal to `2**scale / ln(2)` proves useful (where +`ln()` is the natural logarithm), for example: ```golang - scaleFactor := math.Log2E * math.Exp2(scale) - return int64(math.Floor(math.Log(value) * scaleFactor)) + scaleFactor := math.Ldexp(math.Log2E, scale) + return math.Floor(math.Log(value) * scaleFactor) ``` Note that in the example Golang code above, the built-in `math.Log2E` -is defined as `1 / ln(2)`. +is defined as the inverse natural logarithm of 2. + +The reverse mapping function is: + +```golang + inverseFactor := math.Ldexp(math.Ln2, -scale) + return math.Exp(index * inverseFactor), nil +``` + +Implementations should verify that their mapping function and inverse +mapping function are correct near the lowest and highest IEEE floating +point value. In the Golang reference implementation, for example, the +above formula computes `+Inf` instead of a correct, finite boundary. +In this case, it is appropriate to subtract `1< Date: Fri, 7 Jan 2022 12:18:39 -0800 Subject: [PATCH 02/22] Specify an optional exponential histogram Aggregation with two configuration settings --- specification/metrics/sdk.md | 59 +++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index e1e36dfdc46..593e4742e1b 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -327,6 +327,10 @@ The SDK MUST provide the following `Aggregation` to support the - [Histogram](./sdk.md#histogram-aggregation) - [Explicit Bucket Histogram](./sdk.md#explicit-bucket-histogram-aggregation) +The SDK MAY provide the following `Aggregation`: + +- [Exponential Histogram Aggregation](./sdk.md#exponential-histogram-aggregation) + #### Drop Aggregation The Drop Aggregation informs the SDK to ignore/drop all Instrument Measurements @@ -393,6 +397,19 @@ Aggregation](./sdk.md#explicit-bucket-histogram-aggregation). This Aggregation does not have any configuration parameters. +##### Histogram Aggregation common behavior + +Histogram aggregations should not fill out `sum` when used with +instruments that record negative measurements, e.g. `UpDownCounter` or +`ObservableGauge`. + +All histogram Aggregations inform the SDK to collect: + +- Count of `Measurement` values in population. +- Arithmetic sum of `Measurement` values in population. +- Min (optional) `Measurement` value in population. +- Max (optional) `Measurement` value in population. + #### Explicit Bucket Histogram Aggregation The Explicit Bucket Histogram Aggregation informs the SDK to collect data for @@ -406,15 +423,43 @@ This Aggregation honors the following configuration parameters: | Boundaries | double\[\] | [ 0, 5, 10, 25, 50, 75, 100, 250, 500, 1000 ] | Array of increasing values representing explicit bucket boundary values.

The Default Value represents the following buckets:
(-∞, 0], (0, 5.0], (5.0, 10.0], (10.0, 25.0], (25.0, 50.0], (50.0, 75.0], (75.0, 100.0], (100.0, 250.0], (250.0, 500.0], (500.0, 1000.0], (1000.0, +∞) | | RecordMinMax | true, false | true | Whether to record min and max. | -Note: This aggregation should not fill out `sum` when used with instruments that -record negative measurements, e.g. `UpDownCounter` or `ObservableGauge`. +Explicit buckets stated in terms of their upper boundary. Buckets are +exclusive of their lower boundary and inclusive of their upper bound +(except at positive infinity). A measurement is defined to fall into +the least-numbered bucket with boundary that is greater than or equal +to the measurement. -This Aggregation informs the SDK to collect: +#### Exponential Histogram Aggregation -- Count of `Measurement` values falling within explicit bucket boundaries. -- Arithmetic sum of `Measurement` values in population. -- Min (optional) `Measurement` value in population. -- Max (optional) `Measurement` value in population. +The Exponential Histogram Aggregation informs the SDK to collect data +for the [Exponential Histogram Metric +Point](./datamodel.md#exponentialhistogram), which uses an exponential +formula to determine bucket boundaries and an integer `scale` +parameter to control resolution. + +This Aggregation honors the following configuration parameters: + +| Key | Value | Default Value | Description | +| -- | -- | -- | -- | +| MaxSize | integer | 320 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | +| RangeLimits (optional) | min, max double | _see note_ | When set, limit the range of positive measurements to the inclusive range [min, max] and limit the range of negative measurements to [-max, -min]. Paired with maximum size, this determines a fixed exponential scale during the constructor. | + +##### Exponential Histogram Aggregation: Handle all normal values + +When RangeLimits are not set, implementations are REQUIRED to handle +the entire normal range of IEEE floating point values (i.e., all +values except for +Inf, -Inf and NaN values). Implementations are +permitted to round subnormal values away from zero to the nearest +normal value where it simplifies the implementation. + +##### Exponential Histogram Aggregation: Maintain the ideal scale + +Implementations SHOULD adjust the histogram scale as necessary to +maintain the best resolution possible, given the maximum size. This +results in histogram Aggregations where at least one of the positive +or negative ranges of buckets is more than half full, such that +increasing scale by one would not be possible given the size +constraint. ## Attribute limits From aefaed5d8d8e4aa35c2a6ab4daab12aa4d58661a Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 7 Jan 2022 12:19:31 -0800 Subject: [PATCH 03/22] changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f8230c7184..af26c31786f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ release. ([#2210](https://github.com/open-telemetry/opentelemetry-specification/pull/2210)) - Use UCUM units in Metrics Semantic Conventions. ([#2199](https://github.com/open-telemetry/opentelemetry-specification/pull/2199)) +- Specify optional support for an Exponential Histogram Aggregation. + ([#X](https://github.com/open-telemetry/opentelemetry-specification/pull/X)) ### Logs From 698c2e887c2a22f8426656af933b61f87661ffce Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 7 Jan 2022 12:31:23 -0800 Subject: [PATCH 04/22] update PR number --- CHANGELOG.md | 2 +- specification/metrics/sdk.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af26c31786f..6c6056bf38d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ release. - Use UCUM units in Metrics Semantic Conventions. ([#2199](https://github.com/open-telemetry/opentelemetry-specification/pull/2199)) - Specify optional support for an Exponential Histogram Aggregation. - ([#X](https://github.com/open-telemetry/opentelemetry-specification/pull/X)) + ([#2252](https://github.com/open-telemetry/opentelemetry-specification/pull/2252)) ### Logs diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 593e4742e1b..d2c658e4f52 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -442,7 +442,7 @@ This Aggregation honors the following configuration parameters: | Key | Value | Default Value | Description | | -- | -- | -- | -- | | MaxSize | integer | 320 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | -| RangeLimits (optional) | min, max double | _see note_ | When set, limit the range of positive measurements to the inclusive range [min, max] and limit the range of negative measurements to [-max, -min]. Paired with maximum size, this determines a fixed exponential scale during the constructor. | +| RangeLimits (optional) | min, max double | _not set_ | When set, limit the range of positive measurements to the inclusive range [min, max] and limit the range of negative measurements to [-max, -min]. Paired with maximum size, this determines a fixed exponential scale during the constructor. | ##### Exponential Histogram Aggregation: Handle all normal values From 27af2a7a108063dc914747e52e432952859bf01c Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 7 Jan 2022 12:35:10 -0800 Subject: [PATCH 05/22] Lint --- specification/metrics/sdk.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index d2c658e4f52..6301b7a51ab 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -18,7 +18,11 @@ + [Sum Aggregation](#sum-aggregation) + [Last Value Aggregation](#last-value-aggregation) + [Histogram Aggregation](#histogram-aggregation) + - [Histogram Aggregation common behavior](#histogram-aggregation-common-behavior) + [Explicit Bucket Histogram Aggregation](#explicit-bucket-histogram-aggregation) + + [Exponential Histogram Aggregation](#exponential-histogram-aggregation) + - [Exponential Histogram Aggregation: Handle all normal values](#exponential-histogram-aggregation-handle-all-normal-values) + - [Exponential Histogram Aggregation: Maintain the ideal scale](#exponential-histogram-aggregation-maintain-the-ideal-scale) - [Attribute limits](#attribute-limits) - [Exemplar](#exemplar) * [ExemplarFilter](#exemplarfilter) From f8ae27d36da237636e3caaedd1dc195615f91a5b Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 7 Jan 2022 15:11:44 -0800 Subject: [PATCH 06/22] clarify & note --- specification/metrics/datamodel.md | 18 ++++++++++++------ specification/metrics/sdk.md | 12 ++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index d19dd3217df..562c552267f 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -663,9 +663,10 @@ boundary `0x1p-1024`. ##### All Scales: Use the Logarithm Function -For any scale, use the built-in natural logarithm function. A -multiplicative factor equal to `2**scale / ln(2)` proves useful (where -`ln()` is the natural logarithm), for example: +For any scale, the built-in natural logarithm function can be used to +compute the bucket index. A multiplicative factor equal to `2**scale +/ ln(2)` proves useful (where `ln()` is the natural logarithm), for +example: ```golang scaleFactor := math.Ldexp(math.Log2E, scale) @@ -685,15 +686,20 @@ The reverse mapping function is: Implementations should verify that their mapping function and inverse mapping function are correct near the lowest and highest IEEE floating point value. In the Golang reference implementation, for example, the -above formula computes `+Inf` instead of a correct, finite boundary. -In this case, it is appropriate to subtract `1<
The Default Value represents the following buckets:
(-∞, 0], (0, 5.0], (5.0, 10.0], (10.0, 25.0], (25.0, 50.0], (50.0, 75.0], (75.0, 100.0], (100.0, 250.0], (250.0, 500.0], (500.0, 1000.0], (1000.0, +∞) | | RecordMinMax | true, false | true | Whether to record min and max. | -Explicit buckets stated in terms of their upper boundary. Buckets are -exclusive of their lower boundary and inclusive of their upper bound -(except at positive infinity). A measurement is defined to fall into -the least-numbered bucket with boundary that is greater than or equal -to the measurement. +Explicit buckets are stated in terms of their upper boundary. Buckets +are exclusive of their lower boundary and inclusive of their upper +bound (except at positive infinity). A measurement is defined to fall +into the least-numbered bucket with boundary that is greater than or +equal to the measurement. #### Exponential Histogram Aggregation @@ -446,7 +446,7 @@ This Aggregation honors the following configuration parameters: | Key | Value | Default Value | Description | | -- | -- | -- | -- | | MaxSize | integer | 320 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | -| RangeLimits (optional) | min, max double | _not set_ | When set, limit the range of positive measurements to the inclusive range [min, max] and limit the range of negative measurements to [-max, -min]. Paired with maximum size, this determines a fixed exponential scale during the constructor. | +| RangeLimits (optional) | min, max double | _not set_ | When set, limit the range of positive measurements to the inclusive range [min, max] and limit the range of negative measurements to [-max, -min]. Paired with maximum size, this determines a fixed exponential scale during the constructor. | ##### Exponential Histogram Aggregation: Handle all normal values From 639d565f745e2a30726ffeadb2fae6820bef9e55 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 7 Jan 2022 15:19:22 -0800 Subject: [PATCH 07/22] markdownlint --- specification/metrics/datamodel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index 562c552267f..28690c3dd14 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -692,7 +692,7 @@ multiply the result by `2`. ```golang // Use this form in case the equation above computes +Inf - // as the lower boundary of a valid bucket. + // as the lower boundary of a valid bucket. inverseFactor := math.Ldexp(math.Ln2, -scale) return 2.0 * math.Exp((index - (1 << scale)) * inverseFactor), nil ``` From 8ed6d9449b39330a3ec656803c8be986fa36f425 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Mon, 24 Jan 2022 23:16:31 -0800 Subject: [PATCH 08/22] revisions from code review --- specification/metrics/sdk.md | 74 +++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index efea00d89f4..127e09dad2f 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -21,8 +21,10 @@ - [Histogram Aggregation common behavior](#histogram-aggregation-common-behavior) + [Explicit Bucket Histogram Aggregation](#explicit-bucket-histogram-aggregation) + [Exponential Histogram Aggregation](#exponential-histogram-aggregation) + - [Exponential Histogram Aggregation: Handle range limits](#exponential-histogram-aggregation-handle-range-limits) - [Exponential Histogram Aggregation: Handle all normal values](#exponential-histogram-aggregation-handle-all-normal-values) - - [Exponential Histogram Aggregation: Maintain the ideal scale](#exponential-histogram-aggregation-maintain-the-ideal-scale) + - [Exponential Histogram Aggregation: Maintain the ideal scale when values are not limited in both directions](#exponential-histogram-aggregation-maintain-the-ideal-scale-when-values-are-not-limited-in-both-directions) + - [Exponential Histogram Aggregation: Maintain fixed scale when values are limited in both directions](#exponential-histogram-aggregation-maintain-fixed-scale-when-values-are-limited-in-both-directions) - [Attribute limits](#attribute-limits) - [Exemplar](#exemplar) * [ExemplarFilter](#exemplarfilter) @@ -443,28 +445,72 @@ parameter to control resolution. This Aggregation honors the following configuration parameters: -| Key | Value | Default Value | Description | -| -- | -- | -- | -- | -| MaxSize | integer | 320 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | -| RangeLimits (optional) | min, max double | _not set_ | When set, limit the range of positive measurements to the inclusive range [min, max] and limit the range of negative measurements to [-max, -min]. Paired with maximum size, this determines a fixed exponential scale during the constructor. | +| Key | Value | Default Value | Description | +|---------------------|---------|---------------|--------------------------------------------------------------------------------------------------------------| +| MaxSize | integer | 160 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | +| MinValue (optional) | double | _not set_ | When set, limit the absolute value of measurements to be greater than or equal to this minimum value | +| MaxValue (optional) | double | _not set_ | When set, limit the absolute value of measurements to be less than or equal to this maximum value | + +The default of 160 buckets is selected to establish default support +for a high-resolution histogram able to cover a long-tail latency +distribution from 1ms to 100s with less than 5% relative error. +Because 160 can be factored into `10 * 2**K`, maximum contrast is +relatively simple to derive for scale `K`: + +| Scale | Maximum data contrast at 10 * 2**K buckets | +|-------|--------------------------------------------| +| K+2 | 5.657 (2**(10/4)) | +| K+1 | 32 (2**(10/2)) | +| K | 1024 (2**10) | +| K-1 | 1048576 (2**20) | + +The following table shows how the ideal scale for 160 buckets is +calculated as a function of the input range: + +| Input range | Contrast | Ideal Scale | Base | Relative error | +|-------------|----------|-------------|----------|----------------| +| 1ms - 4ms | 4 | 6 | 1.010889 | 0.542% | +| 1ms - 20ms | 20 | 5 | 1.021897 | 1.083% | +| 1ms - 1s | 10**3 | 4 | 1.044274 | 2.166% | +| 1ms - 100s | 10**5 | 3 | 1.090508 | 4.329% | +| 1μs - 10s | 10**7 | 2 | 1.189207 | 8.643% | + +Note that relative error is calculated as the half of the bucket width +divided by the bucket midpoint, which is the same in every bucket. +Using the bucket from [1, base), we have `(bucketWidth / 2) / +bucketMidpoint = ((base - 1) / 2) / ((base + 1) / 2) = (base - 1) / +(base + 1)`. + +##### Exponential Histogram Aggregation: Handle range limits + +When either the MinValue or MaxValue range limit is configured, the +implementation is REQUIRED to reject out-of-range measurements and +signal an error to the user. ##### Exponential Histogram Aggregation: Handle all normal values -When RangeLimits are not set, implementations are REQUIRED to handle -the entire normal range of IEEE floating point values (i.e., all -values except for +Inf, -Inf and NaN values). Implementations are -permitted to round subnormal values away from zero to the nearest -normal value where it simplifies the implementation. +Range limits aside, 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). -##### Exponential Histogram Aggregation: Maintain the ideal scale +Implementations are permitted to round subnormal values away from zero +to the nearest normal value when it simplifies the implementation. + +##### Exponential Histogram Aggregation: Maintain the ideal scale when values are not limited in both directions Implementations SHOULD adjust the histogram scale as necessary to -maintain the best resolution possible, given the maximum size. This -results in histogram Aggregations where at least one of the positive -or negative ranges of buckets is more than half full, such that +maintain the best resolution possible, given the maximum size, unless +both MinValue and MaxValue range limits are set. This results in +histogram Aggregations where at least one of the positive or negative +ranges of buckets is more than half the maximum size, such that increasing scale by one would not be possible given the size constraint. +##### Exponential Histogram Aggregation: Maintain fixed scale when values are limited in both directions + +Implementations SHOULD fix the histogram scale to the ideal scale of +the configured MinValue and MaxValue when both limits are set. + ## Attribute limits Attributes which belong to Metrics are exempt from the From 590d483b87c0343482e5df0f758207c0f564eb58 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Tue, 1 Feb 2022 14:33:29 -0800 Subject: [PATCH 09/22] remove range limits; separate normative text a bit more --- specification/metrics/sdk.md | 55 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 127e09dad2f..cef553167a0 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -21,10 +21,10 @@ - [Histogram Aggregation common behavior](#histogram-aggregation-common-behavior) + [Explicit Bucket Histogram Aggregation](#explicit-bucket-histogram-aggregation) + [Exponential Histogram Aggregation](#exponential-histogram-aggregation) - - [Exponential Histogram Aggregation: Handle range limits](#exponential-histogram-aggregation-handle-range-limits) - [Exponential Histogram Aggregation: Handle all normal values](#exponential-histogram-aggregation-handle-all-normal-values) - - [Exponential Histogram Aggregation: Maintain the ideal scale when values are not limited in both directions](#exponential-histogram-aggregation-maintain-the-ideal-scale-when-values-are-not-limited-in-both-directions) - - [Exponential Histogram Aggregation: Maintain fixed scale when values are limited in both directions](#exponential-histogram-aggregation-maintain-fixed-scale-when-values-are-limited-in-both-directions) + - [Exponential Histogram Aggregation: Support a minimum and maximum scale](#exponential-histogram-aggregation-support-a-minimum-and-maximum-scale) + - [Exponential Histogram Aggregation: Use the maximum scale for single measurements](#exponential-histogram-aggregation-use-the-maximum-scale-for-single-measurements) + - [Exponential Histogram Aggregation: Maintain the ideal scale](#exponential-histogram-aggregation-maintain-the-ideal-scale) - [Attribute limits](#attribute-limits) - [Exemplar](#exemplar) * [ExemplarFilter](#exemplarfilter) @@ -443,13 +443,13 @@ Point](./datamodel.md#exponentialhistogram), which uses an exponential formula to determine bucket boundaries and an integer `scale` parameter to control resolution. -This Aggregation honors the following configuration parameters: +Scale is not a configurable property of this Aggregation, the +implementation will adjust it as necessary given the data. This +Aggregation honors the following configuration parameter: -| Key | Value | Default Value | Description | -|---------------------|---------|---------------|--------------------------------------------------------------------------------------------------------------| -| MaxSize | integer | 160 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | -| MinValue (optional) | double | _not set_ | When set, limit the absolute value of measurements to be greater than or equal to this minimum value | -| MaxValue (optional) | double | _not set_ | When set, limit the absolute value of measurements to be less than or equal to this maximum value | +| Key | Value | Default Value | Description | +|---------|---------|---------------|--------------------------------------------------------------------------------------------------------------| +| MaxSize | integer | 160 | Maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. | The default of 160 buckets is selected to establish default support for a high-resolution histogram able to cover a long-tail latency @@ -481,35 +481,36 @@ Using the bucket from [1, base), we have `(bucketWidth / 2) / bucketMidpoint = ((base - 1) / 2) / ((base + 1) / 2) = (base - 1) / (base + 1)`. -##### Exponential Histogram Aggregation: Handle range limits +This Aggregation uses the notion of "ideal" scale. The ideal scale is +either: -When either the MinValue or MaxValue range limit is configured, the -implementation is REQUIRED to reject out-of-range measurements and -signal an error to the user. +1. The maximum supported scale, generally used for single-value histogram Aggregations where scale is not otherwise constrained +2. The largest value of scale such that no more than the maximum number of buckets are needed to represent the full range of input data in either of the positive or negative ranges. ##### Exponential Histogram Aggregation: Handle all normal values -Range limits aside, 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). +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). Implementations are permitted to round subnormal values away from zero to the nearest normal value when it simplifies the implementation. -##### Exponential Histogram Aggregation: Maintain the ideal scale when values are not limited in both directions +##### Exponential Histogram Aggregation: Support a minimum and maximum scale -Implementations SHOULD adjust the histogram scale as necessary to -maintain the best resolution possible, given the maximum size, unless -both MinValue and MaxValue range limits are set. This results in -histogram Aggregations where at least one of the positive or negative -ranges of buckets is more than half the maximum size, such that -increasing scale by one would not be possible given the size -constraint. +The implementation MUST maintain reasonable minimum and maximum scale +parameters, values that the automatic scale parameter will not exceed. + +##### Exponential Histogram Aggregation: Use the maximum scale for single measurements -##### Exponential Histogram Aggregation: Maintain fixed scale when values are limited in both directions +When the histogram contains not more than one value in either of the +positive or negative ranges, the implementation SHOULD use the maximum +scale. -Implementations SHOULD fix the histogram scale to the ideal scale of -the configured MinValue and MaxValue when both limits are set. +##### Exponential Histogram Aggregation: Maintain the ideal scale + +Implementations SHOULD adjust the histogram scale as necessary to +maintain the best-possible resolution at the configured maximum size. ## Attribute limits From a6535294aa7be1cb9486a92b51d6069cf8c836fe Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Tue, 1 Feb 2022 14:43:32 -0800 Subject: [PATCH 10/22] missing add --- specification/metrics/sdk.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index f814c6f5366..e99fdbdb9c2 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -513,15 +513,6 @@ scale. Implementations SHOULD adjust the histogram scale as necessary to maintain the best-possible resolution at the configured maximum size. -This Aggregation informs the SDK to collect: - -- Count of `Measurement` values falling within explicit bucket boundaries. -- Arithmetic sum of `Measurement` values in population. This SHOULD NOT be collected when used with -instruments that record negative measurements, e.g. `UpDownCounter` or `ObservableGauge`. -- Min (optional) `Measurement` value in population. -- Max (optional) `Measurement` value in population. ->>>>>>> b024a66950ccd2e5aaf84faeaa14206959cf8a93 - ## Attribute limits Attributes which belong to Metrics are exempt from the From 854c9a9462e5dcbd59b24923031529193c483c98 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Mon, 28 Feb 2022 14:45:32 -0800 Subject: [PATCH 11/22] lint --- CHANGELOG.md | 4 ++-- specification/metrics/sdk.md | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ee12ef7bd6..15ea65f1cea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ release. duplicate conflicts in the data model, specify how the SDK is meant to report and assist the user when these conflicts arise. ([#2317](https://github.com/open-telemetry/opentelemetry-specification/pull/2317)). +- Specify optional support for an Exponential Histogram Aggregation. + ([#2252](https://github.com/open-telemetry/opentelemetry-specification/pull/2252)) ### Logs @@ -94,8 +96,6 @@ release. ([#2282](https://github.com/open-telemetry/opentelemetry-specification/pull/2282)) - Clarified wildcard and predicate support in metrics SDK View API. ([#2325](https://github.com/open-telemetry/opentelemetry-specification/pull/2325)) -- Specify optional support for an Exponential Histogram Aggregation. - ([#2252](https://github.com/open-telemetry/opentelemetry-specification/pull/2252)) ### Logs diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 8c0804a0b81..aeafbee688a 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -20,6 +20,13 @@ + [Histogram Aggregation](#histogram-aggregation) - [Histogram Aggregation common behavior](#histogram-aggregation-common-behavior) + [Explicit Bucket Histogram Aggregation](#explicit-bucket-histogram-aggregation) + + [Exponential Histogram Aggregation](#exponential-histogram-aggregation) + - [Exponential Histogram Aggregation: Handle all normal values](#exponential-histogram-aggregation-handle-all-normal-values) + - [Exponential Histogram Aggregation: Support a minimum and maximum scale](#exponential-histogram-aggregation-support-a-minimum-and-maximum-scale) + - [Exponential Histogram Aggregation: Use the maximum scale for single measurements](#exponential-histogram-aggregation-use-the-maximum-scale-for-single-measurements) + - [Exponential Histogram Aggregation: Maintain the ideal scale](#exponential-histogram-aggregation-maintain-the-ideal-scale) + * [Observations inside asynchronous callbacks](#observations-inside-asynchronous-callbacks) + * [Resolving duplicate instrument registration conflicts](#resolving-duplicate-instrument-registration-conflicts) - [Attribute limits](#attribute-limits) - [Exemplar](#exemplar) * [ExemplarFilter](#exemplarfilter) From ef363b5ce0caf43c90aa60c6751317a07c229e2a Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Mon, 28 Feb 2022 14:53:51 -0800 Subject: [PATCH 12/22] lintier --- specification/metrics/datamodel.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index e01009887f5..220afad106c 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -787,8 +787,8 @@ multiply the result by `2`. return 2.0 * math.Exp((index - (1 << scale)) * inverseFactor), nil ``` -_Note that floating-point to integer type conversions have been -omitted from the code fragments above, to improve readability._ +*Note that floating-point to integer type conversions have been +omitted from the code fragments above, to improve readability.* ##### Positive Scale: Use a Lookup Table From 499831b5478aedf99252df260bea162963bccb35 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 1 Apr 2022 12:46:24 -0700 Subject: [PATCH 13/22] edits --- specification/metrics/datamodel.md | 12 ++++++------ specification/metrics/sdk.md | 10 +++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index be2fa21dfe9..a37e137409e 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -777,12 +777,12 @@ The reverse mapping function is: return math.Exp(index * inverseFactor), nil ``` -Implementations should verify that their mapping function and inverse -mapping function are correct near the lowest and highest IEEE floating -point value. In the Golang reference implementation, for example, the -above formula computes `+Inf` for the maximum-index bucket. In this -case, it is appropriate to subtract `1< Date: Fri, 1 Apr 2022 13:03:41 -0700 Subject: [PATCH 14/22] lint --- specification/metrics/datamodel.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index a37e137409e..1f5fd2e70c6 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -777,9 +777,9 @@ The reverse mapping function is: return math.Exp(index * inverseFactor), nil ``` -Implementations are expected to verify that their mapping function and -inverse mapping function are correct near the lowest and highest IEEE -floating point values. In the Golang reference implementation, for +Implementations are expected to verify that their mapping function and +inverse mapping function are correct near the lowest and highest IEEE +floating point values. In the Golang reference implementation, for example, the above formula computes `+Inf` for the maximum-index bucket. In this case, it is appropriate to subtract `1< Date: Mon, 4 Apr 2022 10:31:04 -0700 Subject: [PATCH 15/22] use MAY --- specification/metrics/sdk.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 246c27acd86..95c050e289f 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -499,8 +499,8 @@ 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). -Implementations are permitted to round subnormal values away from zero -to the nearest normal value when it simplifies the implementation. +Implementations MAY round subnormal values away from zero to the +nearest normal value. ##### Exponential Histogram Aggregation: Support a minimum and maximum scale From 34f616620d2127d84a688c0bc3fec5a1d9e5b474 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Wed, 20 Apr 2022 22:40:21 -0700 Subject: [PATCH 16/22] Apply suggestions from code review Co-authored-by: Aaron Abbott --- specification/metrics/sdk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index f645cbb3fc5..8e5ec890bc6 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -485,7 +485,7 @@ calculated as a function of the input range: | 1ms - 100s | 10**5 | 3 | 1.090508 | 4.329% | | 1μs - 10s | 10**7 | 2 | 1.189207 | 8.643% | -Note that relative error is calculated as the half of the bucket width +Note that relative error is calculated as half of the bucket width divided by the bucket midpoint, which is the same in every bucket. Using the bucket from [1, base), we have `(bucketWidth / 2) / bucketMidpoint = ((base - 1) / 2) / ((base + 1) / 2) = (base - 1) / From 559a6cba9e9e37b01b02841a870a71cc485f5168 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Wed, 20 Apr 2022 22:52:27 -0700 Subject: [PATCH 17/22] lint --- specification/metrics/datamodel.md | 2 +- specification/metrics/sdk.md | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index 0bc611902ab..fb84a06b0c4 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -768,7 +768,7 @@ example: ``` Note that in the example Golang code above, the built-in `math.Log2E` -is defined as the inverse natural logarithm of 2. +is defined as the inverse of the natural logarithm of 2, i.e., `1 / ln(2)`. The reverse mapping function is: diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index f645cbb3fc5..2540a9a4dae 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -17,7 +17,6 @@ + [Default Aggregation](#default-aggregation) + [Sum Aggregation](#sum-aggregation) + [Last Value Aggregation](#last-value-aggregation) - + [Histogram Aggregation](#histogram-aggregation) - [Histogram Aggregation common behavior](#histogram-aggregation-common-behavior) + [Explicit Bucket Histogram Aggregation](#explicit-bucket-histogram-aggregation) + [Exponential Histogram Aggregation](#exponential-histogram-aggregation) @@ -408,14 +407,6 @@ This Aggregation informs the SDK to collect: - The last `Measurement`. - The timestamp of the last `Measurement`. -#### Histogram Aggregation - -The Histogram Aggregation informs the SDK to select the best Histogram -Aggregation available. i.e. [Explicit Bucket Histogram -Aggregation](./sdk.md#explicit-bucket-histogram-aggregation). - -This Aggregation does not have any configuration parameters. - ##### Histogram Aggregation common behavior All histogram Aggregations inform the SDK to collect: @@ -520,7 +511,11 @@ scale. ##### Exponential Histogram Aggregation: Maintain the ideal scale Implementations SHOULD adjust the histogram scale as necessary to -maintain the ideal resolution at the configured maximum size. +maintain the best resolution possible, within the constraint of +maximum size (max number of buckets). Best resolution (highest scale) +is achieved when the number of positive or negative range buckets +exceeds half the maximum size, such that increasing scale by one would +not be possible given the size constraint. ### Observations inside asynchronous callbacks From a89aba999b0909d55df369550728c3354baa8b1c Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Wed, 20 Apr 2022 22:53:16 -0700 Subject: [PATCH 18/22] Update specification/metrics/sdk.md Co-authored-by: Aaron Abbott --- specification/metrics/sdk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index 8b1604fff57..cff6bfab193 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -500,7 +500,7 @@ nearest normal value. ##### Exponential Histogram Aggregation: Support a minimum and maximum scale The implementation MUST maintain reasonable minimum and maximum scale -parameters, values that the automatic scale parameter will not exceed. +parameters that the automatic scale parameter will not exceed. ##### Exponential Histogram Aggregation: Use the maximum scale for single measurements From be7d875eaceb0ae42410fdd9258a01f839e201d1 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Wed, 20 Apr 2022 23:08:02 -0700 Subject: [PATCH 19/22] yzhuge suggestion --- specification/metrics/datamodel.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index fb84a06b0c4..0e659063038 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -779,10 +779,12 @@ The reverse mapping function is: Implementations are expected to verify that their mapping function and inverse mapping function are correct near the lowest and highest IEEE -floating point values. In the Golang reference implementation, for -example, the above formula computes `+Inf` for the maximum-index bucket. -In this case, it is appropriate to subtract `1< Date: Fri, 29 Apr 2022 08:27:50 -0700 Subject: [PATCH 20/22] note on inclusivity --- specification/metrics/datamodel.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/specification/metrics/datamodel.md b/specification/metrics/datamodel.md index 0e659063038..db664490783 100644 --- a/specification/metrics/datamodel.md +++ b/specification/metrics/datamodel.md @@ -22,6 +22,7 @@ * [Sums](#sums) * [Gauge](#gauge) * [Histogram](#histogram) + + [Histogram: Bucket inclusivity](#histogram-bucket-inclusivity) * [ExponentialHistogram](#exponentialhistogram) + [Exponential Scale](#exponential-scale) + [Exponential Buckets](#exponential-buckets) @@ -33,6 +34,7 @@ - [Positive Scale: Use a Lookup Table](#positive-scale-use-a-lookup-table) + [ExponentialHistogram: Producer Recommendations](#exponentialhistogram-producer-recommendations) + [ExponentialHistogram: Consumer Recommendations](#exponentialhistogram-consumer-recommendations) + + [ExponentialHistogram: Bucket inclusivity](#exponentialhistogram-bucket-inclusivity) * [Summary (Legacy)](#summary-legacy) - [Exemplars](#exemplars) - [Single-Writer](#single-writer) @@ -522,6 +524,8 @@ Bucket counts are optional. A Histogram without buckets conveys a population in terms of only the sum and count, and may be interpreted as a histogram with single bucket covering `(-Inf, +Inf)`. +#### Histogram: Bucket inclusivity + Bucket upper-bounds are inclusive (except for the case where the upper-bound is +Inf) while bucket lower-bounds are exclusive. That is, buckets express the number of values that are greater than their lower @@ -836,6 +840,12 @@ bucket indices that overflow or underflow this representation. Consumers that reject such data SHOULD warn the user through error logging that out-of-range data was received. +#### ExponentialHistogram: Bucket inclusivity + +The [specification on bucket inclusivity made for explicit-boundary +Histogram data](#histogram-bucket-inclusivity) applies equally to +ExponentialHistogram data. + ### Summary (Legacy) [Summary](https://github.com/open-telemetry/opentelemetry-proto/blob/v0.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L268) From 1a473d0b4201b9cd8c2ac500f2c91c68d3f234bc Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Fri, 29 Apr 2022 08:31:02 -0700 Subject: [PATCH 21/22] require consistency; do not histogram non-normal values --- specification/metrics/sdk.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/specification/metrics/sdk.md b/specification/metrics/sdk.md index cff6bfab193..a717429fd06 100644 --- a/specification/metrics/sdk.md +++ b/specification/metrics/sdk.md @@ -494,6 +494,10 @@ 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). +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. + Implementations MAY round subnormal values away from zero to the nearest normal value. From 6d2edef7525653678d466401950e987c4e8a8303 Mon Sep 17 00:00:00 2001 From: Joshua MacDonald Date: Tue, 10 May 2022 08:21:46 -0700 Subject: [PATCH 22/22] Changelog. --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 534fd39ff6f..cd90f664ef8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,6 @@ release. ### Metrics -- Specify optional support for an Exponential Histogram Aggregation. - ([#2252](https://github.com/open-telemetry/opentelemetry-specification/pull/2252)) - Clarify that API support for multi-instrument callbacks is permitted. ([#2263](https://github.com/open-telemetry/opentelemetry-specification/pull/2263)). - Clarify SDK behavior when view conflicts are present @@ -23,8 +21,9 @@ release. ([#2495](https://github.com/open-telemetry/opentelemetry-specification/pull/2495)). - Add database connection pool metrics semantic conventions ([#2273](https://github.com/open-telemetry/opentelemetry-specification/pull/2273)). +- Specify optional support for an Exponential Histogram Aggregation. + ([#2252](https://github.com/open-telemetry/opentelemetry-specification/pull/2252)) ->>>>>>> ef5dc5f4d1d187ae44d1e2a1c3938e074d17bfdc ### Logs ### Resource