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

Skip to content

Commit d112814

Browse files
authored
Refactor SDK MeterProvider (open-telemetry#2401)
1 parent e780a97 commit d112814

File tree

2 files changed

+53
-15
lines changed

2 files changed

+53
-15
lines changed

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

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from opentelemetry.sdk._metrics.sdk_configuration import SdkConfiguration
4949
from opentelemetry.sdk.resources import Resource
5050
from opentelemetry.sdk.util.instrumentation import InstrumentationInfo
51+
from opentelemetry.util._once import Once
5152

5253
_logger = getLogger(__name__)
5354

@@ -171,30 +172,30 @@ def __init__(
171172
self._metric_readers = metric_readers
172173

173174
for metric_reader in self._sdk_config.metric_readers:
174-
metric_reader._register_measurement_consumer(self)
175+
metric_reader._set_collect_callback(
176+
self._measurement_consumer.collect
177+
)
175178

179+
self._shutdown_once = Once()
176180
self._shutdown = False
177181

178182
def force_flush(self) -> bool:
179183

180184
# FIXME implement a timeout
181185

182-
metric_reader_result = True
183-
184186
for metric_reader in self._sdk_config.metric_readers:
185-
metric_reader_result = (
186-
metric_reader_result and metric_reader.force_flush()
187-
)
188-
189-
if not metric_reader_result:
190-
_logger.warning("Unable to force flush all metric readers")
191-
192-
return metric_reader_result
187+
metric_reader.collect()
188+
return True
193189

194190
def shutdown(self):
195191
# FIXME implement a timeout
196192

197-
if self._shutdown:
193+
def _shutdown():
194+
self._shutdown = True
195+
196+
did_shutdown = self._shutdown_once.do_once(_shutdown)
197+
198+
if not did_shutdown:
198199
_logger.warning("shutdown can only be called once")
199200
return False
200201

@@ -210,8 +211,6 @@ def shutdown(self):
210211

211212
overall_result = overall_result and metric_reader_result
212213

213-
self._shutdown = True
214-
215214
if self._atexit_handler is not None:
216215
unregister(self._atexit_handler)
217216
self._atexit_handler = None

opentelemetry-sdk/tests/metrics/test_metrics.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,24 @@
2626
ObservableUpDownCounter,
2727
UpDownCounter,
2828
)
29+
from opentelemetry.sdk._metrics.metric_reader import MetricReader
30+
from opentelemetry.sdk._metrics.point import AggregationTemporality
2931
from opentelemetry.sdk.resources import Resource
32+
from opentelemetry.test.concurrency_test import ConcurrencyTestBase, MockFunc
3033

3134

32-
class TestMeterProvider(TestCase):
35+
class DummyMetricReader(MetricReader):
36+
def __init__(self):
37+
super().__init__(AggregationTemporality.CUMULATIVE)
38+
39+
def _receive_metrics(self, metrics):
40+
pass
41+
42+
def shutdown(self):
43+
return True
44+
45+
46+
class TestMeterProvider(ConcurrencyTestBase):
3347
def test_resource(self):
3448
"""
3549
`MeterProvider` provides a way to allow a `Resource` to be specified.
@@ -139,6 +153,31 @@ def test_shutdown_subsequent_calls(self):
139153
with self.assertLogs(level=WARNING):
140154
meter_provider.shutdown()
141155

156+
@patch("opentelemetry.sdk._metrics._logger")
157+
def test_shutdown_race(self, mock_logger):
158+
mock_logger.warning = MockFunc()
159+
meter_provider = MeterProvider()
160+
num_threads = 70
161+
self.run_with_many_threads(
162+
meter_provider.shutdown, num_threads=num_threads
163+
)
164+
self.assertEqual(mock_logger.warning.call_count, num_threads - 1)
165+
166+
@patch("opentelemetry.sdk._metrics.SynchronousMeasurementConsumer")
167+
def test_measurement_collect_callback(
168+
self, mock_sync_measurement_consumer
169+
):
170+
metric_readers = [DummyMetricReader()] * 5
171+
sync_consumer_instance = mock_sync_measurement_consumer()
172+
sync_consumer_instance.collect = MockFunc()
173+
MeterProvider(metric_readers=metric_readers)
174+
175+
for reader in metric_readers:
176+
reader.collect()
177+
self.assertEqual(
178+
sync_consumer_instance.collect.call_count, len(metric_readers)
179+
)
180+
142181
@patch("opentelemetry.sdk._metrics.SynchronousMeasurementConsumer")
143182
def test_creates_sync_measurement_consumer(
144183
self, mock_sync_measurement_consumer

0 commit comments

Comments
 (0)