From 8ceb131c8844dc944e7a121fb071974cbb349463 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Mon, 16 Feb 2026 23:07:08 -0500 Subject: [PATCH 1/4] feat: add support for metric data-point flags --- .../_internal/metrics_encoder/__init__.py | 5 ++- .../tests/test_metrics_encoder.py | 20 ++++++++-- .../sdk/metrics/_internal/aggregation.py | 9 +++-- .../sdk/metrics/_internal/point.py | 37 ++++++++++++++++++- .../sdk/metrics/export/__init__.py | 2 + opentelemetry-sdk/tests/metrics/test_point.py | 35 +++++++++++++++--- .../src/opentelemetry/test/metrictestutil.py | 14 ++++++- 7 files changed, 106 insertions(+), 16 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/metrics_encoder/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/metrics_encoder/__init__.py index 3ea2e26dcb9..15872b4cedf 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/metrics_encoder/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/metrics_encoder/__init__.py @@ -252,6 +252,7 @@ def _encode_metric(metric, pb2_metric): attributes=_encode_attributes(data_point.attributes), time_unix_nano=data_point.time_unix_nano, exemplars=_encode_exemplars(data_point.exemplars), + flags=int(data_point.flags), ) if isinstance(data_point.value, int): pt.as_int = data_point.value @@ -272,6 +273,7 @@ def _encode_metric(metric, pb2_metric): explicit_bounds=data_point.explicit_bounds, max=data_point.max, min=data_point.min, + flags=int(data_point.flags), ) pb2_metric.histogram.aggregation_temporality = ( metric.data.aggregation_temporality @@ -285,6 +287,7 @@ def _encode_metric(metric, pb2_metric): start_time_unix_nano=data_point.start_time_unix_nano, time_unix_nano=data_point.time_unix_nano, exemplars=_encode_exemplars(data_point.exemplars), + flags=int(data_point.flags), ) if isinstance(data_point.value, int): pt.as_int = data_point.value @@ -328,9 +331,9 @@ def _encode_metric(metric, pb2_metric): zero_count=data_point.zero_count, positive=positive, negative=negative, - flags=data_point.flags, max=data_point.max, min=data_point.min, + flags=int(data_point.flags), ) pb2_metric.exponential_histogram.aggregation_temporality = ( metric.data.aggregation_temporality diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py index d2ef292f93a..d64795d0a36 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py @@ -37,6 +37,7 @@ from opentelemetry.sdk.metrics.export import ( AggregationTemporality, Buckets, + DataPointFlags, ExponentialHistogramDataPoint, HistogramDataPoint, Metric, @@ -91,6 +92,7 @@ class TestOTLPMetricsEncoder(unittest.TestCase): explicit_bounds=[10.0, 20.0], min=8, max=18, + flags=DataPointFlags.get_default(), ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -112,7 +114,13 @@ def test_encode_sum_int(self): version="first_version", schema_url="instrumentation_scope_schema_url", ), - metrics=[_generate_sum("sum_int", 33)], + metrics=[ + _generate_sum( + "sum_int", + 33, + flags=DataPointFlags.get_default(), + ) + ], schema_url="instrumentation_scope_schema_url", ) ], @@ -163,6 +171,7 @@ def test_encode_sum_int(self): start_time_unix_nano=1641946015139533244, time_unix_nano=1641946016139533244, as_int=33, + flags=DataPointFlags.DEFAULT, ) ], aggregation_temporality=AggregationTemporality.CUMULATIVE, @@ -515,6 +524,7 @@ def test_encode_histogram(self): ], max=18.0, min=8.0, + flags=DataPointFlags.DEFAULT, ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -646,6 +656,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, + flags=DataPointFlags.DEFAULT, ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -708,6 +719,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, + flags=DataPointFlags.DEFAULT, ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -778,6 +790,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, + flags=DataPointFlags.DEFAULT, ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -848,6 +861,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, + flags=DataPointFlags.DEFAULT, ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -879,7 +893,7 @@ def test_encode_exponential_histogram(self): zero_count=5, positive=Buckets(offset=6, bucket_counts=[7, 8]), negative=Buckets(offset=9, bucket_counts=[10, 11]), - flags=12, + flags=DataPointFlags.get_default(), min=13.0, max=14.0, ) @@ -964,7 +978,7 @@ def test_encode_exponential_histogram(self): offset=9, bucket_counts=[10, 11], ), - flags=12, + flags=DataPointFlags.DEFAULT, exemplars=[], min=13.0, max=14.0, diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py index 1779dac0bba..c7f450ca5d5 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py @@ -62,6 +62,7 @@ from opentelemetry.sdk.metrics._internal.measurement import Measurement from opentelemetry.sdk.metrics._internal.point import Buckets as BucketsPoint from opentelemetry.sdk.metrics._internal.point import ( + DataPointFlags, ExponentialHistogramDataPoint, HistogramDataPoint, NumberDataPoint, @@ -887,10 +888,10 @@ def collect( offset=value_negative.offset, bucket_counts=(value_negative.get_offset_counts()), ), - # FIXME: Find the right value for flags - flags=0, min=min_, max=max_, + # FIXME: Find the right value for flags + flags=DataPointFlags.get_default(), ) # Here collection_temporality is CUMULATIVE. @@ -1055,10 +1056,10 @@ def collect( self._previous_value_negative.get_offset_counts() ), ), - # FIXME: Find the right value for flags - flags=0, min=self._previous_min, max=self._previous_max, + # FIXME: Find the right value for flags + flags=DataPointFlags.get_default(), ) return None diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py index 8c7e3469772..8f8cc6ba22a 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py @@ -26,6 +26,39 @@ from opentelemetry.util.types import Attributes +class DataPointFlags(int): + """A bitmask that represents options specific to the data point. + + The only supported option is the "no recorded value" flag (``0x01``). If + set, this flag reflects explicitly missing data in a series. It serves as + an indicator that a previously present timeseries was removed and that + this timeseries SHOULD NOT be returned in queries after such an indicator + was received. It is an equivalent of the Prometheus staleness marker. + + If this flag is set, all other data point properties except attributes, + time stamps, or time windows, SHOULD be ignored. + + See the `OpenTelemetry Data Point Flags`_ spec for details. + + .. _OpenTelemetry Data Point Flags: + https://opentelemetry.io/docs/specs/otel/metrics/data-model/#data-point-flags + """ + + DEFAULT = 0x00 + NO_RECORDED_VALUE = 0x01 + + @classmethod + def get_default(cls) -> "DataPointFlags": + return cls(cls.DEFAULT) + + @property + def no_recorded_value(self) -> bool: + return bool(self & self.NO_RECORDED_VALUE) + + +DEFAULT_DATA_POINT_FLAGS = DataPointFlags.get_default() + + @dataclass(frozen=True) class NumberDataPoint: """Single data point in a timeseries that describes the time-varying scalar @@ -37,6 +70,7 @@ class NumberDataPoint: time_unix_nano: int value: Union[int, float] exemplars: Sequence[Exemplar] = field(default_factory=list) + flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS def to_json(self, indent: Optional[int] = 4) -> str: return dumps(asdict(self), indent=indent) @@ -58,6 +92,7 @@ class HistogramDataPoint: min: float max: float exemplars: Sequence[Exemplar] = field(default_factory=list) + flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS def to_json(self, indent: Optional[int] = 4) -> str: return dumps(asdict(self), indent=indent) @@ -85,10 +120,10 @@ class ExponentialHistogramDataPoint: zero_count: int positive: Buckets negative: Buckets - flags: int min: float max: float exemplars: Sequence[Exemplar] = field(default_factory=list) + flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS def to_json(self, indent: Optional[int] = 4) -> str: return dumps(asdict(self), indent=indent) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py index 1b6d27e3e01..36812427a9c 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py @@ -28,6 +28,7 @@ # The point module is not in the export directory to avoid a circular import. from opentelemetry.sdk.metrics._internal.point import ( # noqa: F401 Buckets, + DataPointFlags, DataPointT, DataT, ExponentialHistogram, @@ -52,6 +53,7 @@ "MetricExportResult", "MetricReader", "PeriodicExportingMetricReader", + "DataPointFlags", "DataPointT", "DataT", "ExponentialHistogram", diff --git a/opentelemetry-sdk/tests/metrics/test_point.py b/opentelemetry-sdk/tests/metrics/test_point.py index c5a4def85de..5ec2ca4def6 100644 --- a/opentelemetry-sdk/tests/metrics/test_point.py +++ b/opentelemetry-sdk/tests/metrics/test_point.py @@ -17,6 +17,7 @@ from opentelemetry.sdk.metrics.export import ( AggregationTemporality, Buckets, + DataPointFlags, ExponentialHistogram, ExponentialHistogramDataPoint, Gauge, @@ -66,15 +67,16 @@ def setUpClass(cls): time_unix_nano=2, value=3.3, ) - cls.number_data_point_0_str = f'{{"attributes": {cls.attributes_0_str}, "start_time_unix_nano": 1, "time_unix_nano": 2, "value": 3.3, "exemplars": []}}' + cls.number_data_point_0_str = f'{{"attributes": {cls.attributes_0_str}, "start_time_unix_nano": 1, "time_unix_nano": 2, "value": 3.3, "exemplars": [], "flags": {DataPointFlags.get_default()}}}' cls.number_data_point_1 = NumberDataPoint( attributes=cls.attributes_1, start_time_unix_nano=2, time_unix_nano=3, value=4.4, + flags=DataPointFlags(DataPointFlags.NO_RECORDED_VALUE), ) - cls.number_data_point_1_str = f'{{"attributes": {cls.attributes_1_str}, "start_time_unix_nano": 2, "time_unix_nano": 3, "value": 4.4, "exemplars": []}}' + cls.number_data_point_1_str = f'{{"attributes": {cls.attributes_1_str}, "start_time_unix_nano": 2, "time_unix_nano": 3, "value": 4.4, "exemplars": [], "flags": {DataPointFlags.NO_RECORDED_VALUE}}}' cls.histogram_data_point_0 = HistogramDataPoint( attributes=cls.attributes_0, @@ -87,7 +89,7 @@ def setUpClass(cls): min=0.2, max=3.3, ) - cls.histogram_data_point_0_str = f'{{"attributes": {cls.attributes_0_str}, "start_time_unix_nano": 1, "time_unix_nano": 2, "count": 3, "sum": 3.3, "bucket_counts": [1, 1, 1], "explicit_bounds": [0.1, 1.2, 2.3, 3.4], "min": 0.2, "max": 3.3, "exemplars": []}}' + cls.histogram_data_point_0_str = f'{{"attributes": {cls.attributes_0_str}, "start_time_unix_nano": 1, "time_unix_nano": 2, "count": 3, "sum": 3.3, "bucket_counts": [1, 1, 1], "explicit_bounds": [0.1, 1.2, 2.3, 3.4], "min": 0.2, "max": 3.3, "exemplars": [], "flags": {DataPointFlags.get_default()}}}' cls.histogram_data_point_1 = HistogramDataPoint( attributes=cls.attributes_1, @@ -99,8 +101,9 @@ def setUpClass(cls): explicit_bounds=[1.2, 2.3, 3.4, 4.5], min=0.3, max=4.4, + flags=DataPointFlags(DataPointFlags.NO_RECORDED_VALUE), ) - cls.histogram_data_point_1_str = f'{{"attributes": {cls.attributes_1_str}, "start_time_unix_nano": 2, "time_unix_nano": 3, "count": 4, "sum": 4.4, "bucket_counts": [2, 1, 1], "explicit_bounds": [1.2, 2.3, 3.4, 4.5], "min": 0.3, "max": 4.4, "exemplars": []}}' + cls.histogram_data_point_1_str = f'{{"attributes": {cls.attributes_1_str}, "start_time_unix_nano": 2, "time_unix_nano": 3, "count": 4, "sum": 4.4, "bucket_counts": [2, 1, 1], "explicit_bounds": [1.2, 2.3, 3.4, 4.5], "min": 0.3, "max": 4.4, "exemplars": [], "flags": {DataPointFlags.NO_RECORDED_VALUE}}}' cls.exp_histogram_data_point_0 = ExponentialHistogramDataPoint( attributes=cls.attributes_0, @@ -112,11 +115,27 @@ def setUpClass(cls): zero_count=0, positive=Buckets(offset=0, bucket_counts=[1]), negative=Buckets(offset=0, bucket_counts=[0]), - flags=0, min=10, max=10, + flags=DataPointFlags.get_default(), ) - cls.exp_histogram_data_point_0_str = f'{{"attributes": {cls.attributes_0_str}, "start_time_unix_nano": 1, "time_unix_nano": 2, "count": 1, "sum": 10, "scale": 1, "zero_count": 0, "positive": {{"offset": 0, "bucket_counts": [1]}}, "negative": {{"offset": 0, "bucket_counts": [0]}}, "flags": 0, "min": 10, "max": 10, "exemplars": []}}' + cls.exp_histogram_data_point_0_str = f'{{"attributes": {cls.attributes_0_str}, "start_time_unix_nano": 1, "time_unix_nano": 2, "count": 1, "sum": 10, "scale": 1, "zero_count": 0, "positive": {{"offset": 0, "bucket_counts": [1]}}, "negative": {{"offset": 0, "bucket_counts": [0]}}, "min": 10, "max": 10, "exemplars": [], "flags": {DataPointFlags.get_default()}}}' + + cls.exp_histogram_data_point_1 = ExponentialHistogramDataPoint( + attributes=cls.attributes_1, + start_time_unix_nano=2, + time_unix_nano=3, + count=2, + sum=20, + scale=2, + zero_count=1, + positive=Buckets(offset=0, bucket_counts=[1]), + negative=Buckets(offset=0, bucket_counts=[1]), + min=10, + max=20, + flags=DataPointFlags(DataPointFlags.NO_RECORDED_VALUE), + ) + cls.exp_histogram_data_point_1_str = f'{{"attributes": {cls.attributes_1_str}, "start_time_unix_nano": 2, "time_unix_nano": 3, "count": 2, "sum": 20, "scale": 2, "zero_count": 1, "positive": {{"offset": 0, "bucket_counts": [1]}}, "negative": {{"offset": 0, "bucket_counts": [1]}}, "min": 10, "max": 20, "exemplars": [], "flags": {DataPointFlags.NO_RECORDED_VALUE}}}' cls.sum_0 = Sum( data_points=[cls.number_data_point_0, cls.number_data_point_1], @@ -238,6 +257,10 @@ def test_exp_histogram_data_point(self): self.exp_histogram_data_point_0.to_json(indent=None), self.exp_histogram_data_point_0_str, ) + self.assertEqual( + self.exp_histogram_data_point_1.to_json(indent=None), + self.exp_histogram_data_point_1_str, + ) def test_sum(self): self.assertEqual(self.sum_0.to_json(indent=None), self.sum_0_str) diff --git a/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py b/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py index 33f1039ef87..68089050cc0 100644 --- a/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py +++ b/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py @@ -16,8 +16,10 @@ from typing import Optional from opentelemetry.attributes import BoundedAttributes +from opentelemetry.sdk.metrics._internal.point import DEFAULT_DATA_POINT_FLAGS from opentelemetry.sdk.metrics.export import ( AggregationTemporality, + DataPointFlags, Gauge, Histogram, HistogramDataPoint, @@ -50,6 +52,7 @@ def _generate_sum( description=None, unit=None, is_monotonic=True, + flags=DEFAULT_DATA_POINT_FLAGS, ) -> Metric: if attributes is None: attributes = BoundedAttributes(attributes={"a": 1, "b": True}) @@ -62,6 +65,7 @@ def _generate_sum( start_time_unix_nano=1641946015139533244, time_unix_nano=1641946016139533244, value=value, + flags=flags, ) ], aggregation_temporality=AggregationTemporality.CUMULATIVE, @@ -73,7 +77,12 @@ def _generate_sum( def _generate_gauge( - name, value, attributes=None, description=None, unit=None + name, + value, + attributes=None, + description=None, + unit=None, + flags=DEFAULT_DATA_POINT_FLAGS, ) -> Metric: if attributes is None: attributes = BoundedAttributes(attributes={"a": 1, "b": True}) @@ -86,6 +95,7 @@ def _generate_gauge( start_time_unix_nano=None, time_unix_nano=1641946016139533244, value=value, + flags=flags, ) ], ), @@ -110,6 +120,7 @@ def _generate_histogram( attributes: Attributes = None, description: Optional[str] = None, unit: Optional[str] = None, + flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS, ) -> Metric: if attributes is None: attributes = BoundedAttributes(attributes={"a": 1, "b": True}) @@ -127,6 +138,7 @@ def _generate_histogram( explicit_bounds=[123.0, 456.0], min=1, max=457, + flags=flags, ) ], aggregation_temporality=AggregationTemporality.CUMULATIVE, From f10a9045d680ca0ca2474fabdee226ab1cf5b89b Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Mon, 16 Feb 2026 23:11:54 -0500 Subject: [PATCH 2/4] update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b69cbbf7e55..8773716255e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#4709](https://github.com/open-telemetry/opentelemetry-python/pull/4709)) - Implement experimental TracerConfigurator ([#4861](https://github.com/open-telemetry/opentelemetry-python/pull/4861)) +- `opentelemetry-sdk`, `opentelemetry-exporter-otlp-proto-common`: Add support for metric data-point flags + ([#4916](https://github.com/open-telemetry/opentelemetry-python/pull/4916)) ## Version 1.39.0/0.60b0 (2025-12-03) From 802667bf48708b14af56a10ac6124deca9c564c7 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Fri, 20 Feb 2026 21:31:45 -0500 Subject: [PATCH 3/4] add BREAKING label to changelog entry --- CHANGELOG.md | 2 +- .../tests/test_metrics_encoder.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8773716255e..072366be659 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#4709](https://github.com/open-telemetry/opentelemetry-python/pull/4709)) - Implement experimental TracerConfigurator ([#4861](https://github.com/open-telemetry/opentelemetry-python/pull/4861)) -- `opentelemetry-sdk`, `opentelemetry-exporter-otlp-proto-common`: Add support for metric data-point flags +- [BREAKING] `opentelemetry-sdk`, `opentelemetry-exporter-otlp-proto-common`: Add support for metric data-point flags ([#4916](https://github.com/open-telemetry/opentelemetry-python/pull/4916)) ## Version 1.39.0/0.60b0 (2025-12-03) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py index d64795d0a36..8b6ecc2c713 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py @@ -171,7 +171,7 @@ def test_encode_sum_int(self): start_time_unix_nano=1641946015139533244, time_unix_nano=1641946016139533244, as_int=33, - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), ) ], aggregation_temporality=AggregationTemporality.CUMULATIVE, @@ -524,7 +524,7 @@ def test_encode_histogram(self): ], max=18.0, min=8.0, - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -656,7 +656,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -719,7 +719,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -790,7 +790,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -861,7 +861,7 @@ def test_encode_multiple_scope_histogram(self): ], max=18.0, min=8.0, - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), ) ], aggregation_temporality=AggregationTemporality.DELTA, @@ -978,7 +978,7 @@ def test_encode_exponential_histogram(self): offset=9, bucket_counts=[10, 11], ), - flags=DataPointFlags.DEFAULT, + flags=int(DataPointFlags.get_default()), exemplars=[], min=13.0, max=14.0, From 6f4b5bba4400f2b191fe97ab294ca4111b61d227 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Fri, 20 Feb 2026 21:45:59 -0500 Subject: [PATCH 4/4] update dataclass definitions --- .../opentelemetry/sdk/metrics/_internal/point.py | 9 +++------ .../src/opentelemetry/test/metrictestutil.py | 13 +++++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py index 8f8cc6ba22a..5f805fb5a6f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py @@ -56,9 +56,6 @@ def no_recorded_value(self) -> bool: return bool(self & self.NO_RECORDED_VALUE) -DEFAULT_DATA_POINT_FLAGS = DataPointFlags.get_default() - - @dataclass(frozen=True) class NumberDataPoint: """Single data point in a timeseries that describes the time-varying scalar @@ -70,7 +67,7 @@ class NumberDataPoint: time_unix_nano: int value: Union[int, float] exemplars: Sequence[Exemplar] = field(default_factory=list) - flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS + flags: DataPointFlags = DataPointFlags.get_default() def to_json(self, indent: Optional[int] = 4) -> str: return dumps(asdict(self), indent=indent) @@ -92,7 +89,7 @@ class HistogramDataPoint: min: float max: float exemplars: Sequence[Exemplar] = field(default_factory=list) - flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS + flags: DataPointFlags = DataPointFlags.get_default() def to_json(self, indent: Optional[int] = 4) -> str: return dumps(asdict(self), indent=indent) @@ -123,7 +120,7 @@ class ExponentialHistogramDataPoint: min: float max: float exemplars: Sequence[Exemplar] = field(default_factory=list) - flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS + flags: DataPointFlags = DataPointFlags.get_default() def to_json(self, indent: Optional[int] = 4) -> str: return dumps(asdict(self), indent=indent) diff --git a/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py b/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py index 68089050cc0..2dce617b331 100644 --- a/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py +++ b/tests/opentelemetry-test-utils/src/opentelemetry/test/metrictestutil.py @@ -16,7 +16,6 @@ from typing import Optional from opentelemetry.attributes import BoundedAttributes -from opentelemetry.sdk.metrics._internal.point import DEFAULT_DATA_POINT_FLAGS from opentelemetry.sdk.metrics.export import ( AggregationTemporality, DataPointFlags, @@ -52,10 +51,12 @@ def _generate_sum( description=None, unit=None, is_monotonic=True, - flags=DEFAULT_DATA_POINT_FLAGS, + flags=None, ) -> Metric: if attributes is None: attributes = BoundedAttributes(attributes={"a": 1, "b": True}) + if flags is None: + flags = DataPointFlags.get_default() return _generate_metric( name, Sum( @@ -82,10 +83,12 @@ def _generate_gauge( attributes=None, description=None, unit=None, - flags=DEFAULT_DATA_POINT_FLAGS, + flags=None, ) -> Metric: if attributes is None: attributes = BoundedAttributes(attributes={"a": 1, "b": True}) + if flags is None: + flags = DataPointFlags.get_default() return _generate_metric( name, Gauge( @@ -120,10 +123,12 @@ def _generate_histogram( attributes: Attributes = None, description: Optional[str] = None, unit: Optional[str] = None, - flags: DataPointFlags = DEFAULT_DATA_POINT_FLAGS, + flags: Optional[DataPointFlags] = None, ) -> Metric: if attributes is None: attributes = BoundedAttributes(attributes={"a": 1, "b": True}) + if flags is None: + flags = DataPointFlags.get_default() return _generate_metric( name, Histogram(