From f135cc856ae7fa663428c5d0e7d6008fc1695b98 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Sun, 9 Feb 2020 22:55:28 -0800 Subject: [PATCH] Make default meter a DefaultMeter --- .../src/opentelemetry/metrics/__init__.py | 7 +++- .../tests/metrics/test_metrics.py | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 2185bfb7659..596d3ec70ab 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -347,7 +347,12 @@ def meter() -> Meter: if _METER is None: # pylint:disable=protected-access - _METER = loader._load_impl(Meter, _METER_FACTORY) + try: + _METER = loader._load_impl(Meter, _METER_FACTORY) + except TypeError: + # if we raised an exception trying to instantiate an + # abstract class, default to no-op tracer impl + _METER = DefaultMeter() del _METER_FACTORY return _METER diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index 3d37a58b6ae..4ecdffecb97 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -13,6 +13,8 @@ # limitations under the License. import unittest +from contextlib import contextmanager +from unittest import mock from opentelemetry import metrics @@ -90,3 +92,33 @@ def test_gauge_handle(self): def test_measure_handle(self): handle = metrics.MeasureHandle() handle.record(1) + + +@contextmanager +def patch_metrics_globals(meter=None, meter_factory=None): + """Mock metrics._METER and metrics._METER_FACTORY. + + This prevents previous changes to these values from affecting the code in + this scope, and prevents changes in this scope from leaking out and + affecting other tests. + """ + with mock.patch("opentelemetry.metrics._METER", meter): + with mock.patch("opentelemetry.metrics._METER_FACTORY", meter_factory): + yield + + +class TestGlobals(unittest.TestCase): + def test_meter_default_factory(self): + """Check that the default meter is a DefaultMeter.""" + with patch_metrics_globals(): + meter = metrics.meter() + self.assertIsInstance(meter, metrics.DefaultMeter) + # Check that we don't create a new instance on each call + self.assertIs(meter, metrics.meter()) + + def test_meter_custom_factory(self): + """Check that we use the provided factory for custom global meters.""" + mock_meter = mock.Mock(metrics.Meter) + with patch_metrics_globals(meter_factory=lambda _: mock_meter): + meter = metrics.meter() + self.assertIs(meter, mock_meter)