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

Skip to content

Commit d8f32c9

Browse files
authored
Respect OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE only for otlp exporter (open-telemetry#2843)
1 parent c6d7b9f commit d8f32c9

File tree

7 files changed

+190
-132
lines changed

7 files changed

+190
-132
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
([#2754](https://github.com/open-telemetry/opentelemetry-python/pull/2754))
2020
- Fix --insecure of CLI argument
2121
([#2696](https://github.com/open-telemetry/opentelemetry-python/pull/2696))
22+
- Add temporality and aggregation configuration for metrics exporters,
23+
use `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` only for OTLP metrics exporter
24+
([#2843](https://github.com/open-telemetry/opentelemetry-python/pull/2843))
2225
- Instrument instances are always created through a Meter
2326
([#2844](https://github.com/open-telemetry/opentelemetry-python/pull/2844))
2427

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

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313

1414
from logging import getLogger
1515
from os import environ
16-
from typing import Optional, Sequence
16+
from typing import Dict, Optional, Sequence
1717
from grpc import ChannelCredentials, Compression
18+
from opentelemetry.sdk.metrics._internal.aggregation import Aggregation
1819
from opentelemetry.exporter.otlp.proto.grpc.exporter import (
1920
OTLPExporterMixin,
2021
get_resource_data,
@@ -29,18 +30,25 @@
2930
from opentelemetry.proto.metrics.v1 import metrics_pb2 as pb2
3031
from opentelemetry.sdk.environment_variables import (
3132
OTEL_EXPORTER_OTLP_METRICS_INSECURE,
33+
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
3234
)
33-
from opentelemetry.sdk.metrics.export import (
34-
Gauge,
35+
from opentelemetry.sdk.metrics import (
36+
Counter,
3537
Histogram,
36-
Metric,
37-
Sum,
38+
ObservableCounter,
39+
ObservableGauge,
40+
ObservableUpDownCounter,
41+
UpDownCounter,
3842
)
39-
4043
from opentelemetry.sdk.metrics.export import (
44+
AggregationTemporality,
45+
Gauge,
46+
Histogram as HistogramType,
47+
Metric,
4148
MetricExporter,
4249
MetricExportResult,
4350
MetricsData,
51+
Sum,
4452
)
4553

4654
_logger = getLogger(__name__)
@@ -61,22 +69,57 @@ def __init__(
6169
headers: Optional[Sequence] = None,
6270
timeout: Optional[int] = None,
6371
compression: Optional[Compression] = None,
72+
preferred_temporality: Dict[type, AggregationTemporality] = None,
73+
preferred_aggregation: Dict[type, Aggregation] = None,
6474
):
6575

6676
if insecure is None:
6777
insecure = environ.get(OTEL_EXPORTER_OTLP_METRICS_INSECURE)
6878
if insecure is not None:
6979
insecure = insecure.lower() == "true"
7080

71-
super().__init__(
72-
**{
73-
"endpoint": endpoint,
74-
"insecure": insecure,
75-
"credentials": credentials,
76-
"headers": headers,
77-
"timeout": timeout,
78-
"compression": compression,
81+
instrument_class_temporality = {}
82+
if (
83+
environ.get(
84+
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
85+
"CUMULATIVE",
86+
)
87+
.upper()
88+
.strip()
89+
== "DELTA"
90+
):
91+
instrument_class_temporality = {
92+
Counter: AggregationTemporality.DELTA,
93+
UpDownCounter: AggregationTemporality.CUMULATIVE,
94+
Histogram: AggregationTemporality.DELTA,
95+
ObservableCounter: AggregationTemporality.DELTA,
96+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
97+
ObservableGauge: AggregationTemporality.CUMULATIVE,
7998
}
99+
else:
100+
instrument_class_temporality = {
101+
Counter: AggregationTemporality.CUMULATIVE,
102+
UpDownCounter: AggregationTemporality.CUMULATIVE,
103+
Histogram: AggregationTemporality.CUMULATIVE,
104+
ObservableCounter: AggregationTemporality.CUMULATIVE,
105+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
106+
ObservableGauge: AggregationTemporality.CUMULATIVE,
107+
}
108+
instrument_class_temporality.update(preferred_temporality or {})
109+
110+
MetricExporter.__init__(
111+
self,
112+
preferred_temporality=instrument_class_temporality,
113+
preferred_aggregation=preferred_aggregation,
114+
)
115+
OTLPExporterMixin.__init__(
116+
self,
117+
endpoint=endpoint,
118+
insecure=insecure,
119+
credentials=credentials,
120+
headers=headers,
121+
timeout=timeout,
122+
compression=compression,
80123
)
81124

82125
def _translate_data(
@@ -132,7 +175,7 @@ def _translate_data(
132175
pt.as_double = data_point.value
133176
pb2_metric.gauge.data_points.append(pt)
134177

135-
elif isinstance(metric.data, Histogram):
178+
elif isinstance(metric.data, HistogramType):
136179
for data_point in metric.data.data_points:
137180
pt = pb2.HistogramDataPoint(
138181
attributes=self._translate_attributes(

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

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,19 @@
4242
)
4343
from opentelemetry.sdk.environment_variables import (
4444
OTEL_EXPORTER_OTLP_METRICS_INSECURE,
45+
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
4546
)
46-
from opentelemetry.sdk.metrics.export import (
47-
AggregationTemporality,
47+
from opentelemetry.sdk.metrics import (
48+
Counter,
4849
Histogram,
50+
ObservableCounter,
51+
ObservableGauge,
52+
ObservableUpDownCounter,
53+
UpDownCounter,
54+
)
55+
from opentelemetry.sdk.metrics.export import AggregationTemporality
56+
from opentelemetry.sdk.metrics.export import Histogram as HistogramType
57+
from opentelemetry.sdk.metrics.export import (
4958
HistogramDataPoint,
5059
Metric,
5160
MetricExportResult,
@@ -121,7 +130,7 @@ def setUp(self):
121130
name="histogram",
122131
description="foo",
123132
unit="s",
124-
data=Histogram(
133+
data=HistogramType(
125134
data_points=[
126135
HistogramDataPoint(
127136
attributes={"a": 1, "b": True},
@@ -302,6 +311,40 @@ def test_exporting(self):
302311
# pylint: disable=protected-access
303312
self.assertEqual(self.exporter._exporting, "metrics")
304313

314+
@patch.dict(
315+
"os.environ",
316+
{OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: "DELTA"},
317+
)
318+
def test_preferred_temporality(self):
319+
# pylint: disable=protected-access
320+
exporter = OTLPMetricExporter(
321+
preferred_temporality={Counter: AggregationTemporality.CUMULATIVE}
322+
)
323+
self.assertEqual(
324+
exporter._preferred_temporality[Counter],
325+
AggregationTemporality.CUMULATIVE,
326+
)
327+
self.assertEqual(
328+
exporter._preferred_temporality[UpDownCounter],
329+
AggregationTemporality.CUMULATIVE,
330+
)
331+
self.assertEqual(
332+
exporter._preferred_temporality[Histogram],
333+
AggregationTemporality.DELTA,
334+
)
335+
self.assertEqual(
336+
exporter._preferred_temporality[ObservableCounter],
337+
AggregationTemporality.DELTA,
338+
)
339+
self.assertEqual(
340+
exporter._preferred_temporality[ObservableUpDownCounter],
341+
AggregationTemporality.CUMULATIVE,
342+
)
343+
self.assertEqual(
344+
exporter._preferred_temporality[ObservableGauge],
345+
AggregationTemporality.CUMULATIVE,
346+
)
347+
305348
@patch(
306349
"opentelemetry.exporter.otlp.proto.grpc.exporter.ssl_channel_credentials"
307350
)

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
detach,
3232
set_value,
3333
)
34-
from opentelemetry.sdk.environment_variables import (
35-
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
36-
)
3734
from opentelemetry.sdk.metrics._internal.aggregation import (
3835
AggregationTemporality,
3936
DefaultAggregation,
@@ -73,8 +70,26 @@ class MetricExporter(ABC):
7370
7471
Interface to be implemented by services that want to export metrics received
7572
in their own format.
73+
74+
Args:
75+
preferred_temporality: Used by `opentelemetry.sdk.metrics.export.PeriodicExportingMetricReader` to
76+
configure exporter level preferred temporality. See `opentelemetry.sdk.metrics.export.MetricReader` for
77+
more details on what preferred temporality is.
78+
preferred_aggregation: Used by `opentelemetry.sdk.metrics.export.PeriodicExportingMetricReader` to
79+
configure exporter level preferred aggregation. See `opentelemetry.sdk.metrics.export.MetricReader` for
80+
more details on what preferred aggregation is.
7681
"""
7782

83+
def __init__(
84+
self,
85+
preferred_temporality: Dict[type, AggregationTemporality] = None,
86+
preferred_aggregation: Dict[
87+
type, "opentelemetry.sdk.metrics.view.Aggregation"
88+
] = None,
89+
) -> None:
90+
self._preferred_temporality = preferred_temporality
91+
self._preferred_aggregation = preferred_aggregation
92+
7893
@abstractmethod
7994
def export(
8095
self,
@@ -122,6 +137,7 @@ def __init__(
122137
] = lambda metrics_data: metrics_data.to_json()
123138
+ linesep,
124139
):
140+
super().__init__()
125141
self.out = out
126142
self.formatter = formatter
127143

@@ -143,6 +159,7 @@ def force_flush(self, timeout_millis: float = 10_000) -> bool:
143159

144160

145161
class MetricReader(ABC):
162+
# pylint: disable=too-many-branches
146163
"""
147164
Base class for all metric readers
148165
@@ -157,8 +174,6 @@ class MetricReader(ABC):
157174
temporalities of the classes that the user wants to change, not all of
158175
them. The classes not included in the passed dictionary will retain
159176
their association to their default aggregation temporalities.
160-
The value passed here will override the corresponding values set
161-
via the environment variable
162177
preferred_aggregation: A mapping between instrument classes and
163178
aggregation instances. By default maps all instrument classes to an
164179
instance of `DefaultAggregation`. This mapping will be used to
@@ -177,10 +192,6 @@ class MetricReader(ABC):
177192
.. automethod:: _receive_metrics
178193
"""
179194

180-
# FIXME add :std:envvar:`OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE`
181-
# to the end of the documentation paragraph above.
182-
183-
# pylint: disable=too-many-branches
184195
def __init__(
185196
self,
186197
preferred_temporality: Dict[type, AggregationTemporality] = None,
@@ -196,33 +207,14 @@ def __init__(
196207
Iterable["opentelemetry.sdk.metrics.export.Metric"],
197208
] = None
198209

199-
if (
200-
environ.get(
201-
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
202-
"CUMULATIVE",
203-
)
204-
.upper()
205-
.strip()
206-
== "DELTA"
207-
):
208-
self._instrument_class_temporality = {
209-
_Counter: AggregationTemporality.DELTA,
210-
_UpDownCounter: AggregationTemporality.CUMULATIVE,
211-
_Histogram: AggregationTemporality.DELTA,
212-
_ObservableCounter: AggregationTemporality.DELTA,
213-
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
214-
_ObservableGauge: AggregationTemporality.CUMULATIVE,
215-
}
216-
217-
else:
218-
self._instrument_class_temporality = {
219-
_Counter: AggregationTemporality.CUMULATIVE,
220-
_UpDownCounter: AggregationTemporality.CUMULATIVE,
221-
_Histogram: AggregationTemporality.CUMULATIVE,
222-
_ObservableCounter: AggregationTemporality.CUMULATIVE,
223-
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
224-
_ObservableGauge: AggregationTemporality.CUMULATIVE,
225-
}
210+
self._instrument_class_temporality = {
211+
_Counter: AggregationTemporality.CUMULATIVE,
212+
_UpDownCounter: AggregationTemporality.CUMULATIVE,
213+
_Histogram: AggregationTemporality.CUMULATIVE,
214+
_ObservableCounter: AggregationTemporality.CUMULATIVE,
215+
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
216+
_ObservableGauge: AggregationTemporality.CUMULATIVE,
217+
}
226218

227219
if preferred_temporality is not None:
228220
for temporality in preferred_temporality.values():
@@ -404,16 +396,13 @@ class PeriodicExportingMetricReader(MetricReader):
404396
def __init__(
405397
self,
406398
exporter: MetricExporter,
407-
preferred_temporality: Dict[type, AggregationTemporality] = None,
408-
preferred_aggregation: Dict[
409-
type, "opentelemetry.sdk.metrics.view.Aggregation"
410-
] = None,
411399
export_interval_millis: Optional[float] = None,
412400
export_timeout_millis: Optional[float] = None,
413401
) -> None:
402+
# PeriodicExportingMetricReader defers to exporter for configuration
414403
super().__init__(
415-
preferred_temporality=preferred_temporality,
416-
preferred_aggregation=preferred_aggregation,
404+
preferred_temporality=exporter._preferred_temporality,
405+
preferred_aggregation=exporter._preferred_aggregation,
417406
)
418407
self._exporter = exporter
419408
if export_interval_millis is None:

0 commit comments

Comments
 (0)