Skip to content

Commit 82e9a0d

Browse files
committed
Merge branch 'main' into prometheus_exporter
2 parents db2e53d + 5de1ccb commit 82e9a0d

File tree

8 files changed

+101
-59
lines changed

8 files changed

+101
-59
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929
([#4222](https://github.com/open-telemetry/opentelemetry-python/pull/4222))
3030
- Record logger name as the instrumentation scope name
3131
([#4208](https://github.com/open-telemetry/opentelemetry-python/pull/4208))
32+
- Fix memory leak in exporter and reader
33+
([#4224](https://github.com/open-telemetry/opentelemetry-python/pull/4224))
34+
- Drop `OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION` environment variable
35+
([#4217](https://github.com/open-telemetry/opentelemetry-python/pull/4217))
3236

3337
## Version 1.27.0/0.48b0 (2024-08-28)
3438

exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
from opentelemetry.sdk.environment_variables import (
8989
OTEL_EXPORTER_PROMETHEUS_HOST,
9090
OTEL_EXPORTER_PROMETHEUS_PORT,
91-
OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION,
9291
)
9392
from opentelemetry.sdk.metrics import (
9493
Counter,
@@ -255,18 +254,7 @@ def _translate_to_prometheus(
255254

256255
metric_description = metric.description or ""
257256

258-
# TODO(#3929): remove this opt-out option
259-
disable_unit_normalization = (
260-
environ.get(
261-
OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION,
262-
"false",
263-
).lower()
264-
== "true"
265-
)
266-
if disable_unit_normalization:
267-
metric_unit = metric.unit
268-
else:
269-
metric_unit = map_unit(metric.unit)
257+
metric_unit = map_unit(metric.unit)
270258

271259
for number_data_point in metric.data.data_points:
272260
label_keys = []

exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from os import environ
1615
from textwrap import dedent
1716
from unittest import TestCase
1817
from unittest.mock import Mock, patch
@@ -31,9 +30,6 @@
3130
PrometheusMetricReader,
3231
_CustomCollector,
3332
)
34-
from opentelemetry.sdk.environment_variables import (
35-
OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION,
36-
)
3733
from opentelemetry.sdk.metrics import Exemplar, MeterProvider
3834
from opentelemetry.sdk.metrics.export import (
3935
AggregationTemporality,
@@ -623,25 +619,6 @@ def test_metric_name_with_unit(self):
623619
),
624620
)
625621

626-
# TODO(#3929): remove this opt-out option
627-
@patch.dict(
628-
environ,
629-
{
630-
OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION: "true"
631-
},
632-
)
633-
def test_metric_name_with_unit_normalization_disabled(self):
634-
self.verify_text_format(
635-
_generate_sum(name="test_unit_not_normalized", value=1, unit="s"),
636-
dedent(
637-
"""\
638-
# HELP test_unit_not_normalized_s_total foo
639-
# TYPE test_unit_not_normalized_s_total counter
640-
test_unit_not_normalized_s_total{a="1",b="true"} 1.0
641-
"""
642-
),
643-
)
644-
645622
def test_semconv(self):
646623
"""Tests that a few select semconv metrics get converted to the expected prometheus
647624
text format"""

opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -780,21 +780,3 @@
780780
This is an experimental environment variable and the name of this variable and its behavior can
781781
change in a non-backwards compatible way.
782782
"""
783-
784-
785-
# TODO(#3929): remove this opt-out option
786-
OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION = (
787-
"OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION"
788-
)
789-
"""
790-
.. envvar:: OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION
791-
792-
The :envvar:`OTEL_PYTHON_EXPERIMENTAL_DISABLE_PROMETHEUS_UNIT_NORMALIZATION` environment
793-
variable allows you to opt-out of the unit normalization described `in the specification
794-
<https://github.com/open-telemetry/opentelemetry-specification/blob/v1.33.0/specification/compatibility/prometheus_and_openmetrics.md#metric-metadata-1>`_.
795-
796-
Default: False
797-
798-
This is an temporary environment variable that provides backward compatibility but will be
799-
removed in the future https://github.com/open-telemetry/opentelemetry-python/issues/3929.
800-
"""

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
14+
import weakref
1515
from atexit import register, unregister
1616
from logging import getLogger
1717
from os import environ
@@ -386,7 +386,7 @@ class MeterProvider(APIMeterProvider):
386386
"""
387387

388388
_all_metric_readers_lock = Lock()
389-
_all_metric_readers = set()
389+
_all_metric_readers = weakref.WeakSet()
390390

391391
def __init__(
392392
self,

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import math
1616
import os
17+
import weakref
1718
from abc import ABC, abstractmethod
1819
from enum import Enum
1920
from logging import getLogger
@@ -488,7 +489,11 @@ def __init__(
488489
)
489490
self._daemon_thread.start()
490491
if hasattr(os, "register_at_fork"):
491-
os.register_at_fork(after_in_child=self._at_fork_reinit) # pylint: disable=protected-access
492+
weak_at_fork = weakref.WeakMethod(self._at_fork_reinit)
493+
494+
os.register_at_fork(
495+
after_in_child=lambda: weak_at_fork()() # pylint: disable=unnecessary-lambda, protected-access
496+
)
492497
elif self._export_interval_millis <= 0:
493498
raise ValueError(
494499
f"interval value {self._export_interval_millis} is invalid \
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import gc
16+
import time
17+
import weakref
18+
from typing import Sequence
19+
from unittest import TestCase
20+
21+
from opentelemetry.sdk.metrics import MeterProvider
22+
from opentelemetry.sdk.metrics.export import (
23+
Metric,
24+
MetricExporter,
25+
MetricExportResult,
26+
PeriodicExportingMetricReader,
27+
)
28+
29+
30+
class FakeMetricsExporter(MetricExporter):
31+
def __init__(
32+
self, wait=0, preferred_temporality=None, preferred_aggregation=None
33+
):
34+
self.wait = wait
35+
self.metrics = []
36+
self._shutdown = False
37+
super().__init__(
38+
preferred_temporality=preferred_temporality,
39+
preferred_aggregation=preferred_aggregation,
40+
)
41+
42+
def export(
43+
self,
44+
metrics_data: Sequence[Metric],
45+
timeout_millis: float = 10_000,
46+
**kwargs,
47+
) -> MetricExportResult:
48+
time.sleep(self.wait)
49+
self.metrics.extend(metrics_data)
50+
return True
51+
52+
def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
53+
self._shutdown = True
54+
55+
def force_flush(self, timeout_millis: float = 10_000) -> bool:
56+
return True
57+
58+
59+
class TestMeterProviderShutdown(TestCase):
60+
def test_meter_provider_shutdown_cleans_up_successfully(self):
61+
def create_and_shutdown():
62+
exporter = FakeMetricsExporter()
63+
exporter_wr = weakref.ref(exporter)
64+
65+
reader = PeriodicExportingMetricReader(exporter)
66+
reader_wr = weakref.ref(reader)
67+
68+
provider = MeterProvider(metric_readers=[reader])
69+
provider_wr = weakref.ref(provider)
70+
71+
provider.shutdown()
72+
73+
return exporter_wr, reader_wr, provider_wr
74+
75+
# When: the provider is shutdown
76+
(
77+
exporter_weakref,
78+
reader_weakref,
79+
provider_weakref,
80+
) = create_and_shutdown()
81+
gc.collect()
82+
83+
# Then: the provider, exporter and reader should be garbage collected
84+
self.assertIsNone(exporter_weakref())
85+
self.assertIsNone(reader_weakref())
86+
self.assertIsNone(provider_weakref())

opentelemetry-sdk/tests/metrics/test_metrics.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
# pylint: disable=protected-access,no-self-use
1616

17-
17+
import weakref
1818
from logging import WARNING
1919
from time import sleep
2020
from typing import Iterable, Sequence
@@ -66,7 +66,7 @@ def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
6666

6767
class TestMeterProvider(ConcurrencyTestBase, TestCase):
6868
def tearDown(self):
69-
MeterProvider._all_metric_readers = set()
69+
MeterProvider._all_metric_readers = weakref.WeakSet()
7070

7171
@patch.object(Resource, "create")
7272
def test_init_default(self, resource_patch):

0 commit comments

Comments
 (0)