From bba1feaa3fc46e0f3432ba36ed1795e6d742ebed Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 18 Feb 2020 16:56:00 -0800 Subject: [PATCH 01/31] Named meters --- examples/metrics/record.py | 8 +- .../metrics_example.py | 50 ----------- .../src/opentelemetry/metrics/__init__.py | 82 ++++++++++++++----- .../tests/metrics/test_metrics.py | 77 +++++++---------- .../tests/test_implementation.py | 20 +++++ .../src/opentelemetry/sdk/metrics/__init__.py | 27 +++++- .../src/opentelemetry/sdk/trace/__init__.py | 44 +--------- .../src/opentelemetry/sdk/util.py | 41 ++++++++++ .../tests/metrics/test_metrics.py | 32 ++++---- .../tests/test_implementation.py | 7 +- 10 files changed, 207 insertions(+), 181 deletions(-) delete mode 100644 examples/opentelemetry-example-app/src/opentelemetry_example_app/metrics_example.py diff --git a/examples/metrics/record.py b/examples/metrics/record.py index be68c8083ff..af234600f50 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -19,13 +19,15 @@ import time from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, Meter +from opentelemetry.sdk.metrics import Counter, MeterSource from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController +# The preferred tracer implementation must be set, as the opentelemetry-api +# defines the interface with a no-op implementation. +metrics.set_preferred_meter_source_implementation(lambda _: MeterSource()) # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_implementation(lambda _: Meter()) -meter = metrics.meter() +meter = metrics.meter_source().get_meter(__name__) # exporter to export metrics to the console exporter = ConsoleMetricsExporter() # controller collects metrics created from meter and exports it via the diff --git a/examples/opentelemetry-example-app/src/opentelemetry_example_app/metrics_example.py b/examples/opentelemetry-example-app/src/opentelemetry_example_app/metrics_example.py deleted file mode 100644 index 2f423619021..00000000000 --- a/examples/opentelemetry-example-app/src/opentelemetry_example_app/metrics_example.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -""" -This module serves as an example for a simple application using metrics -""" - -from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, Meter -from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter -from opentelemetry.sdk.metrics.export.batcher import UngroupedBatcher -from opentelemetry.sdk.metrics.export.controller import PushController - -batcher = UngroupedBatcher(True) -metrics.set_preferred_meter_implementation(lambda _: Meter(batcher)) -meter = metrics.meter() -counter = meter.create_metric( - "available memory", - "available memory", - "bytes", - int, - Counter, - ("environment",), -) - -label_set = meter.get_label_set({"environment": "staging"}) - -# Direct metric usage -counter.add(25, label_set) - -# Handle usage -counter_handle = counter.get_handle(label_set) -counter_handle.add(100) - -# Record batch usage -meter.record_batch(label_set, [(counter, 50)]) - -exporter = ConsoleMetricsExporter() -controller = PushController(meter, exporter, 5) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 5045c38eed9..3618692402c 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -223,9 +223,49 @@ def record(self, value: ValueT, label_set: LabelSet) -> None: label_set: `LabelSet` to associate with the returned handle. """ +class MeterSource(abc.ABC): -MetricT = TypeVar("MetricT", Counter, Gauge, Measure) + @abc.abstractmethod + def get_meter( + self, + instrumenting_module_name: str, + instrumenting_library_version: str = "", + ) -> "Meter": + """Returns a `Meter` for use by the given instrumentation library. + + This function may return different `Meter` types (e.g. a no-op meter + vs. a functional meter). + + Args: + instrumenting_module_name: The name of the instrumenting module + (usually just ``__name__``). + + This should *not* be the name of the module that is + instrumented but the name of the module doing the instrumentation. + E.g., instead of ``"requests"``, use + ``"opentelemetry.ext.http_requests"``. + + instrumenting_library_version: Optional. The version string of the + instrumenting library. Usually this should be the same as + ``pkg_resources.get_distribution(instrumenting_library_name).version``. + """ + +class DefaultMeterSource(MeterSource): + """The default MeterSource, used when no implementation is available. + + All operations are no-op. + """ + def get_meter( + self, + instrumenting_module_name: str, + instrumenting_library_version: str = "", + ) -> "Meter": + # pylint:disable=no-self-use,unused-argument + return DefaultMeter() + + +MetricT = TypeVar("MetricT", Counter, Gauge, Measure) # pylint: disable=unused-argument class Meter(abc.ABC): @@ -322,45 +362,49 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": # Once https://github.com/python/mypy/issues/7092 is resolved, # the following type definition should be replaced with # from opentelemetry.util.loader import ImplementationFactory -ImplementationFactory = Callable[[Type[Meter]], Optional[Meter]] +ImplementationFactory = Callable[[Type[MeterSource]], Optional[MeterSource]] -_METER = None -_METER_FACTORY = None +_METER_SOURCE = None +_METER_SOURCE_FACTORY = None -def meter() -> Meter: - """Gets the current global :class:`~.Meter` object. +def meter_source() -> MeterSource: + """Gets the current global :class:`~.MeterSource` object. If there isn't one set yet, a default will be loaded. """ - global _METER, _METER_FACTORY # pylint:disable=global-statement + global _METER_SOURCE, _METER_SOURCE_FACTORY # pylint:disable=global-statement - if _METER is None: + if _METER_SOURCE is None: # pylint:disable=protected-access try: - _METER = loader._load_impl(Meter, _METER_FACTORY) # type: ignore + _METER_SOURCE = loader._load_impl( + MeterSource, _METER_SOURCE_FACTORY # type: ignore + ) except TypeError: # if we raised an exception trying to instantiate an # abstract class, default to no-op tracer impl - _METER = DefaultMeter() - del _METER_FACTORY + _METER_SOURCE = DefaultMeterSource() + del _METER_SOURCE_FACTORY - return _METER + return _METER_SOURCE -def set_preferred_meter_implementation(factory: ImplementationFactory) -> None: - """Set the factory to be used to create the meter. +def set_preferred_meter_source_implementation( + factory: ImplementationFactory +) -> None: + """Set the factory to be used to create the meter source. See :mod:`opentelemetry.util.loader` for details. This function may not be called after a meter is already loaded. Args: - factory: Callback that should create a new :class:`Meter` instance. + factory: Callback that should create a new :class:`MeterSource` instance. """ - global _METER, _METER_FACTORY # pylint:disable=global-statement + global _METER_SOURCE_FACTORY # pylint:disable=global-statement - if _METER: - raise RuntimeError("Meter already loaded.") + if _METER_SOURCE: + raise RuntimeError("MeterSource already loaded.") - _METER_FACTORY = factory + _METER_SOURCE_FACTORY = factory diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index 3ec0f81c718..0c0e1781bc9 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -20,24 +20,6 @@ # pylint: disable=no-self-use -class TestMeter(unittest.TestCase): - def setUp(self): - self.meter = metrics.DefaultMeter() - - def test_record_batch(self): - counter = metrics.Counter() - label_set = metrics.LabelSet() - self.meter.record_batch(label_set, ((counter, 1),)) - - def test_create_metric(self): - metric = self.meter.create_metric("", "", "", float, metrics.Counter) - self.assertIsInstance(metric, metrics.DefaultMetric) - - def test_get_label_set(self): - metric = self.meter.get_label_set({}) - self.assertIsInstance(metric, metrics.DefaultLabelSet) - - class TestMetrics(unittest.TestCase): def test_default(self): default = metrics.DefaultMetric() @@ -93,33 +75,32 @@ def test_measure_handle(self): handle = metrics.MeasureHandle() handle.record(1) - -@contextmanager -# type: ignore -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) +# @contextmanager +# # type: ignore +# 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) diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index c7d1d453a1c..5573c572531 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -25,6 +25,8 @@ class TestAPIOnlyImplementation(unittest.TestCase): https://github.com/open-telemetry/opentelemetry-python/issues/142 """ + # TRACER + def test_tracer(self): with self.assertRaises(TypeError): # pylint: disable=abstract-class-instantiated @@ -54,12 +56,30 @@ def test_default_span(self): self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) self.assertIs(span.is_recording_events(), False) + # METER + def test_meter(self): with self.assertRaises(TypeError): # pylint: disable=abstract-class-instantiated metrics.Meter() # type:ignore def test_default_meter(self): + meter_source = metrics.DefaultMeterSource() + meter = meter_source.get_meter(__name__) + self.assertIsInstance(meter, metrics.DefaultMeter) + + def test_record_batch(self): + meter = metrics.DefaultMeter() + counter = metrics.Counter() + label_set = metrics.LabelSet() + meter.record_batch(label_set, ((counter, 1),)) + + def test_create_metric(self): meter = metrics.DefaultMeter() metric = meter.create_metric("", "", "", float, metrics.Counter) self.assertIsInstance(metric, metrics.DefaultMetric) + + def test_get_label_set(self): + meter = metrics.DefaultMeter() + metric = meter.get_label_set({}) + self.assertIsInstance(metric, metrics.DefaultLabelSet) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 4c9231582c8..a6bbc97fc4e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -19,6 +19,7 @@ from opentelemetry import metrics as metrics_api from opentelemetry.sdk.metrics.export.aggregate import Aggregator from opentelemetry.sdk.metrics.export.batcher import Batcher, UngroupedBatcher +from opentelemetry.sdk.util import InstrumentationInfo from opentelemetry.util import time_ns logger = logging.getLogger(__name__) @@ -261,11 +262,17 @@ class Meter(metrics_api.Meter): """See `opentelemetry.metrics.Meter`. Args: + instrumentation_info: The `InstrumentationInfo` for this meter. batcher: The `Batcher` used for this meter. """ - def __init__(self, batcher: Batcher = UngroupedBatcher(True)): + def __init__( + self, + instrumentation_info: InstrumentationInfo, + batcher: Batcher + ): self.batcher = batcher + self.instrumentation_info = instrumentation_info self.metrics = set() def collect(self) -> None: @@ -328,3 +335,21 @@ def get_label_set(self, labels: Dict[str, str]): if len(labels) == 0: return EMPTY_LABEL_SET return LabelSet(labels=labels) + +class MeterSource(metrics_api.MeterSource): + + def get_meter( + self, + instrumenting_module_name: str, + instrumenting_library_version: str = "", + batcher: Batcher = UngroupedBatcher(True), + ) -> "metrics_api.Meter": + if not instrumenting_module_name: # Reject empty strings too. + instrumenting_module_name = "ERROR:MISSING MODULE NAME" + logger.error("get_meter called with missing module name.") + return Meter( + InstrumentationInfo( + instrumenting_module_name, instrumenting_library_version + ), + batcher, + ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 6d249e65080..f7c751d2e84 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -25,7 +25,7 @@ from opentelemetry import context as context_api from opentelemetry import trace as trace_api from opentelemetry.sdk import util -from opentelemetry.sdk.util import BoundedDict, BoundedList +from opentelemetry.sdk.util import BoundedDict, BoundedList, InstrumentationInfo from opentelemetry.trace import SpanContext, sampling from opentelemetry.trace.propagation import get_span_key from opentelemetry.trace.status import Status, StatusCanonicalCode @@ -152,7 +152,7 @@ def __init__( links: Sequence[trace_api.Link] = (), kind: trace_api.SpanKind = trace_api.SpanKind.INTERNAL, span_processor: SpanProcessor = SpanProcessor(), - instrumentation_info: "InstrumentationInfo" = None, + instrumentation_info: InstrumentationInfo = None, set_status_on_exception: bool = True, ) -> None: @@ -385,46 +385,6 @@ def generate_trace_id() -> int: return random.getrandbits(128) -class InstrumentationInfo: - """Immutable information about an instrumentation library module. - - See `TracerSource.get_tracer` for the meaning of the properties. - """ - - __slots__ = ("_name", "_version") - - def __init__(self, name: str, version: str): - self._name = name - self._version = version - - def __repr__(self): - return "{}({}, {})".format( - type(self).__name__, self._name, self._version - ) - - def __hash__(self): - return hash((self._name, self._version)) - - def __eq__(self, value): - return type(value) is type(self) and (self._name, self._version) == ( - value._name, - value._version, - ) - - def __lt__(self, value): - if type(value) is not type(self): - return NotImplemented - return (self._name, self._version) < (value._name, value._version) - - @property - def version(self) -> str: - return self._version - - @property - def name(self) -> str: - return self._name - - class Tracer(trace_api.Tracer): """See `opentelemetry.trace.Tracer`. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util.py b/opentelemetry-sdk/src/opentelemetry/sdk/util.py index 2265c29460b..87aef72d3c9 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util.py @@ -140,3 +140,44 @@ def from_map(cls, maxlen, mapping): # pylint: disable=protected-access bounded_dict._dict = mapping return bounded_dict + + +class InstrumentationInfo: + """Immutable information about an instrumentation library module. + + See `TracerSource.get_tracer` or `MeterSource.get_meter` for the meaning of + the properties. + """ + + __slots__ = ("_name", "_version") + + def __init__(self, name: str, version: str): + self._name = name + self._version = version + + def __repr__(self): + return "{}({}, {})".format( + type(self).__name__, self._name, self._version + ) + + def __hash__(self): + return hash((self._name, self._version)) + + def __eq__(self, value): + return type(value) is type(self) and (self._name, self._version) == ( + value._name, + value._version, + ) + + def __lt__(self, value): + if type(value) is not type(self): + return NotImplemented + return (self._name, self._version) < (value._name, value._version) + + @property + def version(self) -> str: + return self._version + + @property + def name(self) -> str: + return self._name diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index a887621b0cb..cdb4db9ddba 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -22,11 +22,11 @@ class TestMeter(unittest.TestCase): def test_extends_api(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) self.assertIsInstance(meter, metrics_api.Meter) def test_collect(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -41,14 +41,14 @@ def test_collect(self): self.assertTrue(batcher_mock.process.called) def test_collect_no_metrics(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock meter.collect() self.assertFalse(batcher_mock.process.called) def test_collect_disabled_metric(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -63,7 +63,7 @@ def test_collect_disabled_metric(self): self.assertFalse(batcher_mock.process.called) def test_record_batch(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) label_keys = ("key1",) counter = metrics.Counter( "name", "desc", "unit", float, meter, label_keys @@ -75,7 +75,7 @@ def test_record_batch(self): self.assertEqual(counter.get_handle(label_set).aggregator.current, 1.0) def test_record_batch_multiple(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) label_keys = ("key1", "key2", "key3") kvp = {"key1": "value1", "key2": "value2", "key3": "value3"} label_set = meter.get_label_set(kvp) @@ -94,7 +94,7 @@ def test_record_batch_multiple(self): self.assertEqual(measure.get_handle(label_set).aggregator.current, 3.0) def test_record_batch_exists(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) label_keys = ("key1",) kvp = {"key1": "value1"} label_set = meter.get_label_set(kvp) @@ -109,7 +109,7 @@ def test_record_batch_exists(self): self.assertEqual(handle.aggregator.current, 2.0) def test_create_metric(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) counter = meter.create_metric( "name", "desc", "unit", int, metrics.Counter, () ) @@ -118,7 +118,7 @@ def test_create_metric(self): self.assertEqual(counter.name, "name") def test_create_gauge(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) gauge = meter.create_metric( "name", "desc", "unit", float, metrics.Gauge, () ) @@ -127,7 +127,7 @@ def test_create_gauge(self): self.assertEqual(gauge.name, "name") def test_create_measure(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) measure = meter.create_metric( "name", "desc", "unit", float, metrics.Measure, () ) @@ -136,7 +136,7 @@ def test_create_measure(self): self.assertEqual(measure.name, "name") def test_get_label_set(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) kvp = {"environment": "staging", "a": "z"} label_set = meter.get_label_set(kvp) label_set2 = meter.get_label_set(kvp) @@ -144,7 +144,7 @@ def test_get_label_set(self): self.assertEqual(len(labels), 1) def test_get_label_set_empty(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) kvp = {} label_set = meter.get_label_set(kvp) self.assertEqual(label_set, metrics.EMPTY_LABEL_SET) @@ -152,7 +152,7 @@ def test_get_label_set_empty(self): class TestMetric(unittest.TestCase): def test_get_handle(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) metric_types = [metrics.Counter, metrics.Gauge, metrics.Measure] for _type in metric_types: metric = _type("name", "desc", "unit", int, meter, ("key",)) @@ -164,7 +164,7 @@ def test_get_handle(self): class TestCounter(unittest.TestCase): def test_add(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) metric = metrics.Counter("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -176,7 +176,7 @@ def test_add(self): class TestGauge(unittest.TestCase): def test_set(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) metric = metrics.Gauge("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -190,7 +190,7 @@ def test_set(self): class TestMeasure(unittest.TestCase): def test_record(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) metric = metrics.Measure("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) diff --git a/opentelemetry-sdk/tests/test_implementation.py b/opentelemetry-sdk/tests/test_implementation.py index d8d6bae1393..cea1d509c1f 100644 --- a/opentelemetry-sdk/tests/test_implementation.py +++ b/opentelemetry-sdk/tests/test_implementation.py @@ -14,7 +14,7 @@ import unittest -from opentelemetry.metrics import DefaultMetric +from opentelemetry.metrics import DefaultLabelSet, DefaultMeter, DefaultMetric from opentelemetry.sdk import metrics, trace from opentelemetry.trace import INVALID_SPAN, INVALID_SPAN_CONTEXT @@ -48,6 +48,9 @@ def test_span(self): self.assertIs(span.is_recording_events(), True) def test_meter(self): - meter = metrics.Meter() + meter = metrics.MeterSource().get_meter(__name__) metric = meter.create_metric("", "", "", float, metrics.Counter) + label_set = meter.get_label_set({'key1':'val1'}) + self.assertNotIsInstance(meter, DefaultMeter) self.assertNotIsInstance(metric, DefaultMetric) + self.assertNotIsInstance(label_set, DefaultLabelSet) From 712ccd35a74418aba80110562d87f47dbd4ef221 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 18 Feb 2020 16:59:13 -0800 Subject: [PATCH 02/31] Remove test --- .../tests/metrics/test_metrics.py | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index 0c0e1781bc9..dac0b9eba39 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -74,33 +74,3 @@ def test_gauge_handle(self): def test_measure_handle(self): handle = metrics.MeasureHandle() handle.record(1) - -# @contextmanager -# # type: ignore -# 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) From b50c2698c13a1b68a6d04378acf6680bbd21dd98 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 18 Feb 2020 17:09:43 -0800 Subject: [PATCH 03/31] fix comment --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3618692402c..a32f51fe9c0 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -383,7 +383,7 @@ def meter_source() -> MeterSource: ) except TypeError: # if we raised an exception trying to instantiate an - # abstract class, default to no-op tracer impl + # abstract class, default to no-op meter impl _METER_SOURCE = DefaultMeterSource() del _METER_SOURCE_FACTORY From 08b111743f9ec5b7f97677648074074aa2da803b Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 19 Feb 2020 12:42:53 -0800 Subject: [PATCH 04/31] Fix tests --- examples/metrics/simple_example.py | 6 +++--- .../src/opentelemetry/sdk/metrics/__init__.py | 2 +- .../tests/metrics/export/test_export.py | 17 +++++++++-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index 75da80b73ac..83d8f6e1e13 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -23,7 +23,7 @@ import time from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, Measure, Meter +from opentelemetry.sdk.metrics import Counter, Measure, MeterSource from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.batcher import UngroupedBatcher from opentelemetry.sdk.metrics.export.controller import PushController @@ -54,8 +54,8 @@ def usage(argv): # If a batcher is not provided, a default batcher is used # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_implementation(lambda _: Meter(batcher)) -meter = metrics.meter() +metrics.set_preferred_meter_source_implementation(lambda _: MeterSource()) +meter = metrics.meter_source().get_meter(__name__, batcher) # Exporter to export metrics to the console exporter = ConsoleMetricsExporter() diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index a6bbc97fc4e..9c348011556 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -341,8 +341,8 @@ class MeterSource(metrics_api.MeterSource): def get_meter( self, instrumenting_module_name: str, - instrumenting_library_version: str = "", batcher: Batcher = UngroupedBatcher(True), + instrumenting_library_version: str = "", ) -> "metrics_api.Meter": if not instrumenting_module_name: # Reject empty strings too. instrumenting_module_name = "ERROR:MISSING MODULE NAME" diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 5df6c6d08a0..ae8e5524a81 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -15,6 +15,7 @@ import unittest from unittest import mock +from opentelemetry import metrics as metrics_api from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import ( ConsoleMetricsExporter, @@ -32,7 +33,7 @@ class TestConsoleMetricsExporter(unittest.TestCase): # pylint: disable=no-self-use def test_export(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) exporter = ConsoleMetricsExporter() metric = metrics.Counter( "available memory", @@ -43,7 +44,7 @@ def test_export(self): ("environment",), ) kvp = {"environment": "staging"} - label_set = meter.get_label_set(kvp) + label_set = metrics.LabelSet(kvp) aggregator = CounterAggregator() record = MetricRecord(aggregator, label_set, metric) result = '{}(data="{}", label_set="{}", value={})'.format( @@ -69,7 +70,7 @@ def test_aggregator_for_counter(self): # TODO: Add other aggregator tests def test_checkpoint_set(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -97,7 +98,7 @@ def test_checkpoint_set_empty(self): self.assertEqual(len(records), 0) def test_finished_collection_stateless(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) batcher = UngroupedBatcher(False) aggregator = CounterAggregator() metric = metrics.Counter( @@ -117,7 +118,7 @@ def test_finished_collection_stateless(self): self.assertEqual(len(batcher._batch_map), 0) def test_finished_collection_stateful(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -138,7 +139,7 @@ def test_finished_collection_stateful(self): # TODO: Abstract the logic once other batchers implemented def test_ungrouped_batcher_process_exists(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() aggregator2 = CounterAggregator() @@ -167,7 +168,7 @@ def test_ungrouped_batcher_process_exists(self): ) def test_ungrouped_batcher_process_not_exists(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -194,7 +195,7 @@ def test_ungrouped_batcher_process_not_exists(self): ) def test_ungrouped_batcher_process_not_stateful(self): - meter = metrics.Meter() + meter = metrics_api.meter_source().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( From c92f837a7f3240b61978b0edfc11b39672c8bcbc Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 19 Feb 2020 14:17:19 -0800 Subject: [PATCH 05/31] address comments + fix lint --- README.md | 11 ++-- docs/opentelemetry.sdk.metrics.rst | 1 + docs/opentelemetry.sdk.trace.rst | 1 + ...opentelemetry.sdk.util.instrumentation.rst | 4 ++ .../tests/test_flask_integration.py | 5 +- .../context/threadlocal_context.py | 4 +- .../src/opentelemetry/metrics/__init__.py | 22 +++++++- .../src/opentelemetry/util/__init__.py | 13 +++++ .../tests/context/test_contextvars_context.py | 6 ++- .../tests/context/test_threadlocal_context.py | 6 ++- .../tests/test_implementation.py | 4 +- .../tests/trace/test_sampling.py | 4 +- .../src/opentelemetry/sdk/metrics/__init__.py | 11 ++-- .../src/opentelemetry/sdk/trace/__init__.py | 3 +- .../sdk/{util.py => util/__init__.py} | 42 --------------- .../opentelemetry/sdk/util/instrumentation.py | 53 +++++++++++++++++++ .../tests/metrics/export/test_export.py | 14 ++--- .../tests/metrics/test_implementation.py | 35 ++++++++++++ .../tests/{ => trace}/test_implementation.py | 13 +---- opentelemetry-sdk/tests/trace/test_trace.py | 8 +-- 20 files changed, 162 insertions(+), 98 deletions(-) create mode 100644 docs/opentelemetry.sdk.util.instrumentation.rst rename opentelemetry-sdk/src/opentelemetry/sdk/{util.py => util/__init__.py} (79%) create mode 100644 opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py create mode 100644 opentelemetry-sdk/tests/metrics/test_implementation.py rename opentelemetry-sdk/tests/{ => trace}/test_implementation.py (77%) diff --git a/README.md b/README.md index 97a76e1f0c7..53aff5cbe82 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,14 @@ with tracer.start_as_current_span('foo'): ```python from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, Meter +from opentelemetry.sdk.metrics import Counter, MeterSource from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter +from opentelemetry.sdk.metrics.export.controller import PushController -metrics.set_preferred_meter_implementation(lambda T: Meter()) -meter = metrics.meter() +metrics.set_preferred_meter_source_implementation(lambda _: MeterSource()) +meter = metrics.meter_source().get_meter(__name__) exporter = ConsoleMetricsExporter() +controller = PushController(meter, exporter, 5) counter = meter.create_metric( "available memory", @@ -89,9 +91,6 @@ counter = meter.create_metric( label_values = ("staging",) counter_handle = counter.get_handle(label_values) counter_handle.add(100) - -exporter.export([(counter, label_values)]) -exporter.shutdown() ``` See the [API documentation](https://open-telemetry.github.io/opentelemetry-python/) for more detail, and the [examples folder](./examples) for a more sample code. diff --git a/docs/opentelemetry.sdk.metrics.rst b/docs/opentelemetry.sdk.metrics.rst index ec8687dd2dc..88612046c8a 100644 --- a/docs/opentelemetry.sdk.metrics.rst +++ b/docs/opentelemetry.sdk.metrics.rst @@ -8,6 +8,7 @@ Submodules opentelemetry.sdk.metrics.export.aggregate opentelemetry.sdk.metrics.export.batcher + opentelemetry.sdk.util.instrumentation .. automodule:: opentelemetry.sdk.metrics :members: diff --git a/docs/opentelemetry.sdk.trace.rst b/docs/opentelemetry.sdk.trace.rst index 7bb3569fe63..1c0e9b6f61c 100644 --- a/docs/opentelemetry.sdk.trace.rst +++ b/docs/opentelemetry.sdk.trace.rst @@ -7,6 +7,7 @@ Submodules .. toctree:: opentelemetry.sdk.trace.export + opentelemetry.sdk.util.instrumentation .. automodule:: opentelemetry.sdk.trace :members: diff --git a/docs/opentelemetry.sdk.util.instrumentation.rst b/docs/opentelemetry.sdk.util.instrumentation.rst new file mode 100644 index 00000000000..a7d391bcee1 --- /dev/null +++ b/docs/opentelemetry.sdk.util.instrumentation.rst @@ -0,0 +1,4 @@ +opentelemetry.sdk.util.instrumentation +========================================== + +.. automodule:: opentelemetry.sdk.util.instrumentation diff --git a/ext/opentelemetry-ext-flask/tests/test_flask_integration.py b/ext/opentelemetry-ext-flask/tests/test_flask_integration.py index 9d2f2560118..b9454b94472 100644 --- a/ext/opentelemetry-ext-flask/tests/test_flask_integration.py +++ b/ext/opentelemetry-ext-flask/tests/test_flask_integration.py @@ -78,10 +78,7 @@ def assert_environ(): def test_simple(self): expected_attrs = expected_attributes( - { - "http.target": "/hello/123", - "http.route": "/hello/", - } + {"http.target": "/hello/123", "http.route": "/hello/"} ) resp = self.client.get("/hello/123") self.assertEqual(200, resp.status_code) diff --git a/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py b/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py index 899ab863262..62c19b53623 100644 --- a/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py +++ b/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py @@ -35,9 +35,7 @@ def set_current(self, context: Context) -> None: def get_current(self) -> Context: """See `opentelemetry.context.RuntimeContext.get_current`.""" if not hasattr(self._current_context, self._CONTEXT_KEY): - setattr( - self._current_context, self._CONTEXT_KEY, Context(), - ) + setattr(self._current_context, self._CONTEXT_KEY, Context()) context = getattr( self._current_context, self._CONTEXT_KEY ) # type: Context diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index a32f51fe9c0..3470b034585 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -27,10 +27,13 @@ """ import abc +import logging from typing import Callable, Dict, Optional, Sequence, Tuple, Type, TypeVar from opentelemetry.util import loader +logger = logging.getLogger(__name__) + ValueT = TypeVar("ValueT", int, float) @@ -223,8 +226,8 @@ def record(self, value: ValueT, label_set: LabelSet) -> None: label_set: `LabelSet` to associate with the returned handle. """ -class MeterSource(abc.ABC): +class MeterSource(abc.ABC): @abc.abstractmethod def get_meter( self, @@ -250,6 +253,7 @@ def get_meter( ``pkg_resources.get_distribution(instrumenting_library_name).version``. """ + class DefaultMeterSource(MeterSource): """The default MeterSource, used when no implementation is available. @@ -368,6 +372,18 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": _METER_SOURCE_FACTORY = None +def get_meter( + instrumenting_module_name: str, instrumenting_library_version: str = "" +) -> "Meter": + """Returns a `Meter` for use by the given instrumentation library. + This function is a convenience wrapper for + opentelemetry.metrics.meter_source().get_meter + """ + return meter_source().get_meter( + instrumenting_module_name, instrumenting_library_version + ) + + def meter_source() -> MeterSource: """Gets the current global :class:`~.MeterSource` object. @@ -384,6 +400,10 @@ def meter_source() -> MeterSource: except TypeError: # if we raised an exception trying to instantiate an # abstract class, default to no-op meter impl + logger.warning( + "Unable to instantiate MeterSource from meter source factory.", + exc_info=True, + ) _METER_SOURCE = DefaultMeterSource() del _METER_SOURCE_FACTORY diff --git a/opentelemetry-api/src/opentelemetry/util/__init__.py b/opentelemetry-api/src/opentelemetry/util/__init__.py index cbf36d4c05a..6743ac2333f 100644 --- a/opentelemetry-api/src/opentelemetry/util/__init__.py +++ b/opentelemetry-api/src/opentelemetry/util/__init__.py @@ -1,3 +1,16 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import time # Since we want API users to be able to provide timestamps, diff --git a/opentelemetry-api/tests/context/test_contextvars_context.py b/opentelemetry-api/tests/context/test_contextvars_context.py index ebc15d6d9a3..ca79e688425 100644 --- a/opentelemetry-api/tests/context/test_contextvars_context.py +++ b/opentelemetry-api/tests/context/test_contextvars_context.py @@ -38,7 +38,8 @@ def tearDown(self): context.set_current(self.previous_context) @patch( - "opentelemetry.context._RUNTIME_CONTEXT", ContextVarsRuntimeContext() # type: ignore + "opentelemetry.context._RUNTIME_CONTEXT", + ContextVarsRuntimeContext(), # type: ignore ) def test_context(self): self.assertIsNone(context.get_value("say")) @@ -56,7 +57,8 @@ def test_context(self): self.assertEqual(context.get_value("say", context=third), "bar") @patch( - "opentelemetry.context._RUNTIME_CONTEXT", ContextVarsRuntimeContext() # type: ignore + "opentelemetry.context._RUNTIME_CONTEXT", + ContextVarsRuntimeContext(), # type: ignore ) def test_set_value(self): first = context.set_value("a", "yyy") diff --git a/opentelemetry-api/tests/context/test_threadlocal_context.py b/opentelemetry-api/tests/context/test_threadlocal_context.py index aca6b69de72..c9ea0d49c1e 100644 --- a/opentelemetry-api/tests/context/test_threadlocal_context.py +++ b/opentelemetry-api/tests/context/test_threadlocal_context.py @@ -31,7 +31,8 @@ def tearDown(self): context.set_current(self.previous_context) @patch( - "opentelemetry.context._RUNTIME_CONTEXT", ThreadLocalRuntimeContext() # type: ignore + "opentelemetry.context._RUNTIME_CONTEXT", + ThreadLocalRuntimeContext(), # type: ignore ) def test_context(self): self.assertIsNone(context.get_value("say")) @@ -49,7 +50,8 @@ def test_context(self): self.assertEqual(context.get_value("say", context=third), "bar") @patch( - "opentelemetry.context._RUNTIME_CONTEXT", ThreadLocalRuntimeContext() # type: ignore + "opentelemetry.context._RUNTIME_CONTEXT", + ThreadLocalRuntimeContext(), # type: ignore ) def test_set_value(self): first = context.set_value("a", "yyy") diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 5573c572531..b26627135b5 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -81,5 +81,5 @@ def test_create_metric(self): def test_get_label_set(self): meter = metrics.DefaultMeter() - metric = meter.get_label_set({}) - self.assertIsInstance(metric, metrics.DefaultLabelSet) + label_set = meter.get_label_set({}) + self.assertIsInstance(label_set, metrics.DefaultLabelSet) diff --git a/opentelemetry-api/tests/trace/test_sampling.py b/opentelemetry-api/tests/trace/test_sampling.py index f04aecef45b..e9ecd19af77 100644 --- a/opentelemetry-api/tests/trace/test_sampling.py +++ b/opentelemetry-api/tests/trace/test_sampling.py @@ -235,6 +235,4 @@ def test_probability_sampler_limits(self): # Check that the higest effective sampling rate is actually lower than # the highest theoretical sampling rate. If this test fails the test # above is wrong. - self.assertLess( - almost_almost_always_on.bound, 0xFFFFFFFFFFFFFFFF, - ) + self.assertLess(almost_almost_always_on.bound, 0xFFFFFFFFFFFFFFFF) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 9c348011556..751358f6fc5 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -19,7 +19,7 @@ from opentelemetry import metrics as metrics_api from opentelemetry.sdk.metrics.export.aggregate import Aggregator from opentelemetry.sdk.metrics.export.batcher import Batcher, UngroupedBatcher -from opentelemetry.sdk.util import InstrumentationInfo +from opentelemetry.sdk.util.instrumentation import InstrumentationInfo from opentelemetry.util import time_ns logger = logging.getLogger(__name__) @@ -267,9 +267,7 @@ class Meter(metrics_api.Meter): """ def __init__( - self, - instrumentation_info: InstrumentationInfo, - batcher: Batcher + self, instrumentation_info: "InstrumentationInfo", batcher: Batcher ): self.batcher = batcher self.instrumentation_info = instrumentation_info @@ -336,8 +334,8 @@ def get_label_set(self, labels: Dict[str, str]): return EMPTY_LABEL_SET return LabelSet(labels=labels) + class MeterSource(metrics_api.MeterSource): - def get_meter( self, instrumenting_module_name: str, @@ -345,8 +343,7 @@ def get_meter( instrumenting_library_version: str = "", ) -> "metrics_api.Meter": if not instrumenting_module_name: # Reject empty strings too. - instrumenting_module_name = "ERROR:MISSING MODULE NAME" - logger.error("get_meter called with missing module name.") + raise ValueError("get_meter called with missing module name.") return Meter( InstrumentationInfo( instrumenting_module_name, instrumenting_library_version diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index f7c751d2e84..6c0b9cc9daf 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -25,7 +25,8 @@ from opentelemetry import context as context_api from opentelemetry import trace as trace_api from opentelemetry.sdk import util -from opentelemetry.sdk.util import BoundedDict, BoundedList, InstrumentationInfo +from opentelemetry.sdk.util import BoundedDict, BoundedList +from opentelemetry.sdk.util.instrumentation import InstrumentationInfo from opentelemetry.trace import SpanContext, sampling from opentelemetry.trace.propagation import get_span_key from opentelemetry.trace.status import Status, StatusCanonicalCode diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py similarity index 79% rename from opentelemetry-sdk/src/opentelemetry/sdk/util.py rename to opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py index 87aef72d3c9..009a0bcdd73 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py @@ -11,7 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - import datetime import threading from collections import OrderedDict, deque @@ -140,44 +139,3 @@ def from_map(cls, maxlen, mapping): # pylint: disable=protected-access bounded_dict._dict = mapping return bounded_dict - - -class InstrumentationInfo: - """Immutable information about an instrumentation library module. - - See `TracerSource.get_tracer` or `MeterSource.get_meter` for the meaning of - the properties. - """ - - __slots__ = ("_name", "_version") - - def __init__(self, name: str, version: str): - self._name = name - self._version = version - - def __repr__(self): - return "{}({}, {})".format( - type(self).__name__, self._name, self._version - ) - - def __hash__(self): - return hash((self._name, self._version)) - - def __eq__(self, value): - return type(value) is type(self) and (self._name, self._version) == ( - value._name, - value._version, - ) - - def __lt__(self, value): - if type(value) is not type(self): - return NotImplemented - return (self._name, self._version) < (value._name, value._version) - - @property - def version(self) -> str: - return self._version - - @property - def name(self) -> str: - return self._name diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py new file mode 100644 index 00000000000..d60f1e84d06 --- /dev/null +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py @@ -0,0 +1,53 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +class InstrumentationInfo: + """Immutable information about an instrumentation library module. + + See `opentelemetry.trace.TracerSource.get_tracer` or + `opentelemetry.metrics.MeterSource.get_meter` for the meaning of these + properties. + """ + + __slots__ = ("_name", "_version") + + def __init__(self, name: str, version: str): + self._name = name + self._version = version + + def __repr__(self): + return "{}({}, {})".format( + type(self).__name__, self._name, self._version + ) + + def __hash__(self): + return hash((self._name, self._version)) + + def __eq__(self, value): + return type(value) is type(self) and (self._name, self._version) == ( + value._name, + value._version, + ) + + def __lt__(self, value): + if type(value) is not type(self): + return NotImplemented + return (self._name, self._version) < (value._name, value._version) + + @property + def version(self) -> str: + return self._version + + @property + def name(self) -> str: + return self._name diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index ae8e5524a81..b78dfb81246 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -249,9 +249,7 @@ class TestMinMaxSumCountAggregator(unittest.TestCase): def test_update(self): mmsc = MinMaxSumCountAggregator() # test current values without any update - self.assertEqual( - mmsc.current, (None, None, None, 0), - ) + self.assertEqual(mmsc.current, (None, None, None, 0)) # call update with some values values = (3, 50, 3, 97) @@ -259,7 +257,7 @@ def test_update(self): mmsc.update(val) self.assertEqual( - mmsc.current, (min(values), max(values), sum(values), len(values)), + mmsc.current, (min(values), max(values), sum(values), len(values)) ) def test_checkpoint(self): @@ -267,9 +265,7 @@ def test_checkpoint(self): # take checkpoint wihtout any update mmsc.take_checkpoint() - self.assertEqual( - mmsc.checkpoint, (None, None, None, 0), - ) + self.assertEqual(mmsc.checkpoint, (None, None, None, 0)) # call update with some values values = (3, 50, 3, 97) @@ -282,9 +278,7 @@ def test_checkpoint(self): (min(values), max(values), sum(values), len(values)), ) - self.assertEqual( - mmsc.current, (None, None, None, 0), - ) + self.assertEqual(mmsc.current, (None, None, None, 0)) def test_merge(self): mmsc1 = MinMaxSumCountAggregator() diff --git a/opentelemetry-sdk/tests/metrics/test_implementation.py b/opentelemetry-sdk/tests/metrics/test_implementation.py new file mode 100644 index 00000000000..b3b7d5edf71 --- /dev/null +++ b/opentelemetry-sdk/tests/metrics/test_implementation.py @@ -0,0 +1,35 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from opentelemetry.metrics import DefaultLabelSet, DefaultMeter, DefaultMetric +from opentelemetry.sdk import metrics + + +class TestMeterImplementation(unittest.TestCase): + """ + This test is in place to ensure the SDK implementation of the API + is returning values that are valid. The same tests have been added + to the API with different expected results. See issue for more details: + https://github.com/open-telemetry/opentelemetry-python/issues/142 + """ + + def test_meter(self): + meter = metrics.MeterSource().get_meter(__name__) + metric = meter.create_metric("", "", "", float, metrics.Counter) + label_set = meter.get_label_set({"key1": "val1"}) + self.assertNotIsInstance(meter, DefaultMeter) + self.assertNotIsInstance(metric, DefaultMetric) + self.assertNotIsInstance(label_set, DefaultLabelSet) diff --git a/opentelemetry-sdk/tests/test_implementation.py b/opentelemetry-sdk/tests/trace/test_implementation.py similarity index 77% rename from opentelemetry-sdk/tests/test_implementation.py rename to opentelemetry-sdk/tests/trace/test_implementation.py index cea1d509c1f..ae7ee97bc34 100644 --- a/opentelemetry-sdk/tests/test_implementation.py +++ b/opentelemetry-sdk/tests/trace/test_implementation.py @@ -14,12 +14,11 @@ import unittest -from opentelemetry.metrics import DefaultLabelSet, DefaultMeter, DefaultMetric -from opentelemetry.sdk import metrics, trace +from opentelemetry.sdk import trace from opentelemetry.trace import INVALID_SPAN, INVALID_SPAN_CONTEXT -class TestSDKImplementation(unittest.TestCase): +class TestTracerImplementation(unittest.TestCase): """ This test is in place to ensure the SDK implementation of the API is returning values that are valid. The same tests have been added @@ -46,11 +45,3 @@ def test_span(self): span = trace.Span("name", INVALID_SPAN_CONTEXT) self.assertEqual(span.get_context(), INVALID_SPAN_CONTEXT) self.assertIs(span.is_recording_events(), True) - - def test_meter(self): - meter = metrics.MeterSource().get_meter(__name__) - metric = meter.create_metric("", "", "", float, metrics.Counter) - label_set = meter.get_label_set({'key1':'val1'}) - self.assertNotIsInstance(meter, DefaultMeter) - self.assertNotIsInstance(metric, DefaultMetric) - self.assertNotIsInstance(label_set, DefaultLabelSet) diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index a62f91a7e35..218e4685f64 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -20,6 +20,7 @@ from opentelemetry import trace as trace_api from opentelemetry.sdk import trace +from opentelemetry.sdk.util.instrumentation import InstrumentationInfo from opentelemetry.trace import sampling from opentelemetry.trace.status import StatusCanonicalCode from opentelemetry.util import time_ns @@ -153,11 +154,10 @@ def test_instrumentation_info(self): span1 = tracer1.start_span("s1") span2 = tracer2.start_span("s2") self.assertEqual( - span1.instrumentation_info, trace.InstrumentationInfo("instr1", "") + span1.instrumentation_info, InstrumentationInfo("instr1", "") ) self.assertEqual( - span2.instrumentation_info, - trace.InstrumentationInfo("instr2", "1.3b3"), + span2.instrumentation_info, InstrumentationInfo("instr2", "1.3b3") ) self.assertEqual(span2.instrumentation_info.version, "1.3b3") @@ -177,7 +177,7 @@ def test_invalid_instrumentation_info(self): tracer1.instrumentation_info, tracer2.instrumentation_info ) self.assertIsInstance( - tracer1.instrumentation_info, trace.InstrumentationInfo + tracer1.instrumentation_info, InstrumentationInfo ) span1 = tracer1.start_span("foo") self.assertTrue(span1.is_recording_events()) From 7b8b67dbc8010755c528cf28b1fba8af2d9d65bf Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 19 Feb 2020 14:45:22 -0800 Subject: [PATCH 06/31] Rename MeterSource to MeterProvider --- README.md | 4 +-- examples/metrics/record.py | 4 +-- examples/metrics/simple_example.py | 4 +-- .../src/opentelemetry/metrics/__init__.py | 24 +++++++------- .../tests/test_implementation.py | 2 +- .../src/opentelemetry/sdk/metrics/__init__.py | 2 +- .../opentelemetry/sdk/util/instrumentation.py | 2 +- .../tests/metrics/test_implementation.py | 2 +- .../tests/metrics/test_metrics.py | 32 +++++++++---------- 9 files changed, 39 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 53aff5cbe82..072e265d59f 100644 --- a/README.md +++ b/README.md @@ -70,11 +70,11 @@ with tracer.start_as_current_span('foo'): ```python from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, MeterSource +from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController -metrics.set_preferred_meter_source_implementation(lambda _: MeterSource()) +metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) meter = metrics.meter_source().get_meter(__name__) exporter = ConsoleMetricsExporter() controller = PushController(meter, exporter, 5) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index af234600f50..7254db87cb6 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -19,13 +19,13 @@ import time from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, MeterSource +from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController # The preferred tracer implementation must be set, as the opentelemetry-api # defines the interface with a no-op implementation. -metrics.set_preferred_meter_source_implementation(lambda _: MeterSource()) +metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) # Meter is responsible for creating and recording metrics meter = metrics.meter_source().get_meter(__name__) # exporter to export metrics to the console diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index 83d8f6e1e13..e187eab3c62 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -23,7 +23,7 @@ import time from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, Measure, MeterSource +from opentelemetry.sdk.metrics import Counter, Measure, MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.batcher import UngroupedBatcher from opentelemetry.sdk.metrics.export.controller import PushController @@ -54,7 +54,7 @@ def usage(argv): # If a batcher is not provided, a default batcher is used # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_source_implementation(lambda _: MeterSource()) +metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) meter = metrics.meter_source().get_meter(__name__, batcher) # Exporter to export metrics to the console diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3470b034585..8d93e3b9216 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -227,7 +227,7 @@ def record(self, value: ValueT, label_set: LabelSet) -> None: """ -class MeterSource(abc.ABC): +class MeterProvider(abc.ABC): @abc.abstractmethod def get_meter( self, @@ -254,8 +254,8 @@ def get_meter( """ -class DefaultMeterSource(MeterSource): - """The default MeterSource, used when no implementation is available. +class DefaultMeterProvider(MeterProvider): + """The default MeterProvider, used when no implementation is available. All operations are no-op. """ @@ -366,7 +366,9 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": # Once https://github.com/python/mypy/issues/7092 is resolved, # the following type definition should be replaced with # from opentelemetry.util.loader import ImplementationFactory -ImplementationFactory = Callable[[Type[MeterSource]], Optional[MeterSource]] +ImplementationFactory = Callable[ + [Type[MeterProvider]], Optional[MeterProvider] +] _METER_SOURCE = None _METER_SOURCE_FACTORY = None @@ -384,8 +386,8 @@ def get_meter( ) -def meter_source() -> MeterSource: - """Gets the current global :class:`~.MeterSource` object. +def meter_source() -> MeterProvider: + """Gets the current global :class:`~.MeterProvider` object. If there isn't one set yet, a default will be loaded. """ @@ -395,16 +397,16 @@ def meter_source() -> MeterSource: # pylint:disable=protected-access try: _METER_SOURCE = loader._load_impl( - MeterSource, _METER_SOURCE_FACTORY # type: ignore + MeterProvider, _METER_SOURCE_FACTORY # type: ignore ) except TypeError: # if we raised an exception trying to instantiate an # abstract class, default to no-op meter impl logger.warning( - "Unable to instantiate MeterSource from meter source factory.", + "Unable to instantiate MeterProvider from meter source factory.", exc_info=True, ) - _METER_SOURCE = DefaultMeterSource() + _METER_SOURCE = DefaultMeterProvider() del _METER_SOURCE_FACTORY return _METER_SOURCE @@ -420,11 +422,11 @@ def set_preferred_meter_source_implementation( This function may not be called after a meter is already loaded. Args: - factory: Callback that should create a new :class:`MeterSource` instance. + factory: Callback that should create a new :class:`MeterProvider` instance. """ global _METER_SOURCE_FACTORY # pylint:disable=global-statement if _METER_SOURCE: - raise RuntimeError("MeterSource already loaded.") + raise RuntimeError("MeterProvider already loaded.") _METER_SOURCE_FACTORY = factory diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index b26627135b5..3668ab25d3c 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -64,7 +64,7 @@ def test_meter(self): metrics.Meter() # type:ignore def test_default_meter(self): - meter_source = metrics.DefaultMeterSource() + meter_source = metrics.DefaultMeterProvider() meter = meter_source.get_meter(__name__) self.assertIsInstance(meter, metrics.DefaultMeter) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 751358f6fc5..c1475f13bda 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -335,7 +335,7 @@ def get_label_set(self, labels: Dict[str, str]): return LabelSet(labels=labels) -class MeterSource(metrics_api.MeterSource): +class MeterProvider(metrics_api.MeterProvider): def get_meter( self, instrumenting_module_name: str, diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py index d60f1e84d06..8ba9d73de37 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py @@ -15,7 +15,7 @@ class InstrumentationInfo: """Immutable information about an instrumentation library module. See `opentelemetry.trace.TracerSource.get_tracer` or - `opentelemetry.metrics.MeterSource.get_meter` for the meaning of these + `opentelemetry.metrics.MeterProvider.get_meter` for the meaning of these properties. """ diff --git a/opentelemetry-sdk/tests/metrics/test_implementation.py b/opentelemetry-sdk/tests/metrics/test_implementation.py index b3b7d5edf71..80c10d72676 100644 --- a/opentelemetry-sdk/tests/metrics/test_implementation.py +++ b/opentelemetry-sdk/tests/metrics/test_implementation.py @@ -27,7 +27,7 @@ class TestMeterImplementation(unittest.TestCase): """ def test_meter(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = meter.create_metric("", "", "", float, metrics.Counter) label_set = meter.get_label_set({"key1": "val1"}) self.assertNotIsInstance(meter, DefaultMeter) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index 0582a01e909..df4ddd1a436 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -22,11 +22,11 @@ class TestMeter(unittest.TestCase): def test_extends_api(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) self.assertIsInstance(meter, metrics_api.Meter) def test_collect(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -41,14 +41,14 @@ def test_collect(self): self.assertTrue(batcher_mock.process.called) def test_collect_no_metrics(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock meter.collect() self.assertFalse(batcher_mock.process.called) def test_collect_disabled_metric(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -63,7 +63,7 @@ def test_collect_disabled_metric(self): self.assertFalse(batcher_mock.process.called) def test_record_batch(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) label_keys = ("key1",) counter = metrics.Counter( "name", "desc", "unit", float, meter, label_keys @@ -75,7 +75,7 @@ def test_record_batch(self): self.assertEqual(counter.get_handle(label_set).aggregator.current, 1.0) def test_record_batch_multiple(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) label_keys = ("key1", "key2", "key3") kvp = {"key1": "value1", "key2": "value2", "key3": "value3"} label_set = meter.get_label_set(kvp) @@ -96,7 +96,7 @@ def test_record_batch_multiple(self): ) def test_record_batch_exists(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) label_keys = ("key1",) kvp = {"key1": "value1"} label_set = meter.get_label_set(kvp) @@ -111,7 +111,7 @@ def test_record_batch_exists(self): self.assertEqual(handle.aggregator.current, 2.0) def test_create_metric(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) counter = meter.create_metric( "name", "desc", "unit", int, metrics.Counter, () ) @@ -120,7 +120,7 @@ def test_create_metric(self): self.assertEqual(counter.name, "name") def test_create_gauge(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) gauge = meter.create_metric( "name", "desc", "unit", float, metrics.Gauge, () ) @@ -129,7 +129,7 @@ def test_create_gauge(self): self.assertEqual(gauge.name, "name") def test_create_measure(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) measure = meter.create_metric( "name", "desc", "unit", float, metrics.Measure, () ) @@ -138,7 +138,7 @@ def test_create_measure(self): self.assertEqual(measure.name, "name") def test_get_label_set(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) kvp = {"environment": "staging", "a": "z"} label_set = meter.get_label_set(kvp) label_set2 = meter.get_label_set(kvp) @@ -146,7 +146,7 @@ def test_get_label_set(self): self.assertEqual(len(labels), 1) def test_get_label_set_empty(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) kvp = {} label_set = meter.get_label_set(kvp) self.assertEqual(label_set, metrics.EMPTY_LABEL_SET) @@ -154,7 +154,7 @@ def test_get_label_set_empty(self): class TestMetric(unittest.TestCase): def test_get_handle(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric_types = [metrics.Counter, metrics.Gauge, metrics.Measure] for _type in metric_types: metric = _type("name", "desc", "unit", int, meter, ("key",)) @@ -166,7 +166,7 @@ def test_get_handle(self): class TestCounter(unittest.TestCase): def test_add(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Counter("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -178,7 +178,7 @@ def test_add(self): class TestGauge(unittest.TestCase): def test_set(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Gauge("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -192,7 +192,7 @@ def test_set(self): class TestMeasure(unittest.TestCase): def test_record(self): - meter = metrics.MeterSource().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Measure("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) From 63824f31e2d2d4685579d931b704b40db39b7697 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 19 Feb 2020 15:13:09 -0800 Subject: [PATCH 07/31] black --- tox.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 5a69ca62b6a..e3982859228 100644 --- a/tox.ini +++ b/tox.ini @@ -120,7 +120,8 @@ commands_pre = python scripts/eachdist.py install --editable commands = - python scripts/eachdist.py lint --check-only + ; python scripts/eachdist.py lint --check-only + python black . [testenv:docs] deps = From 16e728b21e92012dc0c1f6d9aad565f1d74e8e97 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 19 Feb 2020 15:30:34 -0800 Subject: [PATCH 08/31] black --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index e3982859228..2ba29abc85f 100644 --- a/tox.ini +++ b/tox.ini @@ -121,7 +121,7 @@ commands_pre = commands = ; python scripts/eachdist.py lint --check-only - python black . + black . [testenv:docs] deps = From 7733a872a20a4a9bfc33bfb28ee75a0da8b32eb6 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 19 Feb 2020 17:05:02 -0800 Subject: [PATCH 09/31] remove black --- tox.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 2ba29abc85f..5a69ca62b6a 100644 --- a/tox.ini +++ b/tox.ini @@ -120,8 +120,7 @@ commands_pre = python scripts/eachdist.py install --editable commands = - ; python scripts/eachdist.py lint --check-only - black . + python scripts/eachdist.py lint --check-only [testenv:docs] deps = From b436c623d9aadf9d3b60dc1021fde35ff3dc7f6b Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 20 Feb 2020 10:21:31 -0800 Subject: [PATCH 10/31] fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 8d93e3b9216..8716429ca46 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -413,7 +413,7 @@ def meter_source() -> MeterProvider: def set_preferred_meter_source_implementation( - factory: ImplementationFactory + factory: ImplementationFactory, ) -> None: """Set the factory to be used to create the meter source. From d6c97f049056b4ae182508e8aa74b41af7ff7ec3 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 20 Feb 2020 11:41:31 -0800 Subject: [PATCH 11/31] fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 1 + opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 8716429ca46..db5cc965895 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -271,6 +271,7 @@ def get_meter( MetricT = TypeVar("MetricT", Counter, Gauge, Measure) + # pylint: disable=unused-argument class Meter(abc.ABC): """An interface to allow the recording of metrics. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py index 8ba9d73de37..213187946f6 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py @@ -11,6 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + + class InstrumentationInfo: """Immutable information about an instrumentation library module. From a2f2e0f00fee5909d826228da6f9a0a002681155 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 20 Feb 2020 12:39:06 -0800 Subject: [PATCH 12/31] fix lint --- opentelemetry-api/tests/metrics/test_metrics.py | 2 -- opentelemetry-api/tests/test_implementation.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index dac0b9eba39..2d63083d6ce 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -13,8 +13,6 @@ # limitations under the License. import unittest -from contextlib import contextmanager -from unittest import mock from opentelemetry import metrics diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 3668ab25d3c..2ff978e4933 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -72,6 +72,7 @@ def test_record_batch(self): meter = metrics.DefaultMeter() counter = metrics.Counter() label_set = metrics.LabelSet() + # pylint: disable=no-self-use meter.record_batch(label_set, ((counter, 1),)) def test_create_metric(self): From ec9c673e632fa6e48bd27588f59f2eaa9d3bd2bd Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 25 Feb 2020 12:27:05 -0800 Subject: [PATCH 13/31] Merge --- opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py index 213187946f6..e518dd14cd4 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py @@ -16,7 +16,7 @@ class InstrumentationInfo: """Immutable information about an instrumentation library module. - See `opentelemetry.trace.TracerSource.get_tracer` or + See `opentelemetry.trace.TracerProvider.get_tracer` or `opentelemetry.metrics.MeterProvider.get_meter` for the meaning of these properties. """ From 7ebd43844f1cc931b5efbcb0efb63846851f0639 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 25 Feb 2020 12:55:30 -0800 Subject: [PATCH 14/31] Rename to MeterProvider, remove Batcher from constructor --- examples/metrics/record.py | 4 +-- examples/metrics/simple_example.py | 20 ++++++-------- .../tests/test_prometheus_exporter.py | 6 ++--- .../src/opentelemetry/metrics/__init__.py | 26 +++++++++++++------ .../src/opentelemetry/sdk/metrics/__init__.py | 11 ++++---- .../tests/metrics/export/test_export.py | 14 +++++----- 6 files changed, 44 insertions(+), 37 deletions(-) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index 7254db87cb6..a641599908d 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -25,9 +25,9 @@ # The preferred tracer implementation must be set, as the opentelemetry-api # defines the interface with a no-op implementation. -metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) +metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) # Meter is responsible for creating and recording metrics -meter = metrics.meter_source().get_meter(__name__) +meter = metrics.meter_provider().get_meter(__name__) # exporter to export metrics to the console exporter = ConsoleMetricsExporter() # controller collects metrics created from meter and exports it via the diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index e187eab3c62..16098cf6ef7 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -25,7 +25,6 @@ from opentelemetry import metrics from opentelemetry.sdk.metrics import Counter, Measure, MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter -from opentelemetry.sdk.metrics.export.batcher import UngroupedBatcher from opentelemetry.sdk.metrics.export.controller import PushController batcher_mode = "stateful" @@ -44,18 +43,15 @@ def usage(argv): usage(sys.argv) sys.exit(1) -# Batcher used to collect all created metrics from meter ready for exporting -# Pass in True/False to indicate whether the batcher is stateful. -# True indicates the batcher computes checkpoints from over the process -# lifetime. -# False indicates the batcher computes checkpoints which describe the updates -# of a single collection period (deltas) -batcher = UngroupedBatcher(batcher_mode == "stateful") - -# If a batcher is not provided, a default batcher is used # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) -meter = metrics.meter_source().get_meter(__name__, batcher) +metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) + +# Meter's namespace corresponds to the string passed as the first argument Pass +# in True/False to indicate whether the batcher is stateful. True indicates the +# batcher computes checkpoints from over the process lifetime. False indicates +# the batcher computes checkpoints which describe the updates of a single +# collection period (deltas) +meter = metrics.meter_provider().get_meter(__name__, batcher_mode == "stateful") # Exporter to export metrics to the console exporter = ConsoleMetricsExporter() diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index 94fea96c5b5..f6883475386 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -28,7 +28,7 @@ class TestPrometheusMetricExporter(unittest.TestCase): def setUp(self): - self._meter = metrics.Meter() + self._meter = metrics.MeterProvider().get_meter(__name__) self._test_metric = self._meter.create_metric( "testname", "testdesc", @@ -74,7 +74,7 @@ def test_export(self): self.assertIs(result, MetricsExportResult.SUCCESS) def test_counter_to_prometheus(self): - meter = metrics.Meter() + meter = metrics.MeterProvider().get_meter(__name__) metric = meter.create_metric( "test@name", "testdesc", @@ -111,7 +111,7 @@ def test_counter_to_prometheus(self): def test_invalid_metric(self): - meter = metrics.Meter() + meter = metrics.MeterProvider().get_meter(__name__) metric = meter.create_metric( "tesname", "testdesc", "unit", int, TestMetric ) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index db5cc965895..499283ea65a 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -232,6 +232,7 @@ class MeterProvider(abc.ABC): def get_meter( self, instrumenting_module_name: str, + stateful: bool = True, instrumenting_library_version: str = "", ) -> "Meter": """Returns a `Meter` for use by the given instrumentation library. @@ -248,6 +249,12 @@ def get_meter( E.g., instead of ``"requests"``, use ``"opentelemetry.ext.http_requests"``. + stateful: True/False to indicate whether the meter will be + stateful. True indicates the meter computes checkpoints + from over the process lifetime. False indicates the meter + computes checkpoints which describe the updates of a single + collection period (deltas). + instrumenting_library_version: Optional. The version string of the instrumenting library. Usually this should be the same as ``pkg_resources.get_distribution(instrumenting_library_name).version``. @@ -263,6 +270,7 @@ class DefaultMeterProvider(MeterProvider): def get_meter( self, instrumenting_module_name: str, + stateful: bool = True, instrumenting_library_version: str = "", ) -> "Meter": # pylint:disable=no-self-use,unused-argument @@ -376,18 +384,20 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": def get_meter( - instrumenting_module_name: str, instrumenting_library_version: str = "" + instrumenting_module_name: str, + stateful = True, + instrumenting_library_version: str = "", ) -> "Meter": """Returns a `Meter` for use by the given instrumentation library. This function is a convenience wrapper for - opentelemetry.metrics.meter_source().get_meter + opentelemetry.metrics.meter_provider().get_meter """ - return meter_source().get_meter( - instrumenting_module_name, instrumenting_library_version + return meter_provider().get_meter( + instrumenting_module_name, stateful, instrumenting_library_version ) -def meter_source() -> MeterProvider: +def meter_provider() -> MeterProvider: """Gets the current global :class:`~.MeterProvider` object. If there isn't one set yet, a default will be loaded. @@ -404,7 +414,7 @@ def meter_source() -> MeterProvider: # if we raised an exception trying to instantiate an # abstract class, default to no-op meter impl logger.warning( - "Unable to instantiate MeterProvider from meter source factory.", + "Unable to instantiate MeterProvider from meter provider factory.", exc_info=True, ) _METER_SOURCE = DefaultMeterProvider() @@ -413,10 +423,10 @@ def meter_source() -> MeterProvider: return _METER_SOURCE -def set_preferred_meter_source_implementation( +def set_preferred_meter_provider_implementation( factory: ImplementationFactory, ) -> None: - """Set the factory to be used to create the meter source. + """Set the factory to be used to create the meter provider. See :mod:`opentelemetry.util.loader` for details. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index c1475f13bda..ada14872b3b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -263,15 +263,16 @@ class Meter(metrics_api.Meter): Args: instrumentation_info: The `InstrumentationInfo` for this meter. - batcher: The `Batcher` used for this meter. """ def __init__( - self, instrumentation_info: "InstrumentationInfo", batcher: Batcher + self, + instrumentation_info: "InstrumentationInfo", + stateful: bool, ): - self.batcher = batcher self.instrumentation_info = instrumentation_info self.metrics = set() + self.batcher = UngroupedBatcher(stateful) def collect(self) -> None: """Collects all the metrics created with this `Meter` for export. @@ -339,7 +340,7 @@ class MeterProvider(metrics_api.MeterProvider): def get_meter( self, instrumenting_module_name: str, - batcher: Batcher = UngroupedBatcher(True), + stateful = True, instrumenting_library_version: str = "", ) -> "metrics_api.Meter": if not instrumenting_module_name: # Reject empty strings too. @@ -348,5 +349,5 @@ def get_meter( InstrumentationInfo( instrumenting_module_name, instrumenting_library_version ), - batcher, + stateful = stateful ) diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index b78dfb81246..1c1062bedcb 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -33,7 +33,7 @@ class TestConsoleMetricsExporter(unittest.TestCase): # pylint: disable=no-self-use def test_export(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) exporter = ConsoleMetricsExporter() metric = metrics.Counter( "available memory", @@ -70,7 +70,7 @@ def test_aggregator_for_counter(self): # TODO: Add other aggregator tests def test_checkpoint_set(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -98,7 +98,7 @@ def test_checkpoint_set_empty(self): self.assertEqual(len(records), 0) def test_finished_collection_stateless(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(False) aggregator = CounterAggregator() metric = metrics.Counter( @@ -118,7 +118,7 @@ def test_finished_collection_stateless(self): self.assertEqual(len(batcher._batch_map), 0) def test_finished_collection_stateful(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -139,7 +139,7 @@ def test_finished_collection_stateful(self): # TODO: Abstract the logic once other batchers implemented def test_ungrouped_batcher_process_exists(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() aggregator2 = CounterAggregator() @@ -168,7 +168,7 @@ def test_ungrouped_batcher_process_exists(self): ) def test_ungrouped_batcher_process_not_exists(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -195,7 +195,7 @@ def test_ungrouped_batcher_process_not_exists(self): ) def test_ungrouped_batcher_process_not_stateful(self): - meter = metrics_api.meter_source().get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( From 27d75ba6c5e7d2e8575e44ea11e3b1d689d83f6a Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 25 Feb 2020 13:23:32 -0800 Subject: [PATCH 15/31] fix mypy --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 499283ea65a..0a816878ea0 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -385,7 +385,7 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": def get_meter( instrumenting_module_name: str, - stateful = True, + stateful: bool = True, instrumenting_library_version: str = "", ) -> "Meter": """Returns a `Meter` for use by the given instrumentation library. From 08095b63aebd5d99f1b166c1d90a49a594e2601b Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 25 Feb 2020 15:07:39 -0800 Subject: [PATCH 16/31] black --- examples/metrics/simple_example.py | 4 +++- .../src/opentelemetry/sdk/metrics/__init__.py | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index 16098cf6ef7..0021d9478d5 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -51,7 +51,9 @@ def usage(argv): # batcher computes checkpoints from over the process lifetime. False indicates # the batcher computes checkpoints which describe the updates of a single # collection period (deltas) -meter = metrics.meter_provider().get_meter(__name__, batcher_mode == "stateful") +meter = metrics.meter_provider().get_meter( + __name__, batcher_mode == "stateful" +) # Exporter to export metrics to the console exporter = ConsoleMetricsExporter() diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index ada14872b3b..7aec35d9891 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -266,9 +266,7 @@ class Meter(metrics_api.Meter): """ def __init__( - self, - instrumentation_info: "InstrumentationInfo", - stateful: bool, + self, instrumentation_info: "InstrumentationInfo", stateful: bool, ): self.instrumentation_info = instrumentation_info self.metrics = set() @@ -340,7 +338,7 @@ class MeterProvider(metrics_api.MeterProvider): def get_meter( self, instrumenting_module_name: str, - stateful = True, + stateful=True, instrumenting_library_version: str = "", ) -> "metrics_api.Meter": if not instrumenting_module_name: # Reject empty strings too. @@ -349,5 +347,5 @@ def get_meter( InstrumentationInfo( instrumenting_module_name, instrumenting_library_version ), - stateful = stateful + stateful=stateful, ) From 6a743c7b96790dcebf217d70a5513bc1f259ba33 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 25 Feb 2020 15:38:33 -0800 Subject: [PATCH 17/31] Black --- tox.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index be7f1db9f73..8899c8f53ce 100644 --- a/tox.ini +++ b/tox.ini @@ -187,7 +187,8 @@ commands_pre = python scripts/eachdist.py install --editable commands = - python scripts/eachdist.py lint --check-only + ; python scripts/eachdist.py lint --check-only + black . [testenv:docs] deps = From e226eda1178c5b482f824d10be47d980195b902e Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 00:28:17 -0800 Subject: [PATCH 18/31] address comments --- .../tests/metrics/export/test_export.py | 14 ++++---- .../tests/metrics/test_implementation.py | 3 +- .../tests/metrics/test_metrics.py | 32 +++++++++---------- tox.ini | 3 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 1c1062bedcb..458263e0d42 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -33,7 +33,7 @@ class TestConsoleMetricsExporter(unittest.TestCase): # pylint: disable=no-self-use def test_export(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) exporter = ConsoleMetricsExporter() metric = metrics.Counter( "available memory", @@ -70,7 +70,7 @@ def test_aggregator_for_counter(self): # TODO: Add other aggregator tests def test_checkpoint_set(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -98,7 +98,7 @@ def test_checkpoint_set_empty(self): self.assertEqual(len(records), 0) def test_finished_collection_stateless(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher = UngroupedBatcher(False) aggregator = CounterAggregator() metric = metrics.Counter( @@ -118,7 +118,7 @@ def test_finished_collection_stateless(self): self.assertEqual(len(batcher._batch_map), 0) def test_finished_collection_stateful(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -139,7 +139,7 @@ def test_finished_collection_stateful(self): # TODO: Abstract the logic once other batchers implemented def test_ungrouped_batcher_process_exists(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() aggregator2 = CounterAggregator() @@ -168,7 +168,7 @@ def test_ungrouped_batcher_process_exists(self): ) def test_ungrouped_batcher_process_not_exists(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -195,7 +195,7 @@ def test_ungrouped_batcher_process_not_exists(self): ) def test_ungrouped_batcher_process_not_stateful(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( diff --git a/opentelemetry-sdk/tests/metrics/test_implementation.py b/opentelemetry-sdk/tests/metrics/test_implementation.py index 80c10d72676..85cc90036c8 100644 --- a/opentelemetry-sdk/tests/metrics/test_implementation.py +++ b/opentelemetry-sdk/tests/metrics/test_implementation.py @@ -14,6 +14,7 @@ import unittest +from opentelemetry import metrics as metrics_api from opentelemetry.metrics import DefaultLabelSet, DefaultMeter, DefaultMetric from opentelemetry.sdk import metrics @@ -27,7 +28,7 @@ class TestMeterImplementation(unittest.TestCase): """ def test_meter(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric = meter.create_metric("", "", "", float, metrics.Counter) label_set = meter.get_label_set({"key1": "val1"}) self.assertNotIsInstance(meter, DefaultMeter) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index df4ddd1a436..74019280786 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -22,11 +22,11 @@ class TestMeter(unittest.TestCase): def test_extends_api(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) self.assertIsInstance(meter, metrics_api.Meter) def test_collect(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -41,14 +41,14 @@ def test_collect(self): self.assertTrue(batcher_mock.process.called) def test_collect_no_metrics(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock meter.collect() self.assertFalse(batcher_mock.process.called) def test_collect_disabled_metric(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -63,7 +63,7 @@ def test_collect_disabled_metric(self): self.assertFalse(batcher_mock.process.called) def test_record_batch(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) label_keys = ("key1",) counter = metrics.Counter( "name", "desc", "unit", float, meter, label_keys @@ -75,7 +75,7 @@ def test_record_batch(self): self.assertEqual(counter.get_handle(label_set).aggregator.current, 1.0) def test_record_batch_multiple(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) label_keys = ("key1", "key2", "key3") kvp = {"key1": "value1", "key2": "value2", "key3": "value3"} label_set = meter.get_label_set(kvp) @@ -96,7 +96,7 @@ def test_record_batch_multiple(self): ) def test_record_batch_exists(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) label_keys = ("key1",) kvp = {"key1": "value1"} label_set = meter.get_label_set(kvp) @@ -111,7 +111,7 @@ def test_record_batch_exists(self): self.assertEqual(handle.aggregator.current, 2.0) def test_create_metric(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) counter = meter.create_metric( "name", "desc", "unit", int, metrics.Counter, () ) @@ -120,7 +120,7 @@ def test_create_metric(self): self.assertEqual(counter.name, "name") def test_create_gauge(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) gauge = meter.create_metric( "name", "desc", "unit", float, metrics.Gauge, () ) @@ -129,7 +129,7 @@ def test_create_gauge(self): self.assertEqual(gauge.name, "name") def test_create_measure(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) measure = meter.create_metric( "name", "desc", "unit", float, metrics.Measure, () ) @@ -138,7 +138,7 @@ def test_create_measure(self): self.assertEqual(measure.name, "name") def test_get_label_set(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) kvp = {"environment": "staging", "a": "z"} label_set = meter.get_label_set(kvp) label_set2 = meter.get_label_set(kvp) @@ -146,7 +146,7 @@ def test_get_label_set(self): self.assertEqual(len(labels), 1) def test_get_label_set_empty(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) kvp = {} label_set = meter.get_label_set(kvp) self.assertEqual(label_set, metrics.EMPTY_LABEL_SET) @@ -154,7 +154,7 @@ def test_get_label_set_empty(self): class TestMetric(unittest.TestCase): def test_get_handle(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric_types = [metrics.Counter, metrics.Gauge, metrics.Measure] for _type in metric_types: metric = _type("name", "desc", "unit", int, meter, ("key",)) @@ -166,7 +166,7 @@ def test_get_handle(self): class TestCounter(unittest.TestCase): def test_add(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric = metrics.Counter("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -178,7 +178,7 @@ def test_add(self): class TestGauge(unittest.TestCase): def test_set(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric = metrics.Gauge("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -192,7 +192,7 @@ def test_set(self): class TestMeasure(unittest.TestCase): def test_record(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric = metrics.Measure("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) diff --git a/tox.ini b/tox.ini index 8899c8f53ce..be7f1db9f73 100644 --- a/tox.ini +++ b/tox.ini @@ -187,8 +187,7 @@ commands_pre = python scripts/eachdist.py install --editable commands = - ; python scripts/eachdist.py lint --check-only - black . + python scripts/eachdist.py lint --check-only [testenv:docs] deps = From c7432ef8cada5d745e0d4e1ffe6a2633df3c99d9 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 00:31:58 -0800 Subject: [PATCH 19/31] update tests --- README.md | 2 +- examples/metrics/record.py | 2 +- examples/metrics/simple_example.py | 2 +- .../tests/test_prometheus_exporter.py | 7 ++++--- opentelemetry-api/tests/test_implementation.py | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0fca55298ce..3dae1136e67 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) -meter = metrics.meter_source().get_meter(__name__) +meter = metrics.get_meter(__name__) exporter = ConsoleMetricsExporter() controller = PushController(meter, exporter, 5) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index a641599908d..a0d67ab7857 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -27,7 +27,7 @@ # defines the interface with a no-op implementation. metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) # Meter is responsible for creating and recording metrics -meter = metrics.meter_provider().get_meter(__name__) +meter = metrics.get_meter(__name__) # exporter to export metrics to the console exporter = ConsoleMetricsExporter() # controller collects metrics created from meter and exports it via the diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index 0021d9478d5..ba7a346f164 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -51,7 +51,7 @@ def usage(argv): # batcher computes checkpoints from over the process lifetime. False indicates # the batcher computes checkpoints which describe the updates of a single # collection period (deltas) -meter = metrics.meter_provider().get_meter( +meter = metrics.get_meter( __name__, batcher_mode == "stateful" ) diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index f6883475386..cf73e94e00c 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -21,6 +21,7 @@ CustomCollector, PrometheusMetricsExporter, ) +from opentelemetry import metrics as metrics_api from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import MetricRecord, MetricsExportResult from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator @@ -28,7 +29,7 @@ class TestPrometheusMetricExporter(unittest.TestCase): def setUp(self): - self._meter = metrics.MeterProvider().get_meter(__name__) + self._meter = metrics_api.get_meter(__name__) self._test_metric = self._meter.create_metric( "testname", "testdesc", @@ -74,7 +75,7 @@ def test_export(self): self.assertIs(result, MetricsExportResult.SUCCESS) def test_counter_to_prometheus(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric = meter.create_metric( "test@name", "testdesc", @@ -111,7 +112,7 @@ def test_counter_to_prometheus(self): def test_invalid_metric(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = metrics_api.get_meter(__name__) metric = meter.create_metric( "tesname", "testdesc", "unit", int, TestMetric ) diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 11e6b077642..43abfb2ee58 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -64,8 +64,8 @@ def test_meter(self): metrics.Meter() # type:ignore def test_default_meter(self): - meter_source = metrics.DefaultMeterProvider() - meter = meter_source.get_meter(__name__) + meter_provider = metrics.DefaultMeterProvider() + meter = meter_provider.get_meter(__name__) self.assertIsInstance(meter, metrics.DefaultMeter) def test_record_batch(self): From bd53f847a54368585a87642ac2b4b9ea8249a5b1 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 08:16:25 -0800 Subject: [PATCH 20/31] fix tests --- .../tests/metrics/export/test_export.py | 15 ++++----- .../tests/metrics/test_implementation.py | 3 +- .../tests/metrics/test_metrics.py | 32 +++++++++---------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 458263e0d42..ae89fc47b0b 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -15,7 +15,6 @@ import unittest from unittest import mock -from opentelemetry import metrics as metrics_api from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import ( ConsoleMetricsExporter, @@ -33,7 +32,7 @@ class TestConsoleMetricsExporter(unittest.TestCase): # pylint: disable=no-self-use def test_export(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) exporter = ConsoleMetricsExporter() metric = metrics.Counter( "available memory", @@ -70,7 +69,7 @@ def test_aggregator_for_counter(self): # TODO: Add other aggregator tests def test_checkpoint_set(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -98,7 +97,7 @@ def test_checkpoint_set_empty(self): self.assertEqual(len(records), 0) def test_finished_collection_stateless(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(False) aggregator = CounterAggregator() metric = metrics.Counter( @@ -118,7 +117,7 @@ def test_finished_collection_stateless(self): self.assertEqual(len(batcher._batch_map), 0) def test_finished_collection_stateful(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -139,7 +138,7 @@ def test_finished_collection_stateful(self): # TODO: Abstract the logic once other batchers implemented def test_ungrouped_batcher_process_exists(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() aggregator2 = CounterAggregator() @@ -168,7 +167,7 @@ def test_ungrouped_batcher_process_exists(self): ) def test_ungrouped_batcher_process_not_exists(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( @@ -195,7 +194,7 @@ def test_ungrouped_batcher_process_not_exists(self): ) def test_ungrouped_batcher_process_not_stateful(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( diff --git a/opentelemetry-sdk/tests/metrics/test_implementation.py b/opentelemetry-sdk/tests/metrics/test_implementation.py index 85cc90036c8..80c10d72676 100644 --- a/opentelemetry-sdk/tests/metrics/test_implementation.py +++ b/opentelemetry-sdk/tests/metrics/test_implementation.py @@ -14,7 +14,6 @@ import unittest -from opentelemetry import metrics as metrics_api from opentelemetry.metrics import DefaultLabelSet, DefaultMeter, DefaultMetric from opentelemetry.sdk import metrics @@ -28,7 +27,7 @@ class TestMeterImplementation(unittest.TestCase): """ def test_meter(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = meter.create_metric("", "", "", float, metrics.Counter) label_set = meter.get_label_set({"key1": "val1"}) self.assertNotIsInstance(meter, DefaultMeter) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index 74019280786..df4ddd1a436 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -22,11 +22,11 @@ class TestMeter(unittest.TestCase): def test_extends_api(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) self.assertIsInstance(meter, metrics_api.Meter) def test_collect(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -41,14 +41,14 @@ def test_collect(self): self.assertTrue(batcher_mock.process.called) def test_collect_no_metrics(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock meter.collect() self.assertFalse(batcher_mock.process.called) def test_collect_disabled_metric(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock label_keys = ("key1",) @@ -63,7 +63,7 @@ def test_collect_disabled_metric(self): self.assertFalse(batcher_mock.process.called) def test_record_batch(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) label_keys = ("key1",) counter = metrics.Counter( "name", "desc", "unit", float, meter, label_keys @@ -75,7 +75,7 @@ def test_record_batch(self): self.assertEqual(counter.get_handle(label_set).aggregator.current, 1.0) def test_record_batch_multiple(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) label_keys = ("key1", "key2", "key3") kvp = {"key1": "value1", "key2": "value2", "key3": "value3"} label_set = meter.get_label_set(kvp) @@ -96,7 +96,7 @@ def test_record_batch_multiple(self): ) def test_record_batch_exists(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) label_keys = ("key1",) kvp = {"key1": "value1"} label_set = meter.get_label_set(kvp) @@ -111,7 +111,7 @@ def test_record_batch_exists(self): self.assertEqual(handle.aggregator.current, 2.0) def test_create_metric(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) counter = meter.create_metric( "name", "desc", "unit", int, metrics.Counter, () ) @@ -120,7 +120,7 @@ def test_create_metric(self): self.assertEqual(counter.name, "name") def test_create_gauge(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) gauge = meter.create_metric( "name", "desc", "unit", float, metrics.Gauge, () ) @@ -129,7 +129,7 @@ def test_create_gauge(self): self.assertEqual(gauge.name, "name") def test_create_measure(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) measure = meter.create_metric( "name", "desc", "unit", float, metrics.Measure, () ) @@ -138,7 +138,7 @@ def test_create_measure(self): self.assertEqual(measure.name, "name") def test_get_label_set(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) kvp = {"environment": "staging", "a": "z"} label_set = meter.get_label_set(kvp) label_set2 = meter.get_label_set(kvp) @@ -146,7 +146,7 @@ def test_get_label_set(self): self.assertEqual(len(labels), 1) def test_get_label_set_empty(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) kvp = {} label_set = meter.get_label_set(kvp) self.assertEqual(label_set, metrics.EMPTY_LABEL_SET) @@ -154,7 +154,7 @@ def test_get_label_set_empty(self): class TestMetric(unittest.TestCase): def test_get_handle(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric_types = [metrics.Counter, metrics.Gauge, metrics.Measure] for _type in metric_types: metric = _type("name", "desc", "unit", int, meter, ("key",)) @@ -166,7 +166,7 @@ def test_get_handle(self): class TestCounter(unittest.TestCase): def test_add(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Counter("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -178,7 +178,7 @@ def test_add(self): class TestGauge(unittest.TestCase): def test_set(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Gauge("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) @@ -192,7 +192,7 @@ def test_set(self): class TestMeasure(unittest.TestCase): def test_record(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Measure("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) From 6f6a37d0909f39ed4b64337510c66c46171fc623 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 08:38:09 -0800 Subject: [PATCH 21/31] Fix tests --- .../tests/test_prometheus_exporter.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index cf73e94e00c..f6883475386 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -21,7 +21,6 @@ CustomCollector, PrometheusMetricsExporter, ) -from opentelemetry import metrics as metrics_api from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import MetricRecord, MetricsExportResult from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator @@ -29,7 +28,7 @@ class TestPrometheusMetricExporter(unittest.TestCase): def setUp(self): - self._meter = metrics_api.get_meter(__name__) + self._meter = metrics.MeterProvider().get_meter(__name__) self._test_metric = self._meter.create_metric( "testname", "testdesc", @@ -75,7 +74,7 @@ def test_export(self): self.assertIs(result, MetricsExportResult.SUCCESS) def test_counter_to_prometheus(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = meter.create_metric( "test@name", "testdesc", @@ -112,7 +111,7 @@ def test_counter_to_prometheus(self): def test_invalid_metric(self): - meter = metrics_api.get_meter(__name__) + meter = metrics.MeterProvider().get_meter(__name__) metric = meter.create_metric( "tesname", "testdesc", "unit", int, TestMetric ) From 4770ec4ebc3cd3bf206c44722e6a65a30919866a Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 08:52:35 -0800 Subject: [PATCH 22/31] black --- tox.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index be7f1db9f73..8899c8f53ce 100644 --- a/tox.ini +++ b/tox.ini @@ -187,7 +187,8 @@ commands_pre = python scripts/eachdist.py install --editable commands = - python scripts/eachdist.py lint --check-only + ; python scripts/eachdist.py lint --check-only + black . [testenv:docs] deps = From 0f36b31b7bb64dbe4eb88a55aa70af7603d70cbf Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 09:19:41 -0800 Subject: [PATCH 23/31] remove black --- tox.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 8899c8f53ce..be7f1db9f73 100644 --- a/tox.ini +++ b/tox.ini @@ -187,8 +187,7 @@ commands_pre = python scripts/eachdist.py install --editable commands = - ; python scripts/eachdist.py lint --check-only - black . + python scripts/eachdist.py lint --check-only [testenv:docs] deps = From 4f4632b46ebb486ec3f3bcc4edf3c090a6d6d3cd Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 11:02:52 -0800 Subject: [PATCH 24/31] ADDRESS COMMENTS --- README.md | 2 +- examples/metrics/record.py | 2 +- examples/metrics/simple_example.py | 2 +- .../tests/test_flask_integration.py | 5 +++- .../context/threadlocal_context.py | 4 ++- .../src/opentelemetry/metrics/__init__.py | 26 +++++++++---------- .../src/opentelemetry/util/__init__.py | 2 +- .../tests/metrics/test_metrics.py | 2 +- .../tests/test_implementation.py | 2 +- .../tests/trace/test_sampling.py | 4 ++- .../src/opentelemetry/sdk/metrics/__init__.py | 3 ++- .../opentelemetry/sdk/util/instrumentation.py | 2 +- .../tests/metrics/export/test_export.py | 2 +- .../tests/metrics/test_implementation.py | 2 +- .../tests/metrics/test_metrics.py | 2 +- 15 files changed, 35 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 3dae1136e67..734a824661e 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController -metrics.set_preferred_meter_source_implementation(lambda _: MeterProvider()) +metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) meter = metrics.get_meter(__name__) exporter = ConsoleMetricsExporter() controller = PushController(meter, exporter, 5) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index a0d67ab7857..f008ff67466 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index ba7a346f164..d3aad1046d0 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-flask/tests/test_flask_integration.py b/ext/opentelemetry-ext-flask/tests/test_flask_integration.py index b9454b94472..9d2f2560118 100644 --- a/ext/opentelemetry-ext-flask/tests/test_flask_integration.py +++ b/ext/opentelemetry-ext-flask/tests/test_flask_integration.py @@ -78,7 +78,10 @@ def assert_environ(): def test_simple(self): expected_attrs = expected_attributes( - {"http.target": "/hello/123", "http.route": "/hello/"} + { + "http.target": "/hello/123", + "http.route": "/hello/", + } ) resp = self.client.get("/hello/123") self.assertEqual(200, resp.status_code) diff --git a/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py b/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py index e4afb43c5fc..6a0e76bb693 100644 --- a/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py +++ b/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py @@ -41,7 +41,9 @@ def attach(self, context: Context) -> object: def get_current(self) -> Context: """See `opentelemetry.context.RuntimeContext.get_current`.""" if not hasattr(self._current_context, self._CONTEXT_KEY): - setattr(self._current_context, self._CONTEXT_KEY, Context()) + setattr( + self._current_context, self._CONTEXT_KEY, Context(), + ) context = getattr( self._current_context, self._CONTEXT_KEY ) # type: Context diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 0a816878ea0..ac513905fff 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -379,8 +379,8 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": [Type[MeterProvider]], Optional[MeterProvider] ] -_METER_SOURCE = None -_METER_SOURCE_FACTORY = None +_METER_PROVIDER = None +_METER_PROVIDER_FACTORY = None def get_meter( @@ -402,13 +402,13 @@ def meter_provider() -> MeterProvider: If there isn't one set yet, a default will be loaded. """ - global _METER_SOURCE, _METER_SOURCE_FACTORY # pylint:disable=global-statement + global _METER_PROVIDER, _METER_PROVIDER_FACTORY # pylint:disable=global-statement - if _METER_SOURCE is None: + if _METER_PROVIDER is None: # pylint:disable=protected-access try: - _METER_SOURCE = loader._load_impl( - MeterProvider, _METER_SOURCE_FACTORY # type: ignore + _METER_PROVIDER = loader._load_impl( + MeterProvider, _METER_PROVIDER_FACTORY # type: ignore ) except TypeError: # if we raised an exception trying to instantiate an @@ -417,10 +417,10 @@ def meter_provider() -> MeterProvider: "Unable to instantiate MeterProvider from meter provider factory.", exc_info=True, ) - _METER_SOURCE = DefaultMeterProvider() - del _METER_SOURCE_FACTORY + _METER_PROVIDER = DefaultMeterProvider() + del _METER_PROVIDER_FACTORY - return _METER_SOURCE + return _METER_PROVIDER def set_preferred_meter_provider_implementation( @@ -435,9 +435,9 @@ def set_preferred_meter_provider_implementation( Args: factory: Callback that should create a new :class:`MeterProvider` instance. """ - global _METER_SOURCE_FACTORY # pylint:disable=global-statement + global _METER_PROVIDER_FACTORY # pylint:disable=global-statement - if _METER_SOURCE: + if _METER_PROVIDER: raise RuntimeError("MeterProvider already loaded.") - _METER_SOURCE_FACTORY = factory + _METER_PROVIDER_FACTORY = factory diff --git a/opentelemetry-api/src/opentelemetry/util/__init__.py b/opentelemetry-api/src/opentelemetry/util/__init__.py index 6743ac2333f..9bfc79df21c 100644 --- a/opentelemetry-api/src/opentelemetry/util/__init__.py +++ b/opentelemetry-api/src/opentelemetry/util/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index 2d63083d6ce..788ce57680a 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 43abfb2ee58..cf9b0366e0b 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/trace/test_sampling.py b/opentelemetry-api/tests/trace/test_sampling.py index e9ecd19af77..f04aecef45b 100644 --- a/opentelemetry-api/tests/trace/test_sampling.py +++ b/opentelemetry-api/tests/trace/test_sampling.py @@ -235,4 +235,6 @@ def test_probability_sampler_limits(self): # Check that the higest effective sampling rate is actually lower than # the highest theoretical sampling rate. If this test fails the test # above is wrong. - self.assertLess(almost_almost_always_on.bound, 0xFFFFFFFFFFFFFFFF) + self.assertLess( + almost_almost_always_on.bound, 0xFFFFFFFFFFFFFFFF, + ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 7aec35d9891..fdf145d87ca 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -263,6 +263,7 @@ class Meter(metrics_api.Meter): Args: instrumentation_info: The `InstrumentationInfo` for this meter. + stateful: Indicates whether the meter is stateful. """ def __init__( diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py index e518dd14cd4..893a6066d9f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index ae89fc47b0b..91d79d36b81 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/test_implementation.py b/opentelemetry-sdk/tests/metrics/test_implementation.py index 80c10d72676..1fedc9ae571 100644 --- a/opentelemetry-sdk/tests/metrics/test_implementation.py +++ b/opentelemetry-sdk/tests/metrics/test_implementation.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index df4ddd1a436..daba171c51c 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright 2020, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From e591a392f8b56e968765c2ba2c90517fd2a329a5 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 11:19:08 -0800 Subject: [PATCH 25/31] black --- examples/metrics/simple_example.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/metrics/simple_example.py b/examples/metrics/simple_example.py index d3aad1046d0..75879155176 100644 --- a/examples/metrics/simple_example.py +++ b/examples/metrics/simple_example.py @@ -51,9 +51,7 @@ def usage(argv): # batcher computes checkpoints from over the process lifetime. False indicates # the batcher computes checkpoints which describe the updates of a single # collection period (deltas) -meter = metrics.get_meter( - __name__, batcher_mode == "stateful" -) +meter = metrics.get_meter(__name__, batcher_mode == "stateful") # Exporter to export metrics to the console exporter = ConsoleMetricsExporter() From 0878f5d76bef06a1e394b6c799f1fe8613f3babe Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 11:39:42 -0800 Subject: [PATCH 26/31] fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index ac513905fff..f038a06def6 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -249,7 +249,7 @@ def get_meter( E.g., instead of ``"requests"``, use ``"opentelemetry.ext.http_requests"``. - stateful: True/False to indicate whether the meter will be + stateful: True/False to indicate whether the meter will be stateful. True indicates the meter computes checkpoints from over the process lifetime. False indicates the meter computes checkpoints which describe the updates of a single From 584d99618c4bc99b4e55e9f035d0a4c56192e13a Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 12:00:38 -0800 Subject: [PATCH 27/31] fix example --- examples/metrics/prometheus.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/metrics/prometheus.py b/examples/metrics/prometheus.py index 14f612c6a93..4d30f8abcca 100644 --- a/examples/metrics/prometheus.py +++ b/examples/metrics/prometheus.py @@ -21,15 +21,15 @@ from opentelemetry import metrics from opentelemetry.ext.prometheus import PrometheusMetricsExporter -from opentelemetry.sdk.metrics import Counter, Meter +from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export.controller import PushController # Start Prometheus client start_http_server(port=8000, addr="localhost") # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_implementation(lambda _: Meter()) -meter = metrics.meter() +metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) +meter = metrics.get_meter(__name__) # exporter to export metrics to Prometheus prefix = "MyAppPrefix" exporter = PrometheusMetricsExporter(prefix) From f85492350153bc78197442a10b448b9600c29287 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 12:20:18 -0800 Subject: [PATCH 28/31] Fix lint --- opentelemetry-api/tests/test_implementation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index cf9b0366e0b..0035803bd26 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -68,11 +68,11 @@ def test_default_meter(self): meter = meter_provider.get_meter(__name__) self.assertIsInstance(meter, metrics.DefaultMeter) + # pylint: disable=no-self-use def test_record_batch(self): meter = metrics.DefaultMeter() counter = metrics.Counter() label_set = metrics.LabelSet() - # pylint: disable=no-self-use meter.record_batch(label_set, ((counter, 1),)) def test_create_metric(self): From 40ee67bf4c4fa7fb8e80ec908a26832b06681c3b Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 18:49:52 -0800 Subject: [PATCH 29/31] fix labelset --- opentelemetry-sdk/tests/metrics/export/test_export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 14c9d903cdc..87edd667d3c 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -45,7 +45,7 @@ def test_export(self): ("environment",), ) kvp = {"environment": "staging"} - label_set = meter.LabelSet(kvp) + label_set = metrics.LabelSet(kvp) aggregator = CounterAggregator() record = MetricRecord(aggregator, label_set, metric) result = '{}(data="{}", label_set="{}", value={})'.format( From 0b9328534acb0b0e98825d1480eeb8a385105a7d Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 27 Feb 2020 21:33:38 -0800 Subject: [PATCH 30/31] fix lint --- .../tests/metrics/export/test_export.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 87edd667d3c..cd12bcbb6bf 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -304,9 +304,7 @@ def call_update(mmsc): def test_update(self): mmsc = MinMaxSumCountAggregator() # test current values without any update - self.assertEqual( - mmsc.current, MinMaxSumCountAggregator._EMPTY, - ) + self.assertEqual(mmsc.current, MinMaxSumCountAggregator._EMPTY) # call update with some values values = (3, 50, 3, 97) @@ -314,7 +312,7 @@ def test_update(self): mmsc.update(val) self.assertEqual( - mmsc.current, (min(values), max(values), sum(values), len(values)), + mmsc.current, (min(values), max(values), sum(values), len(values)) ) def test_checkpoint(self): @@ -322,9 +320,7 @@ def test_checkpoint(self): # take checkpoint wihtout any update mmsc.take_checkpoint() - self.assertEqual( - mmsc.checkpoint, MinMaxSumCountAggregator._EMPTY, - ) + self.assertEqual(mmsc.checkpoint, MinMaxSumCountAggregator._EMPTY) # call update with some values values = (3, 50, 3, 97) @@ -337,9 +333,7 @@ def test_checkpoint(self): (min(values), max(values), sum(values), len(values)), ) - self.assertEqual( - mmsc.current, MinMaxSumCountAggregator._EMPTY, - ) + self.assertEqual(mmsc.current, MinMaxSumCountAggregator._EMPTY) def test_merge(self): mmsc1 = MinMaxSumCountAggregator() @@ -440,4 +434,4 @@ def test_push_controller(self): exporter.export.assert_not_called() controller.shutdown() self.assertTrue(controller.finished.isSet()) - exporter.shutdown.assert_any_call() \ No newline at end of file + exporter.shutdown.assert_any_call() From 3735d889ee09fb1a672518e6db176280c50f736c Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 28 Feb 2020 17:38:51 -0800 Subject: [PATCH 31/31] set to none --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index f038a06def6..c1b330551aa 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -418,7 +418,7 @@ def meter_provider() -> MeterProvider: exc_info=True, ) _METER_PROVIDER = DefaultMeterProvider() - del _METER_PROVIDER_FACTORY + _METER_PROVIDER_FACTORY = None return _METER_PROVIDER