diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b949f8c015..004e3598add 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.11.0-0.30b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.11.0-0.30b0) - 2022-04-18 +- Rename API Measurement for async instruments to Observation + ([#2617](https://github.com/open-telemetry/opentelemetry-python/pull/2617)) - Add support for zero or more callbacks ([#2602](https://github.com/open-telemetry/opentelemetry-python/pull/2602)) - Fix parsing of trace flags when extracting traceparent diff --git a/docs/api/metrics.measurement.rst b/docs/api/metrics.observation.rst similarity index 51% rename from docs/api/metrics.measurement.rst rename to docs/api/metrics.observation.rst index d9b70aa1939..3df89ae6a5e 100644 --- a/docs/api/metrics.measurement.rst +++ b/docs/api/metrics.observation.rst @@ -1,7 +1,7 @@ -opentelemetry._metrics.measurement +opentelemetry._metrics.observation ================================== -.. automodule:: opentelemetry._metrics.measurement +.. automodule:: opentelemetry._metrics.observation :members: :undoc-members: :show-inheritance: diff --git a/docs/api/metrics.rst b/docs/api/metrics.rst index d4e29b624bc..08c4cbcc708 100644 --- a/docs/api/metrics.rst +++ b/docs/api/metrics.rst @@ -14,7 +14,7 @@ Submodules .. toctree:: metrics.instrument - metrics.measurement + metrics.observation Module contents --------------- diff --git a/docs/examples/metrics/example.py b/docs/examples/metrics/example.py index 60165c67558..0c4db25cf0e 100644 --- a/docs/examples/metrics/example.py +++ b/docs/examples/metrics/example.py @@ -1,7 +1,7 @@ from typing import Iterable from opentelemetry._metrics import get_meter_provider, set_meter_provider -from opentelemetry._metrics.measurement import Measurement +from opentelemetry._metrics.observation import Observation from opentelemetry.exporter.otlp.proto.grpc._metric_exporter import ( OTLPMetricExporter, ) @@ -14,16 +14,16 @@ set_meter_provider(provider) -def observable_counter_func() -> Iterable[Measurement]: - yield Measurement(1, {}) +def observable_counter_func() -> Iterable[Observation]: + yield Observation(1, {}) -def observable_up_down_counter_func() -> Iterable[Measurement]: - yield Measurement(-10, {}) +def observable_up_down_counter_func() -> Iterable[Observation]: + yield Observation(-10, {}) -def observable_gauge_func() -> Iterable[Measurement]: - yield Measurement(9, {}) +def observable_gauge_func() -> Iterable[Observation]: + yield Observation(9, {}) meter = get_meter_provider().get_meter("getting-started", "0.1.2") diff --git a/docs/getting_started/metrics_example.py b/docs/getting_started/metrics_example.py index c763e3855c1..2a7199b99c5 100644 --- a/docs/getting_started/metrics_example.py +++ b/docs/getting_started/metrics_example.py @@ -18,7 +18,7 @@ from typing import Iterable from opentelemetry._metrics import get_meter_provider, set_meter_provider -from opentelemetry._metrics.measurement import Measurement +from opentelemetry._metrics.observation import Observation from opentelemetry.sdk._metrics import MeterProvider from opentelemetry.sdk._metrics.export import ( ConsoleMetricExporter, @@ -31,16 +31,16 @@ set_meter_provider(provider) -def observable_counter_func() -> Iterable[Measurement]: - yield Measurement(1, {}) +def observable_counter_func() -> Iterable[Observation]: + yield Observation(1, {}) -def observable_up_down_counter_func() -> Iterable[Measurement]: - yield Measurement(-10, {}) +def observable_up_down_counter_func() -> Iterable[Observation]: + yield Observation(-10, {}) -def observable_gauge_func() -> Iterable[Measurement]: - yield Measurement(9, {}) +def observable_gauge_func() -> Iterable[Observation]: + yield Observation(9, {}) meter = get_meter_provider().get_meter("getting-started", "0.1.2") diff --git a/opentelemetry-api/src/opentelemetry/_metrics/__init__.py b/opentelemetry-api/src/opentelemetry/_metrics/__init__.py index 8e23eef18f2..a42cfd53f37 100644 --- a/opentelemetry-api/src/opentelemetry/_metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/_metrics/__init__.py @@ -227,7 +227,7 @@ def create_counter( Args: name: The name of the instrument to be created - unit: The unit for measurements this instrument reports. For + unit: The unit for observations this instrument reports. For example, ``By`` for bytes. UCUM units are recommended. description: A description for this instrument and what it measures. """ @@ -240,7 +240,7 @@ def create_up_down_counter( Args: name: The name of the instrument to be created - unit: The unit for measurements this instrument reports. For + unit: The unit for observations this instrument reports. For example, ``By`` for bytes. UCUM units are recommended. description: A description for this instrument and what it measures. """ @@ -253,23 +253,23 @@ def create_observable_counter( An observable counter observes a monotonically increasing count by calling provided callbacks which returns multiple - :class:`~opentelemetry._metrics.measurement.Measurement`. + :class:`~opentelemetry._metrics.observation.Observation`. For example, an observable counter could be used to report system CPU time periodically. Here is a basic implementation:: - def cpu_time_callback() -> Iterable[Measurement]: - measurements = [] + def cpu_time_callback() -> Iterable[Observation]: + observations = [] with open("/proc/stat") as procstat: procstat.readline() # skip the first line for line in procstat: if not line.startswith("cpu"): break cpu, *states = line.split() - measurements.append(Measurement(int(states[0]) // 100, {"cpu": cpu, "state": "user"})) - measurements.append(Measurement(int(states[1]) // 100, {"cpu": cpu, "state": "nice"})) - measurements.append(Measurement(int(states[2]) // 100, {"cpu": cpu, "state": "system"})) + observations.append(Observation(int(states[0]) // 100, {"cpu": cpu, "state": "user"})) + observations.append(Observation(int(states[1]) // 100, {"cpu": cpu, "state": "nice"})) + observations.append(Observation(int(states[2]) // 100, {"cpu": cpu, "state": "system"})) # ... other states - return measurements + return observations meter.create_observable_counter( "system.cpu.time", @@ -281,34 +281,34 @@ def cpu_time_callback() -> Iterable[Measurement]: To reduce memory usage, you can use generator callbacks instead of building the full list:: - def cpu_time_callback() -> Iterable[Measurement]: + def cpu_time_callback() -> Iterable[Observation]: with open("/proc/stat") as procstat: procstat.readline() # skip the first line for line in procstat: if not line.startswith("cpu"): break cpu, *states = line.split() - yield Measurement(int(states[0]) // 100, {"cpu": cpu, "state": "user"}) - yield Measurement(int(states[1]) // 100, {"cpu": cpu, "state": "nice"}) + yield Observation(int(states[0]) // 100, {"cpu": cpu, "state": "user"}) + yield Observation(int(states[1]) // 100, {"cpu": cpu, "state": "nice"}) # ... other states Alternatively, you can pass a sequence of generators directly instead of a sequence of callbacks, which each should return iterables of - :class:`~opentelemetry._metrics.measurement.Measurement`:: + :class:`~opentelemetry._metrics.observation.Observation`:: - def cpu_time_callback(states_to_include: set[str]) -> Iterable[Iterable[Measurement]]: + def cpu_time_callback(states_to_include: set[str]) -> Iterable[Iterable[Observation]]: while True: - measurements = [] + observations = [] with open("/proc/stat") as procstat: procstat.readline() # skip the first line for line in procstat: if not line.startswith("cpu"): break cpu, *states = line.split() if "user" in states_to_include: - measurements.append(Measurement(int(states[0]) // 100, {"cpu": cpu, "state": "user"})) + observations.append(Observation(int(states[0]) // 100, {"cpu": cpu, "state": "user"})) if "nice" in states_to_include: - measurements.append(Measurement(int(states[1]) // 100, {"cpu": cpu, "state": "nice"})) + observations.append(Observation(int(states[1]) // 100, {"cpu": cpu, "state": "nice"})) # ... other states - yield measurements + yield observations meter.create_observable_counter( "system.cpu.time", @@ -320,11 +320,11 @@ def cpu_time_callback(states_to_include: set[str]) -> Iterable[Iterable[Measurem Args: name: The name of the instrument to be created callbacks: A sequence of callbacks that return an iterable of - :class:`~opentelemetry._metrics.measurement.Measurement`. + :class:`~opentelemetry._metrics.observation.Observation`. Alternatively, can be a sequence of generators that each yields iterables of - :class:`~opentelemetry._metrics.measurement.Measurement`. - unit: The unit for measurements this instrument reports. For + :class:`~opentelemetry._metrics.observation.Observation`. + unit: The unit for observations this instrument reports. For example, ``By`` for bytes. UCUM units are recommended. description: A description for this instrument and what it measures. """ @@ -335,7 +335,7 @@ def create_histogram(self, name, unit="", description="") -> Histogram: Args: name: The name of the instrument to be created - unit: The unit for measurements this instrument reports. For + unit: The unit for observations this instrument reports. For example, ``By`` for bytes. UCUM units are recommended. description: A description for this instrument and what it measures. """ @@ -349,10 +349,10 @@ def create_observable_gauge( Args: name: The name of the instrument to be created callbacks: A sequence of callbacks that return an iterable of - :class:`~opentelemetry._metrics.measurement.Measurement`. + :class:`~opentelemetry._metrics.observation.Observation`. Alternatively, can be a generator that yields iterables of - :class:`~opentelemetry._metrics.measurement.Measurement`. - unit: The unit for measurements this instrument reports. For + :class:`~opentelemetry._metrics.observation.Observation`. + unit: The unit for observations this instrument reports. For example, ``By`` for bytes. UCUM units are recommended. description: A description for this instrument and what it measures. """ @@ -366,10 +366,10 @@ def create_observable_up_down_counter( Args: name: The name of the instrument to be created callbacks: A sequence of callbacks that return an iterable of - :class:`~opentelemetry._metrics.measurement.Measurement`. + :class:`~opentelemetry._metrics.observation.Observation`. Alternatively, can be a generator that yields iterables of - :class:`~opentelemetry._metrics.measurement.Measurement`. - unit: The unit for measurements this instrument reports. For + :class:`~opentelemetry._metrics.observation.Observation`. + unit: The unit for observations this instrument reports. For example, ``By`` for bytes. UCUM units are recommended. description: A description for this instrument and what it measures. """ diff --git a/opentelemetry-api/src/opentelemetry/_metrics/instrument.py b/opentelemetry-api/src/opentelemetry/_metrics/instrument.py index 87e9d33f5d3..0718a312e85 100644 --- a/opentelemetry-api/src/opentelemetry/_metrics/instrument.py +++ b/opentelemetry-api/src/opentelemetry/_metrics/instrument.py @@ -30,12 +30,12 @@ # pylint: disable=unused-import; needed for typing and sphinx from opentelemetry import _metrics as metrics -from opentelemetry._metrics.measurement import Measurement +from opentelemetry._metrics.observation import Observation InstrumentT = TypeVar("InstrumentT", bound="Instrument") CallbackT = Union[ - Callable[[], Iterable[Measurement]], - Generator[Iterable[Measurement], None, None], + Callable[[], Iterable[Observation]], + Generator[Iterable[Observation], None, None], ] diff --git a/opentelemetry-api/src/opentelemetry/_metrics/measurement.py b/opentelemetry-api/src/opentelemetry/_metrics/observation.py similarity index 92% rename from opentelemetry-api/src/opentelemetry/_metrics/measurement.py rename to opentelemetry-api/src/opentelemetry/_metrics/observation.py index e8fd9725bb8..7aa24e3342d 100644 --- a/opentelemetry-api/src/opentelemetry/_metrics/measurement.py +++ b/opentelemetry-api/src/opentelemetry/_metrics/observation.py @@ -17,7 +17,7 @@ from opentelemetry.util.types import Attributes -class Measurement: +class Observation: """A measurement observed in an asynchronous instrument Return/yield instances of this class from asynchronous instrument callbacks. @@ -43,10 +43,10 @@ def attributes(self) -> Attributes: def __eq__(self, other: object) -> bool: return ( - isinstance(other, Measurement) + isinstance(other, Observation) and self.value == other.value and self.attributes == other.attributes ) def __repr__(self) -> str: - return f"Measurement(value={self.value}, attributes={self.attributes})" + return f"Observation(value={self.value}, attributes={self.attributes})" diff --git a/opentelemetry-api/tests/metrics/test_measurement.py b/opentelemetry-api/tests/metrics/test_measurement.py index 8791bc1a2fa..295c5b9a6be 100644 --- a/opentelemetry-api/tests/metrics/test_measurement.py +++ b/opentelemetry-api/tests/metrics/test_measurement.py @@ -14,33 +14,33 @@ from unittest import TestCase -from opentelemetry._metrics.measurement import Measurement +from opentelemetry._metrics.observation import Observation -class TestMeasurement(TestCase): +class TestObservation(TestCase): def test_measurement_init(self): try: # int - Measurement(321, {"hello": "world"}) + Observation(321, {"hello": "world"}) # float - Measurement(321.321, {"hello": "world"}) + Observation(321.321, {"hello": "world"}) except Exception: # pylint: disable=broad-except self.fail( - "Unexpected exception raised when instantiating Measurement" + "Unexpected exception raised when instantiating Observation" ) def test_measurement_equality(self): self.assertEqual( - Measurement(321, {"hello": "world"}), - Measurement(321, {"hello": "world"}), + Observation(321, {"hello": "world"}), + Observation(321, {"hello": "world"}), ) self.assertNotEqual( - Measurement(321, {"hello": "world"}), - Measurement(321.321, {"hello": "world"}), + Observation(321, {"hello": "world"}), + Observation(321.321, {"hello": "world"}), ) self.assertNotEqual( - Measurement(321, {"baz": "world"}), - Measurement(321, {"hello": "world"}), + Observation(321, {"baz": "world"}), + Observation(321, {"hello": "world"}), ) diff --git a/opentelemetry-sdk/tests/metrics/integration_test/test_cpu_time.py b/opentelemetry-sdk/tests/metrics/integration_test/test_cpu_time.py index b21091c3c8f..e8c541c090d 100644 --- a/opentelemetry-sdk/tests/metrics/integration_test/test_cpu_time.py +++ b/opentelemetry-sdk/tests/metrics/integration_test/test_cpu_time.py @@ -18,7 +18,7 @@ from unittest import TestCase from opentelemetry._metrics.instrument import Instrument -from opentelemetry._metrics.measurement import Measurement as APIMeasurement +from opentelemetry._metrics.observation import Observation from opentelemetry.sdk._metrics import MeterProvider from opentelemetry.sdk._metrics.measurement import Measurement @@ -139,38 +139,38 @@ def create_measurements_expected( ] def test_cpu_time_callback(self): - def cpu_time_callback() -> Iterable[APIMeasurement]: + def cpu_time_callback() -> Iterable[Observation]: procstat = io.StringIO(self.procstat_str) procstat.readline() # skip the first line for line in procstat: if not line.startswith("cpu"): break cpu, *states = line.split() - yield APIMeasurement( + yield Observation( int(states[0]) / 100, {"cpu": cpu, "state": "user"} ) - yield APIMeasurement( + yield Observation( int(states[1]) / 100, {"cpu": cpu, "state": "nice"} ) - yield APIMeasurement( + yield Observation( int(states[2]) / 100, {"cpu": cpu, "state": "system"} ) - yield APIMeasurement( + yield Observation( int(states[3]) / 100, {"cpu": cpu, "state": "idle"} ) - yield APIMeasurement( + yield Observation( int(states[4]) / 100, {"cpu": cpu, "state": "iowait"} ) - yield APIMeasurement( + yield Observation( int(states[5]) / 100, {"cpu": cpu, "state": "irq"} ) - yield APIMeasurement( + yield Observation( int(states[6]) / 100, {"cpu": cpu, "state": "softirq"} ) - yield APIMeasurement( + yield Observation( int(states[7]) / 100, {"cpu": cpu, "state": "guest"} ) - yield APIMeasurement( + yield Observation( int(states[8]) / 100, {"cpu": cpu, "state": "guest_nice"} ) @@ -188,7 +188,7 @@ def cpu_time_callback() -> Iterable[APIMeasurement]: def test_cpu_time_generator(self): def cpu_time_generator() -> Generator[ - Iterable[APIMeasurement], None, None + Iterable[Observation], None, None ]: while True: measurements = [] @@ -199,54 +199,54 @@ def cpu_time_generator() -> Generator[ break cpu, *states = line.split() measurements.append( - APIMeasurement( + Observation( int(states[0]) / 100, {"cpu": cpu, "state": "user"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[1]) / 100, {"cpu": cpu, "state": "nice"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[2]) / 100, {"cpu": cpu, "state": "system"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[3]) / 100, {"cpu": cpu, "state": "idle"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[4]) / 100, {"cpu": cpu, "state": "iowait"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[5]) / 100, {"cpu": cpu, "state": "irq"} ) ) measurements.append( - APIMeasurement( + Observation( int(states[6]) / 100, {"cpu": cpu, "state": "softirq"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[7]) / 100, {"cpu": cpu, "state": "guest"}, ) ) measurements.append( - APIMeasurement( + Observation( int(states[8]) / 100, {"cpu": cpu, "state": "guest_nice"}, ) diff --git a/opentelemetry-sdk/tests/metrics/test_in_memory_metric_reader.py b/opentelemetry-sdk/tests/metrics/test_in_memory_metric_reader.py index fcafea38db9..89d39b5e2d4 100644 --- a/opentelemetry-sdk/tests/metrics/test_in_memory_metric_reader.py +++ b/opentelemetry-sdk/tests/metrics/test_in_memory_metric_reader.py @@ -15,7 +15,7 @@ from unittest import TestCase from unittest.mock import Mock -from opentelemetry._metrics.measurement import Measurement +from opentelemetry._metrics.observation import Observation from opentelemetry.sdk._metrics import MeterProvider from opentelemetry.sdk._metrics.export import InMemoryMetricReader from opentelemetry.sdk._metrics.point import ( @@ -70,7 +70,7 @@ def test_integration(self): meter = MeterProvider(metric_readers=[reader]).get_meter("test_meter") counter1 = meter.create_counter("counter1") meter.create_observable_gauge( - "observable_gauge1", callbacks=[lambda: [Measurement(value=12)]] + "observable_gauge1", callbacks=[lambda: [Observation(value=12)]] ) counter1.add(1, {"foo": "1"}) counter1.add(1, {"foo": "2"}) diff --git a/opentelemetry-sdk/tests/metrics/test_instrument.py b/opentelemetry-sdk/tests/metrics/test_instrument.py index b52216560f9..ba792842a1e 100644 --- a/opentelemetry-sdk/tests/metrics/test_instrument.py +++ b/opentelemetry-sdk/tests/metrics/test_instrument.py @@ -15,7 +15,7 @@ from unittest import TestCase from unittest.mock import Mock -from opentelemetry._metrics.measurement import Measurement as APIMeasurement +from opentelemetry._metrics.observation import Observation from opentelemetry.sdk._metrics.instrument import ( Counter, Histogram, @@ -60,33 +60,33 @@ def test_add_non_monotonic(self): def callable_callback_0(): return [ - APIMeasurement(1, attributes=TEST_ATTRIBUTES), - APIMeasurement(2, attributes=TEST_ATTRIBUTES), - APIMeasurement(3, attributes=TEST_ATTRIBUTES), + Observation(1, attributes=TEST_ATTRIBUTES), + Observation(2, attributes=TEST_ATTRIBUTES), + Observation(3, attributes=TEST_ATTRIBUTES), ] def callable_callback_1(): return [ - APIMeasurement(4, attributes=TEST_ATTRIBUTES), - APIMeasurement(5, attributes=TEST_ATTRIBUTES), - APIMeasurement(6, attributes=TEST_ATTRIBUTES), + Observation(4, attributes=TEST_ATTRIBUTES), + Observation(5, attributes=TEST_ATTRIBUTES), + Observation(6, attributes=TEST_ATTRIBUTES), ] def generator_callback_0(): yield [ - APIMeasurement(1, attributes=TEST_ATTRIBUTES), - APIMeasurement(2, attributes=TEST_ATTRIBUTES), - APIMeasurement(3, attributes=TEST_ATTRIBUTES), + Observation(1, attributes=TEST_ATTRIBUTES), + Observation(2, attributes=TEST_ATTRIBUTES), + Observation(3, attributes=TEST_ATTRIBUTES), ] def generator_callback_1(): yield [ - APIMeasurement(4, attributes=TEST_ATTRIBUTES), - APIMeasurement(5, attributes=TEST_ATTRIBUTES), - APIMeasurement(6, attributes=TEST_ATTRIBUTES), + Observation(4, attributes=TEST_ATTRIBUTES), + Observation(5, attributes=TEST_ATTRIBUTES), + Observation(6, attributes=TEST_ATTRIBUTES), ]