Skip to content

Commit 42f8736

Browse files
authored
Implement LowMemory temporality presets (#3223)
* Implement LowMemory temporality Fixes #3075 * Fix lint
1 parent f40be51 commit 42f8736

File tree

6 files changed

+310
-35
lines changed

6 files changed

+310
-35
lines changed

CHANGELOG.md

+2
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+
- Implement LowMemory temporality
11+
([#3223](https://github.com/open-telemetry/opentelemetry-python/pull/3223))
1012
- PeriodicExportingMetricReader will continue if collection times out
1113
([#3100](https://github.com/open-telemetry/opentelemetry-python/pull/3100))
1214
- Fix formatting of ConsoleMetricExporter.

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

+35-12
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# See the License for the specific language governing permissions and
1212
# limitations under the License.
1313

14-
import dataclasses
14+
from dataclasses import replace
1515
from logging import getLogger
1616
from os import environ
1717
from typing import Dict, Iterable, List, Optional, Sequence
@@ -120,15 +120,17 @@ def __init__(
120120
)
121121

122122
instrument_class_temporality = {}
123-
if (
123+
124+
otel_exporter_otlp_metrics_temporality_preference = (
124125
environ.get(
125126
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
126127
"CUMULATIVE",
127128
)
128129
.upper()
129130
.strip()
130-
== "DELTA"
131-
):
131+
)
132+
133+
if otel_exporter_otlp_metrics_temporality_preference == "DELTA":
132134
instrument_class_temporality = {
133135
Counter: AggregationTemporality.DELTA,
134136
UpDownCounter: AggregationTemporality.CUMULATIVE,
@@ -137,7 +139,27 @@ def __init__(
137139
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
138140
ObservableGauge: AggregationTemporality.CUMULATIVE,
139141
}
142+
143+
elif otel_exporter_otlp_metrics_temporality_preference == "LOWMEMORY":
144+
instrument_class_temporality = {
145+
Counter: AggregationTemporality.DELTA,
146+
UpDownCounter: AggregationTemporality.CUMULATIVE,
147+
Histogram: AggregationTemporality.DELTA,
148+
ObservableCounter: AggregationTemporality.CUMULATIVE,
149+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
150+
ObservableGauge: AggregationTemporality.CUMULATIVE,
151+
}
152+
140153
else:
154+
if otel_exporter_otlp_metrics_temporality_preference != (
155+
"CUMULATIVE"
156+
):
157+
_logger.warning(
158+
"Unrecognized OTEL_EXPORTER_METRICS_TEMPORALITY_PREFERENCE"
159+
" value found: "
160+
f"{otel_exporter_otlp_metrics_temporality_preference}, "
161+
"using CUMULATIVE"
162+
)
141163
instrument_class_temporality = {
142164
Counter: AggregationTemporality.CUMULATIVE,
143165
UpDownCounter: AggregationTemporality.CUMULATIVE,
@@ -146,6 +168,7 @@ def __init__(
146168
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
147169
ObservableGauge: AggregationTemporality.CUMULATIVE,
148170
}
171+
149172
instrument_class_temporality.update(preferred_temporality or {})
150173

151174
MetricExporter.__init__(
@@ -359,25 +382,25 @@ def _split_metrics_data(
359382
for resource_metrics in metrics_data.resource_metrics:
360383
split_scope_metrics: List[ScopeMetrics] = []
361384
split_resource_metrics.append(
362-
dataclasses.replace(
385+
replace(
363386
resource_metrics,
364387
scope_metrics=split_scope_metrics,
365388
)
366389
)
367390
for scope_metrics in resource_metrics.scope_metrics:
368391
split_metrics: List[Metric] = []
369392
split_scope_metrics.append(
370-
dataclasses.replace(
393+
replace(
371394
scope_metrics,
372395
metrics=split_metrics,
373396
)
374397
)
375398
for metric in scope_metrics.metrics:
376399
split_data_points: List[DataPointT] = []
377400
split_metrics.append(
378-
dataclasses.replace(
401+
replace(
379402
metric,
380-
data=dataclasses.replace(
403+
data=replace(
381404
metric.data,
382405
data_points=split_data_points,
383406
),
@@ -396,22 +419,22 @@ def _split_metrics_data(
396419
batch_size = 0
397420
split_data_points = []
398421
split_metrics = [
399-
dataclasses.replace(
422+
replace(
400423
metric,
401-
data=dataclasses.replace(
424+
data=replace(
402425
metric.data,
403426
data_points=split_data_points,
404427
),
405428
)
406429
]
407430
split_scope_metrics = [
408-
dataclasses.replace(
431+
replace(
409432
scope_metrics,
410433
metrics=split_metrics,
411434
)
412435
]
413436
split_resource_metrics = [
414-
dataclasses.replace(
437+
replace(
415438
resource_metrics,
416439
scope_metrics=split_scope_metrics,
417440
)

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

+107
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
# pylint: disable=too-many-lines
2020
from logging import WARNING
21+
from os import environ
2122
from os.path import dirname
2223
from typing import List
2324
from unittest import TestCase
@@ -1532,6 +1533,112 @@ def test_shutdown_wait_last_export(self):
15321533
finally:
15331534
export_thread.join()
15341535

1536+
def test_aggregation_temporality(self):
1537+
# pylint: disable=protected-access
1538+
1539+
otlp_metric_exporter = OTLPMetricExporter()
1540+
1541+
for (
1542+
temporality
1543+
) in otlp_metric_exporter._preferred_temporality.values():
1544+
self.assertEqual(temporality, AggregationTemporality.CUMULATIVE)
1545+
1546+
with patch.dict(
1547+
environ,
1548+
{OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: "CUMULATIVE"},
1549+
):
1550+
1551+
otlp_metric_exporter = OTLPMetricExporter()
1552+
1553+
for (
1554+
temporality
1555+
) in otlp_metric_exporter._preferred_temporality.values():
1556+
self.assertEqual(
1557+
temporality, AggregationTemporality.CUMULATIVE
1558+
)
1559+
1560+
with patch.dict(
1561+
environ, {OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: "ABC"}
1562+
):
1563+
1564+
with self.assertLogs(level=WARNING):
1565+
otlp_metric_exporter = OTLPMetricExporter()
1566+
1567+
for (
1568+
temporality
1569+
) in otlp_metric_exporter._preferred_temporality.values():
1570+
self.assertEqual(
1571+
temporality, AggregationTemporality.CUMULATIVE
1572+
)
1573+
1574+
with patch.dict(
1575+
environ,
1576+
{OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: "DELTA"},
1577+
):
1578+
1579+
otlp_metric_exporter = OTLPMetricExporter()
1580+
1581+
self.assertEqual(
1582+
otlp_metric_exporter._preferred_temporality[Counter],
1583+
AggregationTemporality.DELTA,
1584+
)
1585+
self.assertEqual(
1586+
otlp_metric_exporter._preferred_temporality[UpDownCounter],
1587+
AggregationTemporality.CUMULATIVE,
1588+
)
1589+
self.assertEqual(
1590+
otlp_metric_exporter._preferred_temporality[Histogram],
1591+
AggregationTemporality.DELTA,
1592+
)
1593+
self.assertEqual(
1594+
otlp_metric_exporter._preferred_temporality[ObservableCounter],
1595+
AggregationTemporality.DELTA,
1596+
)
1597+
self.assertEqual(
1598+
otlp_metric_exporter._preferred_temporality[
1599+
ObservableUpDownCounter
1600+
],
1601+
AggregationTemporality.CUMULATIVE,
1602+
)
1603+
self.assertEqual(
1604+
otlp_metric_exporter._preferred_temporality[ObservableGauge],
1605+
AggregationTemporality.CUMULATIVE,
1606+
)
1607+
1608+
with patch.dict(
1609+
environ,
1610+
{OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: "LOWMEMORY"},
1611+
):
1612+
1613+
otlp_metric_exporter = OTLPMetricExporter()
1614+
1615+
self.assertEqual(
1616+
otlp_metric_exporter._preferred_temporality[Counter],
1617+
AggregationTemporality.DELTA,
1618+
)
1619+
self.assertEqual(
1620+
otlp_metric_exporter._preferred_temporality[UpDownCounter],
1621+
AggregationTemporality.CUMULATIVE,
1622+
)
1623+
self.assertEqual(
1624+
otlp_metric_exporter._preferred_temporality[Histogram],
1625+
AggregationTemporality.DELTA,
1626+
)
1627+
self.assertEqual(
1628+
otlp_metric_exporter._preferred_temporality[ObservableCounter],
1629+
AggregationTemporality.CUMULATIVE,
1630+
)
1631+
self.assertEqual(
1632+
otlp_metric_exporter._preferred_temporality[
1633+
ObservableUpDownCounter
1634+
],
1635+
AggregationTemporality.CUMULATIVE,
1636+
)
1637+
self.assertEqual(
1638+
otlp_metric_exporter._preferred_temporality[ObservableGauge],
1639+
AggregationTemporality.CUMULATIVE,
1640+
)
1641+
15351642

15361643
def _resource_metrics(
15371644
index: int, scope_metrics: List[ScopeMetrics]

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

+26-3
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,17 @@ def __init__(
138138
)
139139

140140
instrument_class_temporality = {}
141-
if (
141+
142+
otel_exporter_otlp_metrics_temporality_preference = (
142143
environ.get(
143144
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
144145
"CUMULATIVE",
145146
)
146147
.upper()
147148
.strip()
148-
== "DELTA"
149-
):
149+
)
150+
151+
if otel_exporter_otlp_metrics_temporality_preference == "DELTA":
150152
instrument_class_temporality = {
151153
Counter: AggregationTemporality.DELTA,
152154
UpDownCounter: AggregationTemporality.CUMULATIVE,
@@ -155,7 +157,27 @@ def __init__(
155157
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
156158
ObservableGauge: AggregationTemporality.CUMULATIVE,
157159
}
160+
161+
elif otel_exporter_otlp_metrics_temporality_preference == "LOWMEMORY":
162+
instrument_class_temporality = {
163+
Counter: AggregationTemporality.DELTA,
164+
UpDownCounter: AggregationTemporality.CUMULATIVE,
165+
Histogram: AggregationTemporality.DELTA,
166+
ObservableCounter: AggregationTemporality.CUMULATIVE,
167+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
168+
ObservableGauge: AggregationTemporality.CUMULATIVE,
169+
}
170+
158171
else:
172+
if otel_exporter_otlp_metrics_temporality_preference != (
173+
"CUMULATIVE"
174+
):
175+
_logger.warning(
176+
"Unrecognized OTEL_EXPORTER_METRICS_TEMPORALITY_PREFERENCE"
177+
" value found: "
178+
f"{otel_exporter_otlp_metrics_temporality_preference}, "
179+
"using CUMULATIVE"
180+
)
159181
instrument_class_temporality = {
160182
Counter: AggregationTemporality.CUMULATIVE,
161183
UpDownCounter: AggregationTemporality.CUMULATIVE,
@@ -164,6 +186,7 @@ def __init__(
164186
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
165187
ObservableGauge: AggregationTemporality.CUMULATIVE,
166188
}
189+
167190
instrument_class_temporality.update(preferred_temporality or {})
168191

169192
MetricExporter.__init__(

0 commit comments

Comments
 (0)