Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 14ca9f4

Browse files
authored
Select histogram aggregation with environment variables (open-telemetry#3265)
1 parent 98c23c8 commit 14ca9f4

File tree

8 files changed

+242
-136
lines changed

8 files changed

+242
-136
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- Select histogram aggregation with an environment variable
11+
([#3265](https://github.com/open-telemetry/opentelemetry-python/pull/3265))
1012
- Move Protobuf encoding to its own package
1113
([#3169](https://github.com/open-telemetry/opentelemetry-python/pull/3169))
1214
- Add experimental feature to detect resource detectors in auto instrumentation

exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/metrics_encoder/__init__.py

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,27 @@
1313
# limitations under the License.
1414
import logging
1515

16+
from opentelemetry.sdk.metrics.export import (
17+
MetricExporter,
18+
)
19+
from os import environ
20+
from opentelemetry.sdk.metrics import (
21+
Counter,
22+
Histogram,
23+
ObservableCounter,
24+
ObservableGauge,
25+
ObservableUpDownCounter,
26+
UpDownCounter,
27+
)
1628
from opentelemetry.exporter.otlp.proto.common._internal import (
1729
_encode_attributes,
1830
)
31+
from opentelemetry.sdk.environment_variables import (
32+
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
33+
)
34+
from opentelemetry.sdk.metrics.export import (
35+
AggregationTemporality,
36+
)
1937
from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import (
2038
ExportMetricsServiceRequest,
2139
)
@@ -24,17 +42,118 @@
2442
from opentelemetry.sdk.metrics.export import (
2543
MetricsData,
2644
Gauge,
27-
Histogram,
45+
Histogram as HistogramType,
2846
Sum,
2947
ExponentialHistogram as ExponentialHistogramType,
3048
)
49+
from typing import Dict
3150
from opentelemetry.proto.resource.v1.resource_pb2 import (
3251
Resource as PB2Resource,
3352
)
53+
from opentelemetry.sdk.environment_variables import (
54+
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION,
55+
)
56+
from opentelemetry.sdk.metrics.view import (
57+
ExponentialBucketHistogramAggregation,
58+
ExplicitBucketHistogramAggregation,
59+
)
3460

3561
_logger = logging.getLogger(__name__)
3662

3763

64+
class OTLPMetricExporterMixin:
65+
def _common_configuration(
66+
self,
67+
preferred_temporality: Dict[type, AggregationTemporality] = None,
68+
) -> None:
69+
70+
instrument_class_temporality = {}
71+
72+
otel_exporter_otlp_metrics_temporality_preference = (
73+
environ.get(
74+
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
75+
"CUMULATIVE",
76+
)
77+
.upper()
78+
.strip()
79+
)
80+
81+
if otel_exporter_otlp_metrics_temporality_preference == "DELTA":
82+
instrument_class_temporality = {
83+
Counter: AggregationTemporality.DELTA,
84+
UpDownCounter: AggregationTemporality.CUMULATIVE,
85+
Histogram: AggregationTemporality.DELTA,
86+
ObservableCounter: AggregationTemporality.DELTA,
87+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
88+
ObservableGauge: AggregationTemporality.CUMULATIVE,
89+
}
90+
91+
elif otel_exporter_otlp_metrics_temporality_preference == "LOWMEMORY":
92+
instrument_class_temporality = {
93+
Counter: AggregationTemporality.DELTA,
94+
UpDownCounter: AggregationTemporality.CUMULATIVE,
95+
Histogram: AggregationTemporality.DELTA,
96+
ObservableCounter: AggregationTemporality.CUMULATIVE,
97+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
98+
ObservableGauge: AggregationTemporality.CUMULATIVE,
99+
}
100+
101+
else:
102+
if otel_exporter_otlp_metrics_temporality_preference != (
103+
"CUMULATIVE"
104+
):
105+
_logger.warning(
106+
"Unrecognized OTEL_EXPORTER_METRICS_TEMPORALITY_PREFERENCE"
107+
" value found: "
108+
f"{otel_exporter_otlp_metrics_temporality_preference}, "
109+
"using CUMULATIVE"
110+
)
111+
instrument_class_temporality = {
112+
Counter: AggregationTemporality.CUMULATIVE,
113+
UpDownCounter: AggregationTemporality.CUMULATIVE,
114+
Histogram: AggregationTemporality.CUMULATIVE,
115+
ObservableCounter: AggregationTemporality.CUMULATIVE,
116+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
117+
ObservableGauge: AggregationTemporality.CUMULATIVE,
118+
}
119+
120+
instrument_class_temporality.update(preferred_temporality or {})
121+
122+
otel_exporter_otlp_metrics_default_histogram_aggregation = environ.get(
123+
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION,
124+
"explicit_bucket_histogram",
125+
)
126+
127+
if otel_exporter_otlp_metrics_default_histogram_aggregation == (
128+
"base2_exponential_bucket_histogram"
129+
):
130+
131+
histogram_aggregation_type = ExponentialBucketHistogramAggregation
132+
133+
else:
134+
135+
if otel_exporter_otlp_metrics_default_histogram_aggregation != (
136+
"explicit_bucket_histogram"
137+
):
138+
139+
_logger.warning(
140+
(
141+
"Invalid value for %s: %s, using explicit bucket "
142+
"histogram aggregation"
143+
),
144+
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION,
145+
otel_exporter_otlp_metrics_default_histogram_aggregation,
146+
)
147+
148+
histogram_aggregation_type = ExplicitBucketHistogramAggregation
149+
150+
MetricExporter.__init__(
151+
self,
152+
preferred_temporality=instrument_class_temporality,
153+
preferred_aggregation={Histogram: histogram_aggregation_type()},
154+
)
155+
156+
38157
def encode_metrics(data: MetricsData) -> ExportMetricsServiceRequest:
39158
resource_metrics_dict = {}
40159

@@ -85,7 +204,7 @@ def encode_metrics(data: MetricsData) -> ExportMetricsServiceRequest:
85204
pt.as_double = data_point.value
86205
pb2_metric.gauge.data_points.append(pt)
87206

88-
elif isinstance(metric.data, Histogram):
207+
elif isinstance(metric.data, HistogramType):
89208
for data_point in metric.data.data_points:
90209
pt = pb2.HistogramDataPoint(
91210
attributes=_encode_attributes(

exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py

Lines changed: 5 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,6 @@
4747
OTEL_EXPORTER_OTLP_METRICS_HEADERS,
4848
OTEL_EXPORTER_OTLP_METRICS_INSECURE,
4949
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
50-
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
51-
)
52-
from opentelemetry.sdk.metrics import (
53-
Counter,
54-
Histogram,
55-
ObservableCounter,
56-
ObservableGauge,
57-
ObservableUpDownCounter,
58-
UpDownCounter,
5950
)
6051
from opentelemetry.sdk.metrics.export import (
6152
AggregationTemporality,
@@ -73,13 +64,17 @@
7364
Sum,
7465
ExponentialHistogram as ExponentialHistogramType,
7566
)
67+
from opentelemetry.exporter.otlp.proto.common._internal.metrics_encoder import (
68+
OTLPMetricExporterMixin,
69+
)
7670

7771
_logger = getLogger(__name__)
7872

7973

8074
class OTLPMetricExporter(
8175
MetricExporter,
8276
OTLPExporterMixin[Metric, ExportMetricsServiceRequest, MetricExportResult],
77+
OTLPMetricExporterMixin,
8378
):
8479
"""OTLP metric exporter
8580
@@ -132,63 +127,7 @@ def __init__(
132127
else compression
133128
)
134129

135-
instrument_class_temporality = {}
136-
137-
otel_exporter_otlp_metrics_temporality_preference = (
138-
environ.get(
139-
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
140-
"CUMULATIVE",
141-
)
142-
.upper()
143-
.strip()
144-
)
145-
146-
if otel_exporter_otlp_metrics_temporality_preference == "DELTA":
147-
instrument_class_temporality = {
148-
Counter: AggregationTemporality.DELTA,
149-
UpDownCounter: AggregationTemporality.CUMULATIVE,
150-
Histogram: AggregationTemporality.DELTA,
151-
ObservableCounter: AggregationTemporality.DELTA,
152-
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
153-
ObservableGauge: AggregationTemporality.CUMULATIVE,
154-
}
155-
156-
elif otel_exporter_otlp_metrics_temporality_preference == "LOWMEMORY":
157-
instrument_class_temporality = {
158-
Counter: AggregationTemporality.DELTA,
159-
UpDownCounter: AggregationTemporality.CUMULATIVE,
160-
Histogram: AggregationTemporality.DELTA,
161-
ObservableCounter: AggregationTemporality.CUMULATIVE,
162-
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
163-
ObservableGauge: AggregationTemporality.CUMULATIVE,
164-
}
165-
166-
else:
167-
if otel_exporter_otlp_metrics_temporality_preference != (
168-
"CUMULATIVE"
169-
):
170-
_logger.warning(
171-
"Unrecognized OTEL_EXPORTER_METRICS_TEMPORALITY_PREFERENCE"
172-
" value found: "
173-
f"{otel_exporter_otlp_metrics_temporality_preference}, "
174-
"using CUMULATIVE"
175-
)
176-
instrument_class_temporality = {
177-
Counter: AggregationTemporality.CUMULATIVE,
178-
UpDownCounter: AggregationTemporality.CUMULATIVE,
179-
Histogram: AggregationTemporality.CUMULATIVE,
180-
ObservableCounter: AggregationTemporality.CUMULATIVE,
181-
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
182-
ObservableGauge: AggregationTemporality.CUMULATIVE,
183-
}
184-
185-
instrument_class_temporality.update(preferred_temporality or {})
186-
187-
MetricExporter.__init__(
188-
self,
189-
preferred_temporality=instrument_class_temporality,
190-
preferred_aggregation=preferred_aggregation,
191-
)
130+
self._common_configuration(preferred_temporality)
192131

193132
OTLPExporterMixin.__init__(
194133
self,

exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_metrics_exporter.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
OTEL_EXPORTER_OTLP_COMPRESSION,
4545
OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE,
4646
OTEL_EXPORTER_OTLP_METRICS_COMPRESSION,
47+
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION,
4748
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
4849
OTEL_EXPORTER_OTLP_METRICS_HEADERS,
4950
OTEL_EXPORTER_OTLP_METRICS_INSECURE,
@@ -68,6 +69,10 @@
6869
ResourceMetrics,
6970
ScopeMetrics,
7071
)
72+
from opentelemetry.sdk.metrics.view import (
73+
ExplicitBucketHistogramAggregation,
74+
ExponentialBucketHistogramAggregation,
75+
)
7176
from opentelemetry.sdk.resources import Resource
7277
from opentelemetry.sdk.util.instrumentation import (
7378
InstrumentationScope as SDKInstrumentationScope,
@@ -872,6 +877,57 @@ def test_aggregation_temporality(self):
872877
AggregationTemporality.CUMULATIVE,
873878
)
874879

880+
def test_exponential_explicit_bucket_histogram(self):
881+
882+
self.assertIsInstance(
883+
# pylint: disable=protected-access
884+
OTLPMetricExporter()._preferred_aggregation[Histogram],
885+
ExplicitBucketHistogramAggregation,
886+
)
887+
888+
with patch.dict(
889+
environ,
890+
{
891+
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION: "base2_exponential_bucket_histogram"
892+
},
893+
):
894+
self.assertIsInstance(
895+
# pylint: disable=protected-access
896+
OTLPMetricExporter()._preferred_aggregation[Histogram],
897+
ExponentialBucketHistogramAggregation,
898+
)
899+
900+
with patch.dict(
901+
environ,
902+
{OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION: "abc"},
903+
):
904+
with self.assertLogs(level=WARNING) as log:
905+
self.assertIsInstance(
906+
# pylint: disable=protected-access
907+
OTLPMetricExporter()._preferred_aggregation[Histogram],
908+
ExplicitBucketHistogramAggregation,
909+
)
910+
self.assertIn(
911+
(
912+
"Invalid value for OTEL_EXPORTER_OTLP_METRICS_DEFAULT_"
913+
"HISTOGRAM_AGGREGATION: abc, using explicit bucket "
914+
"histogram aggregation"
915+
),
916+
log.output[0],
917+
)
918+
919+
with patch.dict(
920+
environ,
921+
{
922+
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION: "explicit_bucket_histogram"
923+
},
924+
):
925+
self.assertIsInstance(
926+
# pylint: disable=protected-access
927+
OTLPMetricExporter()._preferred_aggregation[Histogram],
928+
ExplicitBucketHistogramAggregation,
929+
)
930+
875931

876932
def _resource_metrics(
877933
index: int, scope_metrics: List[ScopeMetrics]

0 commit comments

Comments
 (0)