From 958cb479f2901e5f03c757227d4c00e747c24755 Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 9 Mar 2020 12:37:08 -0700 Subject: [PATCH 1/8] init --- README.md | 20 ++--- examples/metrics/record.py | 12 +-- .../src/opentelemetry/metrics/__init__.py | 88 +++++++++---------- .../tests/metrics/test_metrics.py | 28 +++--- .../src/opentelemetry/sdk/metrics/__init__.py | 79 ++++++----------- .../tests/metrics/test_metrics.py | 82 ++++++++--------- 6 files changed, 144 insertions(+), 165 deletions(-) diff --git a/README.md b/README.md index 734a824661e..84ce5244af6 100644 --- a/README.md +++ b/README.md @@ -77,20 +77,20 @@ from opentelemetry.sdk.metrics.export.controller import PushController metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) meter = metrics.get_meter(__name__) exporter = ConsoleMetricsExporter() -controller = PushController(meter, exporter, 5) +controller = PushController(meter=meter, exporter=exporter, interval=5) counter = meter.create_metric( - "available memory", - "available memory", - "bytes", - int, - Counter, - ("environment",), + name="available memory", + description="available memory", + unit="bytes", + value_type=int, + metric_type=Counter, + label_keys=("environment",), ) -label_values = ("staging",) -counter_handle = counter.get_handle(label_values) -counter_handle.add(100) +label_set = meter.get_label_set({"environment": "staging"}) +bound_counter = counter.bind(label_set) +bound_counter.add(100) ``` 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/examples/metrics/record.py b/examples/metrics/record.py index a376b2aafc0..4d6dba810be 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -61,12 +61,12 @@ label_set = meter.get_label_set({"environment": "staging"}) # Handle usage -# You can record metrics with metric handles. Handles are created by passing in -# a labelset. A handle is essentially metric data that corresponds to a specific -# set of labels. Therefore, getting a handle using the same set of labels will -# yield the same metric handle. -counter_handle = counter.get_handle(label_set) -counter_handle.add(100) +# You can record metrics with bound metrics. Bound metrics are created by +# passing in a labelset. A bound metric is essentially metric data that +# corresponds to a specific set of labels. Therefore, getting a bound metric +# using the same set of labels will yield the same bound metric. +bound_counter = counter.bind(label_set) +bound_counter.add(100) # Direct metric usage # You can record metrics directly using the metric instrument. You pass in a diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3ba9bcad009..67bdf854af0 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -37,42 +37,42 @@ ValueT = TypeVar("ValueT", int, float) -class DefaultMetricHandle: - """The default MetricHandle. +class DefaultBoundMetric: + """The default BoundMetric. - Used when no MetricHandle implementation is available. + Used when no BoundMetric implementation is available. """ def add(self, value: ValueT) -> None: - """No-op implementation of `CounterHandle` add. + """No-op implementation of `BoundCounter` add. Args: - value: The value to add to the handle. + value: The value to add to the bound metric. """ def record(self, value: ValueT) -> None: - """No-op implementation of `MeasureHandle` record. + """No-op implementation of `BoundMeasure` record. Args: - value: The value to record to the handle. + value: The value to record to the bound metric. """ -class CounterHandle: +class BoundCounter: def add(self, value: ValueT) -> None: - """Increases the value of the handle by ``value``. + """Increases the value of the bound counter by ``value``. Args: - value: The value to add to the handle. + value: The value to add to the bound counter. """ -class MeasureHandle: +class BoundMeasure: def record(self, value: ValueT) -> None: - """Records the given ``value`` to this handle. + """Records the given ``value`` to this bound measure. Args: - value: The value to record to the handle. + value: The value to record to the bound measure. """ @@ -80,11 +80,11 @@ class LabelSet(abc.ABC): """A canonicalized set of labels useful for preaggregation Re-usable LabelSet objects provide a potential optimization for scenarios - where handles might not be effective. For example, if the LabelSet will be - re-used but only used once per metrics, handles do not offer any - optimization. It may best to pre-compute a canonicalized LabelSet once and - re-use it with the direct calling convention. LabelSets are immutable and - should be opaque in implementation. + where bound metrics might not be effective. For example, if the LabelSet + will be re-used but only used once per metrics, bound metrics do not offer + any optimization. It may best to pre-compute a canonicalized LabelSet once + and re-use it with the direct calling convention. LabelSets are immutable + and should be opaque in implementation. """ @@ -99,42 +99,42 @@ class Metric(abc.ABC): """Base class for various types of metrics. Metric class that inherit from this class are specialized with the type of - handle that the metric holds. + bound metric that the metric holds. """ @abc.abstractmethod - def get_handle(self, label_set: LabelSet) -> "object": - """Gets a handle, used for repeated-use of metrics instruments. + def bind(self, label_set: LabelSet) -> "object": + """Gets a bound metric, used for repeated-use of metrics instruments. - Handles are useful to reduce the cost of repeatedly recording a metric - with a pre-defined set of label values. All metric kinds (counter, - measure) support declaring a set of required label keys. The - values corresponding to these keys should be specified in every handle. - "Unspecified" label values, in cases where a handle is requested but - a value was not provided are permitted. + Bound metrics are useful to reduce the cost of repeatedly recording a + metric with a pre-defined set of label values. All metric kinds + (counter, measure) support declaring a set of required label keys. The + values corresponding to these keys should be specified in every bound + metric. "Unspecified" label values, in cases where a bound metric is + requested but a value was not provided are permitted. Args: - label_set: `LabelSet` to associate with the returned handle. + label_set: `LabelSet` to associate with the returned bound metric. """ class DefaultMetric(Metric): """The default Metric used when no Metric implementation is available.""" - def get_handle(self, label_set: LabelSet) -> "DefaultMetricHandle": - """Gets a `DefaultMetricHandle`. + def bind(self, label_set: LabelSet) -> "DefaultBoundMetric": + """Gets a `DefaultBoundMetric`. Args: - label_set: `LabelSet` to associate with the returned handle. + label_set: `LabelSet` to associate with the returned bound metric. """ - return DefaultMetricHandle() + return DefaultBoundMetric() def add(self, value: ValueT, label_set: LabelSet) -> None: """No-op implementation of `Counter` add. Args: value: The value to add to the counter metric. - label_set: `LabelSet` to associate with the returned handle. + label_set: `LabelSet` to associate with the returned bound metric. """ def record(self, value: ValueT, label_set: LabelSet) -> None: @@ -142,23 +142,23 @@ def record(self, value: ValueT, label_set: LabelSet) -> None: Args: value: The value to record to this measure metric. - label_set: `LabelSet` to associate with the returned handle. + label_set: `LabelSet` to associate with the returned bound metric. """ class Counter(Metric): """A counter type metric that expresses the computation of a sum.""" - def get_handle(self, label_set: LabelSet) -> "CounterHandle": - """Gets a `CounterHandle`.""" - return CounterHandle() + def bind(self, label_set: LabelSet) -> "BoundCounter": + """Gets a `BoundCounter`.""" + return BoundCounter() def add(self, value: ValueT, label_set: LabelSet) -> None: """Increases the value of the counter by ``value``. Args: value: The value to add to the counter metric. - label_set: `LabelSet` to associate with the returned handle. + label_set: `LabelSet` to associate with the returned bound counter. """ @@ -168,16 +168,16 @@ class Measure(Metric): Measure metrics represent raw statistics that are recorded. """ - def get_handle(self, label_set: LabelSet) -> "MeasureHandle": - """Gets a `MeasureHandle` with a float value.""" - return MeasureHandle() + def bind(self, label_set: LabelSet) -> "BoundMeasure": + """Gets a `BoundMeasure` with a float value.""" + return BoundMeasure() def record(self, value: ValueT, label_set: LabelSet) -> None: """Records the ``value`` to the measure. Args: value: The value to record to this measure metric. - label_set: `LabelSet` to associate with the returned handle. + label_set: `LabelSet` to associate with the returned bound measure. """ @@ -284,8 +284,8 @@ def record_batch( """Atomically records a batch of `Metric` and value pairs. Allows the functionality of acting upon multiple metrics with - a single API call. Implementations should find metric and handles that - match the key-value pairs in the label tuples. + a single API call. Implementations should find metric and bound metrics + that match the key-value pairs in the label tuples. Args: label_set: The `LabelSet` associated with all measurements in diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index 45913ca6720..c7ea3638bb9 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -22,14 +22,14 @@ class TestMetrics(unittest.TestCase): def test_default(self): default = metrics.DefaultMetric() default_ls = metrics.DefaultLabelSet() - handle = default.get_handle(default_ls) - self.assertIsInstance(handle, metrics.DefaultMetricHandle) + bound_metric = default.bind(default_ls) + self.assertIsInstance(bound_metric, metrics.DefaultBoundMetric) def test_counter(self): counter = metrics.Counter() label_set = metrics.LabelSet() - handle = counter.get_handle(label_set) - self.assertIsInstance(handle, metrics.CounterHandle) + bound_metric = counter.bind(label_set) + self.assertIsInstance(bound_metric, metrics.BoundCounter) def test_counter_add(self): counter = metrics.Counter() @@ -39,21 +39,21 @@ def test_counter_add(self): def test_measure(self): measure = metrics.Measure() label_set = metrics.LabelSet() - handle = measure.get_handle(label_set) - self.assertIsInstance(handle, metrics.MeasureHandle) + bound_metric = measure.bind(label_set) + self.assertIsInstance(bound_metric, metrics.BoundMeasure) def test_measure_record(self): measure = metrics.Measure() label_set = metrics.LabelSet() measure.record(1, label_set) - def test_default_handle(self): - metrics.DefaultMetricHandle() + def test_default_bound_metric(self): + metrics.DefaultBoundMetric() - def test_counter_handle(self): - handle = metrics.CounterHandle() - handle.add(1) + def test_bound_counter(self): + bound_metric = metrics.BoundCounter() + bound_metric.add(1) - def test_measure_handle(self): - handle = metrics.MeasureHandle() - handle.record(1) + def test_bound_measure(self): + bound_metric = metrics.BoundMeasure() + bound_metric.record(1) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index fc0fe6ae521..b60257ca85a 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -47,17 +47,16 @@ def __eq__(self, other): return self._encoded == other._encoded -class BaseHandle: - """The base handle class containing common behavior for all handles. +class BaseBoundMetric: + """Class containing common behavior for all bound metrics. - Handles are responsible for operating on data for metric instruments for a - specific set of labels. + Bound metrics are responsible for operating on data for metric instruments + for a specific set of labels. - Args: - value_type: The type of values this handle holds (int, float). - enabled: True if the originating instrument is enabled. - aggregator: The aggregator for this handle. Will handle aggregation - upon updates and checkpointing of values for exporting. + Args: value_type: The type of values this bound metric holds (int, float). + enabled: True if the originating instrument is enabled. aggregator: The + aggregator for this bound metric. Will handle aggregation upon updates + and checkpointing of values for exporting. """ def __init__( @@ -93,16 +92,16 @@ def __repr__(self): ) -class CounterHandle(metrics_api.CounterHandle, BaseHandle): +class BoundCounter(metrics_api.BoundCounter, BaseBoundMetric): def add(self, value: metrics_api.ValueT) -> None: - """See `opentelemetry.metrics.CounterHandle.add`.""" + """See `opentelemetry.metrics.BoundCounter.add`.""" if self._validate_update(value): self.update(value) -class MeasureHandle(metrics_api.MeasureHandle, BaseHandle): +class BoundMeasure(metrics_api.BoundMeasure, BaseBoundMetric): def record(self, value: metrics_api.ValueT) -> None: - """See `opentelemetry.metrics.MeasureHandle.record`.""" + """See `opentelemetry.metrics.BoundMeasure.record`.""" if self._validate_update(value): self.update(value) @@ -112,11 +111,11 @@ class Metric(metrics_api.Metric): Also known as metric instrument. This is the class that is used to represent a metric that is to be continuously recorded and tracked. Each - metric has a set of handles that are created from the metric. See - `BaseHandle` for information on handles. + metric has a set of bound metrics that are created from the metric. See + `BaseBoundMetric` for information on bound metrics. """ - HANDLE_TYPE = BaseHandle + BOUND_METRIC_TYPE = BaseBoundMetric def __init__( self, @@ -135,20 +134,20 @@ def __init__( self.meter = meter self.label_keys = label_keys self.enabled = enabled - self.handles = {} + self.bound_metrics = {} - def get_handle(self, label_set: LabelSet) -> BaseHandle: - """See `opentelemetry.metrics.Metric.get_handle`.""" - handle = self.handles.get(label_set) - if not handle: - handle = self.HANDLE_TYPE( + def bind(self, label_set: LabelSet) -> BaseBoundMetric: + """See `opentelemetry.metrics.Metric.bind`.""" + bound_metric = self.bound_metrics.get(label_set) + if not bound_metric: + bound_metric = self.BOUND_METRIC_TYPE( self.value_type, self.enabled, # Aggregator will be created based off type of metric self.meter.batcher.aggregator_for(self.__class__), ) - self.handles[label_set] = handle - return handle + self.bound_metrics[label_set] = bound_metric + return bound_metric def __repr__(self): return '{}(name="{}", description="{}")'.format( @@ -162,31 +161,11 @@ class Counter(Metric, metrics_api.Counter): """See `opentelemetry.metrics.Counter`. """ - HANDLE_TYPE = CounterHandle - - def __init__( - self, - name: str, - description: str, - unit: str, - value_type: Type[metrics_api.ValueT], - meter: "Meter", - label_keys: Sequence[str] = (), - enabled: bool = True, - ): - super().__init__( - name, - description, - unit, - value_type, - meter, - label_keys=label_keys, - enabled=enabled, - ) + BOUND_METRIC_TYPE = BoundCounter def add(self, value: metrics_api.ValueT, label_set: LabelSet) -> None: """See `opentelemetry.metrics.Counter.add`.""" - self.get_handle(label_set).add(value) + self.bind(label_set).add(value) UPDATE_FUNCTION = add @@ -194,11 +173,11 @@ def add(self, value: metrics_api.ValueT, label_set: LabelSet) -> None: class Measure(Metric, metrics_api.Measure): """See `opentelemetry.metrics.Measure`.""" - HANDLE_TYPE = MeasureHandle + BOUND_METRIC_TYPE = BoundMeasure def record(self, value: metrics_api.ValueT, label_set: LabelSet) -> None: """See `opentelemetry.metrics.Measure.record`.""" - self.get_handle(label_set).record(value) + self.bind(label_set).record(value) UPDATE_FUNCTION = record @@ -310,9 +289,9 @@ def collect(self) -> None: def _collect_metrics(self) -> None: for metric in self.metrics: if metric.enabled: - for label_set, handle in metric.handles.items(): + for label_set, bound_metric in metric.bound_metrics.items(): # TODO: Consider storing records in memory? - record = Record(metric, label_set, handle.aggregator) + record = Record(metric, label_set, bound_metric.aggregator) # Checkpoints the current aggregators # Applies different batching logic based on type of batcher self.batcher.process(record) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index ea20cdd5930..b2d57b12593 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -89,7 +89,7 @@ def test_record_batch(self): label_set = meter.get_label_set(kvp) record_tuples = [(counter, 1.0)] meter.record_batch(label_set, record_tuples) - self.assertEqual(counter.get_handle(label_set).aggregator.current, 1.0) + self.assertEqual(counter.bind(label_set).aggregator.current, 1.0) def test_record_batch_multiple(self): meter = metrics.MeterProvider().get_meter(__name__) @@ -104,9 +104,9 @@ def test_record_batch_multiple(self): ) record_tuples = [(counter, 1.0), (measure, 3.0)] meter.record_batch(label_set, record_tuples) - self.assertEqual(counter.get_handle(label_set).aggregator.current, 1.0) + self.assertEqual(counter.bind(label_set).aggregator.current, 1.0) self.assertEqual( - measure.get_handle(label_set).aggregator.current, + measure.bind(label_set).aggregator.current, (3.0, 3.0, 3.0, 1), ) @@ -119,11 +119,11 @@ def test_record_batch_exists(self): "name", "desc", "unit", float, meter, label_keys ) counter.add(1.0, label_set) - handle = counter.get_handle(label_set) + bound_metric = counter.bind(label_set) record_tuples = [(counter, 1.0)] meter.record_batch(label_set, record_tuples) - self.assertEqual(counter.get_handle(label_set), handle) - self.assertEqual(handle.aggregator.current, 2.0) + self.assertEqual(counter.bind(label_set), bound_metric) + self.assertEqual(bound_metric.aggregator.current, 2.0) def test_create_metric(self): meter = metrics.MeterProvider().get_meter(__name__) @@ -179,15 +179,15 @@ def test_get_label_set_empty(self): class TestMetric(unittest.TestCase): - def test_get_handle(self): + def test_bind(self): meter = metrics.MeterProvider().get_meter(__name__) metric_types = [metrics.Counter, metrics.Measure] for _type in metric_types: metric = _type("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) - handle = metric.get_handle(label_set) - self.assertEqual(metric.handles.get(label_set), handle) + bound_metric = metric.bind(label_set) + self.assertEqual(metric.bound_metrics.get(label_set), bound_metric) class TestCounter(unittest.TestCase): @@ -196,10 +196,10 @@ def test_add(self): metric = metrics.Counter("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) - handle = metric.get_handle(label_set) + bound_metric = metric.bind(label_set) metric.add(3, label_set) metric.add(2, label_set) - self.assertEqual(handle.aggregator.current, 5) + self.assertEqual(bound_metric.aggregator.current, 5) class TestMeasure(unittest.TestCase): @@ -208,12 +208,12 @@ def test_record(self): metric = metrics.Measure("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) - handle = metric.get_handle(label_set) + bound_metric = metric.bind(label_set) values = (37, 42, 7) for val in values: metric.record(val, label_set) self.assertEqual( - handle.aggregator.current, + bound_metric.aggregator.current, (min(values), max(values), sum(values), len(values)), ) @@ -284,63 +284,63 @@ def test_run_exception(self, logger_mock): self.assertTrue(logger_mock.warning.called) -class TestCounterHandle(unittest.TestCase): +class TestBoundCounter(unittest.TestCase): def test_add(self): aggregator = export.aggregate.CounterAggregator() - handle = metrics.CounterHandle(int, True, aggregator) - handle.add(3) - self.assertEqual(handle.aggregator.current, 3) + bound_metric = metrics.BoundCounter(int, True, aggregator) + bound_metric.add(3) + self.assertEqual(bound_metric.aggregator.current, 3) def test_add_disabled(self): aggregator = export.aggregate.CounterAggregator() - handle = metrics.CounterHandle(int, False, aggregator) - handle.add(3) - self.assertEqual(handle.aggregator.current, 0) + bound_metric = metrics.BoundCounter(int, False, aggregator) + bound_metric.add(3) + self.assertEqual(bound_metric.aggregator.current, 0) @mock.patch("opentelemetry.sdk.metrics.logger") def test_add_incorrect_type(self, logger_mock): aggregator = export.aggregate.CounterAggregator() - handle = metrics.CounterHandle(int, True, aggregator) - handle.add(3.0) - self.assertEqual(handle.aggregator.current, 0) + bound_metric = metrics.BoundCounter(int, True, aggregator) + bound_metric.add(3.0) + self.assertEqual(bound_metric.aggregator.current, 0) self.assertTrue(logger_mock.warning.called) @mock.patch("opentelemetry.sdk.metrics.time_ns") def test_update(self, time_mock): aggregator = export.aggregate.CounterAggregator() - handle = metrics.CounterHandle(int, True, aggregator) + bound_metric = metrics.BoundCounter(int, True, aggregator) time_mock.return_value = 123 - handle.update(4.0) - self.assertEqual(handle.last_update_timestamp, 123) - self.assertEqual(handle.aggregator.current, 4.0) + bound_metric.update(4.0) + self.assertEqual(bound_metric.last_update_timestamp, 123) + self.assertEqual(bound_metric.aggregator.current, 4.0) -class TestMeasureHandle(unittest.TestCase): +class TestBoundMeasure(unittest.TestCase): def test_record(self): aggregator = export.aggregate.MinMaxSumCountAggregator() - handle = metrics.MeasureHandle(int, True, aggregator) - handle.record(3) - self.assertEqual(handle.aggregator.current, (3, 3, 3, 1)) + bound_metric = metrics.BoundMeasure(int, True, aggregator) + bound_metric.record(3) + self.assertEqual(bound_metric.aggregator.current, (3, 3, 3, 1)) def test_record_disabled(self): aggregator = export.aggregate.MinMaxSumCountAggregator() - handle = metrics.MeasureHandle(int, False, aggregator) - handle.record(3) - self.assertEqual(handle.aggregator.current, (None, None, None, 0)) + bound_metric = metrics.BoundMeasure(int, False, aggregator) + bound_metric.record(3) + self.assertEqual(bound_metric.aggregator.current, (None, None, None, 0)) @mock.patch("opentelemetry.sdk.metrics.logger") def test_record_incorrect_type(self, logger_mock): aggregator = export.aggregate.MinMaxSumCountAggregator() - handle = metrics.MeasureHandle(int, True, aggregator) - handle.record(3.0) - self.assertEqual(handle.aggregator.current, (None, None, None, 0)) + bound_metric = metrics.BoundMeasure(int, True, aggregator) + bound_metric.record(3.0) + self.assertEqual(bound_metric.aggregator.current, (None, None, None, 0)) self.assertTrue(logger_mock.warning.called) @mock.patch("opentelemetry.sdk.metrics.time_ns") def test_update(self, time_mock): aggregator = export.aggregate.MinMaxSumCountAggregator() - handle = metrics.MeasureHandle(int, True, aggregator) + bound_metric = metrics.BoundMeasure(int, True, aggregator) time_mock.return_value = 123 - handle.update(4.0) - self.assertEqual(handle.last_update_timestamp, 123) - self.assertEqual(handle.aggregator.current, (4.0, 4.0, 4.0, 1)) + bound_metric.update(4.0) + self.assertEqual(bound_metric.last_update_timestamp, 123) + self.assertEqual(bound_metric.aggregator.current, (4.0, 4.0, 4.0, 1)) From 295cc5a2a07e382b645b6afc9d38ce229c1eb3aa Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 9 Mar 2020 12:54:40 -0700 Subject: [PATCH 2/8] Fix black --- .../src/opentelemetry/sdk/metrics/__init__.py | 2 +- opentelemetry-sdk/tests/metrics/export/test_export.py | 8 ++------ opentelemetry-sdk/tests/metrics/test_metrics.py | 11 +++++++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index b60257ca85a..da923a97d06 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -268,7 +268,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() diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 3aab1632ec3..33d8d07c299 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -430,9 +430,7 @@ class TestObserverAggregator(unittest.TestCase): def test_update(self): observer = ObserverAggregator() # test current values without any update - self.assertEqual( - observer.mmsc.current, (None, None, None, 0), - ) + self.assertEqual(observer.mmsc.current, (None, None, None, 0)) self.assertIsNone(observer.current) # call update with some values @@ -452,9 +450,7 @@ def test_checkpoint(self): # take checkpoint wihtout any update observer.take_checkpoint() - self.assertEqual( - observer.checkpoint, (None, None, None, 0, None), - ) + self.assertEqual(observer.checkpoint, (None, None, None, 0, None)) # call update with some values values = (3, 50, 3, 97) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index b2d57b12593..4a48e308a7c 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -106,8 +106,7 @@ def test_record_batch_multiple(self): meter.record_batch(label_set, record_tuples) self.assertEqual(counter.bind(label_set).aggregator.current, 1.0) self.assertEqual( - measure.bind(label_set).aggregator.current, - (3.0, 3.0, 3.0, 1), + measure.bind(label_set).aggregator.current, (3.0, 3.0, 3.0, 1) ) def test_record_batch_exists(self): @@ -326,14 +325,18 @@ def test_record_disabled(self): aggregator = export.aggregate.MinMaxSumCountAggregator() bound_metric = metrics.BoundMeasure(int, False, aggregator) bound_metric.record(3) - self.assertEqual(bound_metric.aggregator.current, (None, None, None, 0)) + self.assertEqual( + bound_metric.aggregator.current, (None, None, None, 0) + ) @mock.patch("opentelemetry.sdk.metrics.logger") def test_record_incorrect_type(self, logger_mock): aggregator = export.aggregate.MinMaxSumCountAggregator() bound_metric = metrics.BoundMeasure(int, True, aggregator) bound_metric.record(3.0) - self.assertEqual(bound_metric.aggregator.current, (None, None, None, 0)) + self.assertEqual( + bound_metric.aggregator.current, (None, None, None, 0) + ) self.assertTrue(logger_mock.warning.called) @mock.patch("opentelemetry.sdk.metrics.time_ns") From 9b160a6ca2b0fbc2020272eeb4388a064df86151 Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 9 Mar 2020 16:40:02 -0700 Subject: [PATCH 3/8] bound metric to instrument --- examples/metrics/record.py | 9 +-- .../src/opentelemetry/metrics/__init__.py | 56 ++++++++-------- .../tests/metrics/test_metrics.py | 22 +++---- .../src/opentelemetry/sdk/metrics/__init__.py | 48 +++++++------- .../tests/metrics/test_metrics.py | 64 +++++++++---------- 5 files changed, 100 insertions(+), 99 deletions(-) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index 4d6dba810be..b0f12a6f5ef 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -61,10 +61,11 @@ label_set = meter.get_label_set({"environment": "staging"}) # Handle usage -# You can record metrics with bound metrics. Bound metrics are created by -# passing in a labelset. A bound metric is essentially metric data that -# corresponds to a specific set of labels. Therefore, getting a bound metric -# using the same set of labels will yield the same bound metric. + +# You can record metrics with bound metric instruments. Bound metric instruments +# are created by passing in a labelset. A bound metric is essentially metric +# data that corresponds to a specific set of labels. Therefore, getting a bound +# metric using the same set of labels will yield the same bound metric. bound_counter = counter.bind(label_set) bound_counter.add(100) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 67bdf854af0..84ddba3370e 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -37,10 +37,10 @@ ValueT = TypeVar("ValueT", int, float) -class DefaultBoundMetric: - """The default BoundMetric. +class DefaultBoundInstrument: + """The default bound metric instrument. - Used when no BoundMetric implementation is available. + Used when no bound instrument implementation is available. """ def add(self, value: ValueT) -> None: @@ -80,11 +80,11 @@ class LabelSet(abc.ABC): """A canonicalized set of labels useful for preaggregation Re-usable LabelSet objects provide a potential optimization for scenarios - where bound metrics might not be effective. For example, if the LabelSet - will be re-used but only used once per metrics, bound metrics do not offer - any optimization. It may best to pre-compute a canonicalized LabelSet once - and re-use it with the direct calling convention. LabelSets are immutable - and should be opaque in implementation. + where bound metric instruments might not be effective. For example, if the + LabelSet will be re-used but only used once per metrics, bound metric + instruments do not offer any optimization. It may best to pre-compute a + canonicalized LabelSet once and re-use it with the direct calling + convention. LabelSets are immutable and should be opaque in implementation. """ @@ -99,35 +99,34 @@ class Metric(abc.ABC): """Base class for various types of metrics. Metric class that inherit from this class are specialized with the type of - bound metric that the metric holds. + bound metric instrument that the metric holds. """ @abc.abstractmethod def bind(self, label_set: LabelSet) -> "object": """Gets a bound metric, used for repeated-use of metrics instruments. - Bound metrics are useful to reduce the cost of repeatedly recording a - metric with a pre-defined set of label values. All metric kinds - (counter, measure) support declaring a set of required label keys. The - values corresponding to these keys should be specified in every bound - metric. "Unspecified" label values, in cases where a bound metric is - requested but a value was not provided are permitted. + Bound metric instruments are useful to reduce the cost of repeatedly + recording a metric with a pre-defined set of label values. All metric + kinds (counter, measure) support declaring a set of required label keys. + The values corresponding to these keys should be specified in every + bound metric. "Unspecified" label values, in cases where a bound metric + instrument is requested but a value was not provided are permitted. - Args: - label_set: `LabelSet` to associate with the returned bound metric. + Args: label_set: `LabelSet` to associate with the returned bound metric. """ class DefaultMetric(Metric): """The default Metric used when no Metric implementation is available.""" - def bind(self, label_set: LabelSet) -> "DefaultBoundMetric": - """Gets a `DefaultBoundMetric`. + def bind(self, label_set: LabelSet) -> "DefaultBoundInstrument": + """Gets a `DefaultBoundInstrument`. Args: label_set: `LabelSet` to associate with the returned bound metric. """ - return DefaultBoundMetric() + return DefaultBoundInstrument() def add(self, value: ValueT, label_set: LabelSet) -> None: """No-op implementation of `Counter` add. @@ -283,16 +282,15 @@ def record_batch( ) -> None: """Atomically records a batch of `Metric` and value pairs. - Allows the functionality of acting upon multiple metrics with - a single API call. Implementations should find metric and bound metrics - that match the key-value pairs in the label tuples. + Allows the functionality of acting upon multiple metrics with a single + API call. Implementations should find bound metric instruments that + match the key-value pairs in the labelset. - Args: - label_set: The `LabelSet` associated with all measurements in - the batch. A measurement is a tuple, representing the `Metric` - being recorded and the corresponding value to record. - record_tuples: A sequence of pairs of `Metric` s and the - corresponding value to record for that metric. + Args: label_set: The `LabelSet` associated with all measurements in the + batch. A measurement is a tuple, representing the `Metric` being + recorded and the corresponding value to record. record_tuples: A + sequence of pairs of `Metric` s and the corresponding value to + record for that metric. """ @abc.abstractmethod diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index c7ea3638bb9..bb7ef7391b5 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -22,14 +22,14 @@ class TestMetrics(unittest.TestCase): def test_default(self): default = metrics.DefaultMetric() default_ls = metrics.DefaultLabelSet() - bound_metric = default.bind(default_ls) - self.assertIsInstance(bound_metric, metrics.DefaultBoundMetric) + bound_metric_instr = default.bind(default_ls) + self.assertIsInstance(bound_metric_instr, metrics.DefaultBoundInstrument) def test_counter(self): counter = metrics.Counter() label_set = metrics.LabelSet() - bound_metric = counter.bind(label_set) - self.assertIsInstance(bound_metric, metrics.BoundCounter) + bound_counter = counter.bind(label_set) + self.assertIsInstance(bound_counter, metrics.BoundCounter) def test_counter_add(self): counter = metrics.Counter() @@ -39,8 +39,8 @@ def test_counter_add(self): def test_measure(self): measure = metrics.Measure() label_set = metrics.LabelSet() - bound_metric = measure.bind(label_set) - self.assertIsInstance(bound_metric, metrics.BoundMeasure) + bound_measure = measure.bind(label_set) + self.assertIsInstance(bound_measure, metrics.BoundMeasure) def test_measure_record(self): measure = metrics.Measure() @@ -48,12 +48,12 @@ def test_measure_record(self): measure.record(1, label_set) def test_default_bound_metric(self): - metrics.DefaultBoundMetric() + metrics.DefaultBoundInstrument() def test_bound_counter(self): - bound_metric = metrics.BoundCounter() - bound_metric.add(1) + bound_counter = metrics.BoundCounter() + bound_counter.add(1) def test_bound_measure(self): - bound_metric = metrics.BoundMeasure() - bound_metric.record(1) + bound_measure = metrics.BoundMeasure() + bound_measure.record(1) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 350968fbbd9..4ff0cadb358 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -48,16 +48,18 @@ def __eq__(self, other): return self._encoded == other._encoded -class BaseBoundMetric: - """Class containing common behavior for all bound metrics. +class BaseBoundInstrument: + """Class containing common behavior for all bound metric instruments. - Bound metrics are responsible for operating on data for metric instruments - for a specific set of labels. + Bound metric instruments are responsible for operating on data for metric + instruments for a specific set of labels. - Args: value_type: The type of values this bound metric holds (int, float). - enabled: True if the originating instrument is enabled. aggregator: The - aggregator for this bound metric. Will handle aggregation upon updates - and checkpointing of values for exporting. + Args: + value_type: The type of values for this bound instrument (int, float). + enabled: True if the originating instrument is enabled. + aggregator: The aggregator for this bound metric instrument. Will + handle aggregation upon updates and checkpointing of values for + exporting. """ def __init__( @@ -93,14 +95,14 @@ def __repr__(self): ) -class BoundCounter(metrics_api.BoundCounter, BaseBoundMetric): +class BoundCounter(metrics_api.BoundCounter, BaseBoundInstrument): def add(self, value: metrics_api.ValueT) -> None: """See `opentelemetry.metrics.BoundCounter.add`.""" if self._validate_update(value): self.update(value) -class BoundMeasure(metrics_api.BoundMeasure, BaseBoundMetric): +class BoundMeasure(metrics_api.BoundMeasure, BaseBoundInstrument): def record(self, value: metrics_api.ValueT) -> None: """See `opentelemetry.metrics.BoundMeasure.record`.""" if self._validate_update(value): @@ -113,10 +115,10 @@ class Metric(metrics_api.Metric): Also known as metric instrument. This is the class that is used to represent a metric that is to be continuously recorded and tracked. Each metric has a set of bound metrics that are created from the metric. See - `BaseBoundMetric` for information on bound metrics. + `BaseBoundInstrument` for information on bound metric instruments. """ - BOUND_METRIC_TYPE = BaseBoundMetric + BOUND_INSTR_TYPE = BaseBoundInstrument def __init__( self, @@ -135,20 +137,20 @@ def __init__( self.meter = meter self.label_keys = label_keys self.enabled = enabled - self.bound_metrics = {} + self.bound_instruments = {} - def bind(self, label_set: LabelSet) -> BaseBoundMetric: + def bind(self, label_set: LabelSet) -> BaseBoundInstrument: """See `opentelemetry.metrics.Metric.bind`.""" - bound_metric = self.bound_metrics.get(label_set) - if not bound_metric: - bound_metric = self.BOUND_METRIC_TYPE( + bound_instrument = self.bound_instruments.get(label_set) + if not bound_instrument: + bound_instrument = self.BOUND_INSTR_TYPE( self.value_type, self.enabled, # Aggregator will be created based off type of metric self.meter.batcher.aggregator_for(self.__class__), ) - self.bound_metrics[label_set] = bound_metric - return bound_metric + self.bound_instruments[label_set] = bound_instrument + return bound_instrument def __repr__(self): return '{}(name="{}", description="{}")'.format( @@ -162,7 +164,7 @@ class Counter(Metric, metrics_api.Counter): """See `opentelemetry.metrics.Counter`. """ - BOUND_METRIC_TYPE = BoundCounter + BOUND_INSTR_TYPE = BoundCounter def add(self, value: metrics_api.ValueT, label_set: LabelSet) -> None: """See `opentelemetry.metrics.Counter.add`.""" @@ -174,7 +176,7 @@ def add(self, value: metrics_api.ValueT, label_set: LabelSet) -> None: class Measure(Metric, metrics_api.Measure): """See `opentelemetry.metrics.Measure`.""" - BOUND_METRIC_TYPE = BoundMeasure + BOUND_INSTR_TYPE = BoundMeasure def record(self, value: metrics_api.ValueT, label_set: LabelSet) -> None: """See `opentelemetry.metrics.Measure.record`.""" @@ -294,9 +296,9 @@ def collect(self) -> None: def _collect_metrics(self) -> None: for metric in self.metrics: if metric.enabled: - for label_set, bound_metric in metric.bound_metrics.items(): + for label_set, bound_instr in metric.bound_instruments.items(): # TODO: Consider storing records in memory? - record = Record(metric, label_set, bound_metric.aggregator) + record = Record(metric, label_set, bound_instr.aggregator) # Checkpoints the current aggregators # Applies different batching logic based on type of batcher self.batcher.process(record) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index 45624215d42..aefcf9da45a 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -132,11 +132,11 @@ def test_record_batch_exists(self): "name", "desc", "unit", float, meter, label_keys ) counter.add(1.0, label_set) - bound_metric = counter.bind(label_set) + bound_counter = counter.bind(label_set) record_tuples = [(counter, 1.0)] meter.record_batch(label_set, record_tuples) - self.assertEqual(counter.bind(label_set), bound_metric) - self.assertEqual(bound_metric.aggregator.current, 2.0) + self.assertEqual(counter.bind(label_set), bound_counter) + self.assertEqual(bound_counter.aggregator.current, 2.0) def test_create_metric(self): resource = mock.Mock(spec=resources.Resource) @@ -202,8 +202,8 @@ def test_bind(self): metric = _type("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) - bound_metric = metric.bind(label_set) - self.assertEqual(metric.bound_metrics.get(label_set), bound_metric) + bound_instrument = metric.bind(label_set) + self.assertEqual(metric.bound_metrics.get(label_set), bound_instrument) class TestCounter(unittest.TestCase): @@ -212,10 +212,10 @@ def test_add(self): metric = metrics.Counter("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) - bound_metric = metric.bind(label_set) + bound_counter = metric.bind(label_set) metric.add(3, label_set) metric.add(2, label_set) - self.assertEqual(bound_metric.aggregator.current, 5) + self.assertEqual(bound_counter.aggregator.current, 5) class TestMeasure(unittest.TestCase): @@ -224,12 +224,12 @@ def test_record(self): metric = metrics.Measure("name", "desc", "unit", int, meter, ("key",)) kvp = {"key": "value"} label_set = meter.get_label_set(kvp) - bound_metric = metric.bind(label_set) + bound_measure = metric.bind(label_set) values = (37, 42, 7) for val in values: metric.record(val, label_set) self.assertEqual( - bound_metric.aggregator.current, + bound_measure.aggregator.current, (min(values), max(values), sum(values), len(values)), ) @@ -309,58 +309,58 @@ def test_add(self): def test_add_disabled(self): aggregator = export.aggregate.CounterAggregator() - bound_metric = metrics.BoundCounter(int, False, aggregator) - bound_metric.add(3) - self.assertEqual(bound_metric.aggregator.current, 0) + bound_counter = metrics.BoundCounter(int, False, aggregator) + bound_counter.add(3) + self.assertEqual(bound_counter.aggregator.current, 0) @mock.patch("opentelemetry.sdk.metrics.logger") def test_add_incorrect_type(self, logger_mock): aggregator = export.aggregate.CounterAggregator() - bound_metric = metrics.BoundCounter(int, True, aggregator) - bound_metric.add(3.0) - self.assertEqual(bound_metric.aggregator.current, 0) + bound_counter = metrics.BoundCounter(int, True, aggregator) + bound_counter.add(3.0) + self.assertEqual(bound_counter.aggregator.current, 0) self.assertTrue(logger_mock.warning.called) @mock.patch("opentelemetry.sdk.metrics.time_ns") def test_update(self, time_mock): aggregator = export.aggregate.CounterAggregator() - bound_metric = metrics.BoundCounter(int, True, aggregator) + bound_counter = metrics.BoundCounter(int, True, aggregator) time_mock.return_value = 123 - bound_metric.update(4.0) - self.assertEqual(bound_metric.last_update_timestamp, 123) - self.assertEqual(bound_metric.aggregator.current, 4.0) + bound_counter.update(4.0) + self.assertEqual(bound_counter.last_update_timestamp, 123) + self.assertEqual(bound_counter.aggregator.current, 4.0) class TestBoundMeasure(unittest.TestCase): def test_record(self): aggregator = export.aggregate.MinMaxSumCountAggregator() - bound_metric = metrics.BoundMeasure(int, True, aggregator) - bound_metric.record(3) - self.assertEqual(bound_metric.aggregator.current, (3, 3, 3, 1)) + bound_measure = metrics.BoundMeasure(int, True, aggregator) + bound_measure.record(3) + self.assertEqual(bound_measure.aggregator.current, (3, 3, 3, 1)) def test_record_disabled(self): aggregator = export.aggregate.MinMaxSumCountAggregator() - bound_metric = metrics.BoundMeasure(int, False, aggregator) - bound_metric.record(3) + bound_measure = metrics.BoundMeasure(int, False, aggregator) + bound_measure.record(3) self.assertEqual( - bound_metric.aggregator.current, (None, None, None, 0) + bound_measure.aggregator.current, (None, None, None, 0) ) @mock.patch("opentelemetry.sdk.metrics.logger") def test_record_incorrect_type(self, logger_mock): aggregator = export.aggregate.MinMaxSumCountAggregator() - bound_metric = metrics.BoundMeasure(int, True, aggregator) - bound_metric.record(3.0) + bound_measure = metrics.BoundMeasure(int, True, aggregator) + bound_measure.record(3.0) self.assertEqual( - bound_metric.aggregator.current, (None, None, None, 0) + bound_measure.aggregator.current, (None, None, None, 0) ) self.assertTrue(logger_mock.warning.called) @mock.patch("opentelemetry.sdk.metrics.time_ns") def test_update(self, time_mock): aggregator = export.aggregate.MinMaxSumCountAggregator() - bound_metric = metrics.BoundMeasure(int, True, aggregator) + bound_measure = metrics.BoundMeasure(int, True, aggregator) time_mock.return_value = 123 - bound_metric.update(4.0) - self.assertEqual(bound_metric.last_update_timestamp, 123) - self.assertEqual(bound_metric.aggregator.current, (4.0, 4.0, 4.0, 1)) + bound_measure.update(4.0) + self.assertEqual(bound_measure.last_update_timestamp, 123) + self.assertEqual(bound_measure.aggregator.current, (4.0, 4.0, 4.0, 1)) From f143a35e2de55f19b004fe6c30ec204c3970151c Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 9 Mar 2020 17:03:30 -0700 Subject: [PATCH 4/8] Fix test --- opentelemetry-sdk/tests/metrics/test_metrics.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index aefcf9da45a..1d996528848 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -203,7 +203,8 @@ def test_bind(self): kvp = {"key": "value"} label_set = meter.get_label_set(kvp) bound_instrument = metric.bind(label_set) - self.assertEqual(metric.bound_metrics.get(label_set), bound_instrument) + self.assertEqual(metric.bound_instruments. \ + get(label_set), bound_instrument) class TestCounter(unittest.TestCase): From 567c8631c5a479a2e3dcf5a568bf91008c4f4af8 Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 9 Mar 2020 18:29:37 -0700 Subject: [PATCH 5/8] fix lint --- examples/metrics/record.py | 2 +- opentelemetry-sdk/tests/metrics/test_metrics.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index b0f12a6f5ef..1eee08d4f55 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -60,7 +60,7 @@ # The meter takes a dictionary of key value pairs label_set = meter.get_label_set({"environment": "staging"}) -# Handle usage +# Bound instrument usage # You can record metrics with bound metric instruments. Bound metric instruments # are created by passing in a labelset. A bound metric is essentially metric diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index 1d996528848..4e7e532d867 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -203,8 +203,9 @@ def test_bind(self): kvp = {"key": "value"} label_set = meter.get_label_set(kvp) bound_instrument = metric.bind(label_set) - self.assertEqual(metric.bound_instruments. \ - get(label_set), bound_instrument) + self.assertEqual( + metric.bound_instruments.get(label_set), bound_instrument + ) class TestCounter(unittest.TestCase): From 01341a19b18c54d194dbc06f5c7d6dd96496de51 Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 9 Mar 2020 18:47:26 -0700 Subject: [PATCH 6/8] Fix lint --- opentelemetry-api/tests/metrics/test_metrics.py | 4 +++- opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index bb7ef7391b5..9ecbede9f27 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -23,7 +23,9 @@ def test_default(self): default = metrics.DefaultMetric() default_ls = metrics.DefaultLabelSet() bound_metric_instr = default.bind(default_ls) - self.assertIsInstance(bound_metric_instr, metrics.DefaultBoundInstrument) + self.assertIsInstance( + bound_metric_instr, metrics.DefaultBoundInstrument + ) def test_counter(self): counter = metrics.Counter() diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 4ff0cadb358..7fa0bde1128 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -58,8 +58,8 @@ class BaseBoundInstrument: value_type: The type of values for this bound instrument (int, float). enabled: True if the originating instrument is enabled. aggregator: The aggregator for this bound metric instrument. Will - handle aggregation upon updates and checkpointing of values for - exporting. + handle aggregation upon updates and checkpointing of values for + exporting. """ def __init__( From 8710493efec4ef56bd00dd63a9e0b63f7acc8360 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 10 Mar 2020 00:02:31 -0700 Subject: [PATCH 7/8] Misc cosmetic fixes --- examples/metrics/record.py | 9 +++++---- .../src/opentelemetry/metrics/__init__.py | 17 ++++++++++------- .../src/opentelemetry/sdk/metrics/__init__.py | 3 +-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index 1eee08d4f55..fb4b44e7673 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -62,10 +62,11 @@ # Bound instrument usage -# You can record metrics with bound metric instruments. Bound metric instruments -# are created by passing in a labelset. A bound metric is essentially metric -# data that corresponds to a specific set of labels. Therefore, getting a bound -# metric using the same set of labels will yield the same bound metric. +# You can record metrics with bound metric instruments. Bound metric +# instruments are created by passing in a labelset. A bound metric is +# essentially metric data that corresponds to a specific set of labels. +# Therefore, getting a bound metric using the same set of labels will yield the +# same bound metric. bound_counter = counter.bind(label_set) bound_counter.add(100) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 84ddba3370e..8cd20015117 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -108,12 +108,14 @@ def bind(self, label_set: LabelSet) -> "object": Bound metric instruments are useful to reduce the cost of repeatedly recording a metric with a pre-defined set of label values. All metric - kinds (counter, measure) support declaring a set of required label keys. - The values corresponding to these keys should be specified in every - bound metric. "Unspecified" label values, in cases where a bound metric - instrument is requested but a value was not provided are permitted. - - Args: label_set: `LabelSet` to associate with the returned bound metric. + kinds (counter, measure) support declaring a set of required label + keys. The values corresponding to these keys should be specified in + every bound metric. "Unspecified" label values, in cases where a bound + metric instrument is requested but a value was not provided are + permitted. + + Args: label_set: `LabelSet` to associate with the returned bound + metric. """ @@ -181,7 +183,8 @@ def record(self, value: ValueT, label_set: LabelSet) -> None: class Observer(abc.ABC): - """An observer type metric instrument used to capture a current set of values. + """An observer type metric instrument used to capture a current set of + values. Observer instruments are asynchronous, a callback is invoked with the diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 7fa0bde1128..9c840da2984 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -13,12 +13,11 @@ # limitations under the License. import logging -from collections import OrderedDict from typing import Dict, Sequence, Tuple, Type 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.metrics.export.batcher import UngroupedBatcher from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.util.instrumentation import InstrumentationInfo from opentelemetry.util import time_ns From 01301056639a0d4d3d06f8705e2e7613465b3e91 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 10 Mar 2020 10:29:49 -0700 Subject: [PATCH 8/8] fix comments --- examples/metrics/record.py | 7 +++--- .../src/opentelemetry/metrics/__init__.py | 22 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/metrics/record.py b/examples/metrics/record.py index 1eee08d4f55..04245d66dd1 100644 --- a/examples/metrics/record.py +++ b/examples/metrics/record.py @@ -63,9 +63,10 @@ # Bound instrument usage # You can record metrics with bound metric instruments. Bound metric instruments -# are created by passing in a labelset. A bound metric is essentially metric -# data that corresponds to a specific set of labels. Therefore, getting a bound -# metric using the same set of labels will yield the same bound metric. +# are created by passing in a labelset. A bound metric instrument is +# essentially metric data that corresponds to a specific set of labels. +# Therefore, getting a bound metric instrument using the same set of labels will +# yield the same bound metric instrument. bound_counter = counter.bind(label_set) bound_counter.add(100) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 84ddba3370e..62cbdcf0659 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -47,14 +47,14 @@ def add(self, value: ValueT) -> None: """No-op implementation of `BoundCounter` add. Args: - value: The value to add to the bound metric. + value: The value to add to the bound metric instrument. """ def record(self, value: ValueT) -> None: """No-op implementation of `BoundMeasure` record. Args: - value: The value to record to the bound metric. + value: The value to record to the bound metric instrument. """ @@ -104,16 +104,18 @@ class Metric(abc.ABC): @abc.abstractmethod def bind(self, label_set: LabelSet) -> "object": - """Gets a bound metric, used for repeated-use of metrics instruments. + """Gets a bound metric instrument. Bound metric instruments are useful to reduce the cost of repeatedly recording a metric with a pre-defined set of label values. All metric kinds (counter, measure) support declaring a set of required label keys. The values corresponding to these keys should be specified in every - bound metric. "Unspecified" label values, in cases where a bound metric - instrument is requested but a value was not provided are permitted. + bound metric instrument. "Unspecified" label values, in cases where a + bound metric instrument is requested but a value was not provided are + permitted. - Args: label_set: `LabelSet` to associate with the returned bound metric. + Args: + label_set: `LabelSet` to associate with the bound instrument. """ @@ -124,7 +126,7 @@ def bind(self, label_set: LabelSet) -> "DefaultBoundInstrument": """Gets a `DefaultBoundInstrument`. Args: - label_set: `LabelSet` to associate with the returned bound metric. + label_set: `LabelSet` to associate with the bound instrument. """ return DefaultBoundInstrument() @@ -133,7 +135,7 @@ def add(self, value: ValueT, label_set: LabelSet) -> None: Args: value: The value to add to the counter metric. - label_set: `LabelSet` to associate with the returned bound metric. + label_set: `LabelSet` to associate with the bound instrument. """ def record(self, value: ValueT, label_set: LabelSet) -> None: @@ -141,7 +143,7 @@ def record(self, value: ValueT, label_set: LabelSet) -> None: Args: value: The value to record to this measure metric. - label_set: `LabelSet` to associate with the returned bound metric. + label_set: `LabelSet` to associate with the bound instrument. """ @@ -168,7 +170,7 @@ class Measure(Metric): """ def bind(self, label_set: LabelSet) -> "BoundMeasure": - """Gets a `BoundMeasure` with a float value.""" + """Gets a `BoundMeasure`.""" return BoundMeasure() def record(self, value: ValueT, label_set: LabelSet) -> None: