From 6a25608ebef6bf3214ad8b0df64541a52d8b83cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Collonval?= Date: Wed, 14 Aug 2024 10:29:46 +0200 Subject: [PATCH] Add first test focusing on exemplar --- .../src/opentelemetry/sdk/metrics/__init__.py | 10 +++++ .../sdk/metrics/_internal/__init__.py | 2 +- .../integration_test/test_console_exporter.py | 43 ++++++++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 204b0155728..a92d60cfb94 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -16,8 +16,13 @@ from opentelemetry.sdk.metrics._internal import Meter, MeterProvider from opentelemetry.sdk.metrics._internal.exceptions import MetricsTimeoutError from opentelemetry.sdk.metrics._internal.exemplar import ( + AlignedHistogramBucketExemplarReservoir, + AlwaysOnExemplarFilter, + AlwaysOffExemplarFilter, ExemplarFilter, ExemplarReservoir, + SimpleFixedSizeExemplarReservoir, + TraceBasedExemplarFilter, ) from opentelemetry.sdk.metrics._internal.instrument import Counter from opentelemetry.sdk.metrics._internal.instrument import Gauge as _Gauge @@ -30,6 +35,9 @@ ) __all__ = [ + "AlignedHistogramBucketExemplarReservoir", + "AlwaysOnExemplarFilter", + "AlwaysOffExemplarFilter", "ExemplarFilter", "ExemplarReservoir", "Meter", @@ -41,5 +49,7 @@ "ObservableCounter", "ObservableGauge", "ObservableUpDownCounter", + "SimpleFixedSizeExemplarReservoir", "UpDownCounter", + "TraceBasedExemplarFilter", ] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py index 1e96f0b4b65..5a2e428965d 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py @@ -384,7 +384,7 @@ def __init__( metric_readers: Sequence[ "opentelemetry.sdk.metrics.export.MetricReader" ] = (), - resource: Resource = None, + resource: Optional[Resource] = None, exemplar_filter: Optional[ExemplarFilter] = None, shutdown_on_exit: bool = True, views: Sequence["opentelemetry.sdk.metrics.view.View"] = (), diff --git a/opentelemetry-sdk/tests/metrics/integration_test/test_console_exporter.py b/opentelemetry-sdk/tests/metrics/integration_test/test_console_exporter.py index 1b3283717ae..2d3f37736ae 100644 --- a/opentelemetry-sdk/tests/metrics/integration_test/test_console_exporter.py +++ b/opentelemetry-sdk/tests/metrics/integration_test/test_console_exporter.py @@ -15,9 +15,11 @@ from io import StringIO from json import loads from unittest import TestCase +from unittest.mock import Mock, patch +from opentelemetry.context import Context from opentelemetry.metrics import get_meter, set_meter_provider -from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.metrics import AlwaysOnExemplarFilter, MeterProvider from opentelemetry.sdk.metrics.export import ( ConsoleMetricExporter, PeriodicExportingMetricReader, @@ -25,6 +27,9 @@ from opentelemetry.test.globals_test import reset_metrics_globals +TEST_TIMESTAMP = 1_234_567_890 + + class TestConsoleExporter(TestCase): def setUp(self): reset_metrics_globals() @@ -88,3 +93,39 @@ def test_console_exporter_no_export(self): expected = "" self.assertEqual(actual, expected) + + @patch( + "opentelemetry.sdk.metrics._internal.instrument.time_ns", + Mock(return_value=TEST_TIMESTAMP), + ) + def test_console_exporter_with_exemplars(self): + ctx = Context() + + output = StringIO() + exporter = ConsoleMetricExporter(out=output) + reader = PeriodicExportingMetricReader( + exporter, export_interval_millis=100 + ) + provider = MeterProvider(metric_readers=[reader], exemplar_filter=AlwaysOnExemplarFilter()) + set_meter_provider(provider) + meter = get_meter(__name__) + counter = meter.create_counter( + "name", description="description", unit="unit" + ) + counter.add(1, attributes={"a": "b"}, context=ctx) + provider.shutdown() + + output.seek(0) + result_0 = loads("".join(output.readlines())) + + self.assertGreater(len(result_0), 0) + + metrics = result_0["resource_metrics"][0]["scope_metrics"][0] + + self.assertEqual(metrics["scope"]["name"], "test_console_exporter") + + point = metrics["metrics"][0]["data"]["data_points"][0] + + self.assertEqual(point["attributes"], {"a": "b"}) + self.assertEqual(point["value"], 1) + self.assertEqual(point["exemplars"], [{"filtered_attributes": {}, "value": 1, "time_unix_nano": TEST_TIMESTAMP, "span_id": None, "trace_id": None}])