Skip to content

Commit 54c7ee8

Browse files
authored
exporter/prometheus_remote_write: sort labels before exporting (#2940)
1 parent a940fc4 commit 54c7ee8

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3434
([#2922](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2922))
3535
- `opentelemetry-instrumentation-celery` Don't detach context without a None token
3636
([#2927](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2927))
37+
- `opentelemetry-exporter-prometheus-remote-write`: sort labels before exporting
38+
([#2940](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2940))
3739
- `opentelemetry-instrumentation-dbapi` sqlcommenter key values created from PostgreSQL, MySQL systems
3840
([#2897](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2897))
3941

exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import re
1717
from collections import defaultdict
1818
from itertools import chain
19-
from typing import Dict, Sequence
19+
from typing import Dict, Mapping, Sequence
2020

2121
import requests
2222
import snappy
@@ -253,12 +253,14 @@ def _parse_metric(
253253
return self._convert_to_timeseries(sample_sets, resource_labels)
254254

255255
def _convert_to_timeseries(
256-
self, sample_sets: Sequence[tuple], resource_labels: Sequence
256+
self, sample_sets: Mapping[tuple, Sequence], resource_labels: Sequence
257257
) -> Sequence[TimeSeries]:
258258
timeseries = []
259259
for labels, samples in sample_sets.items():
260260
ts = TimeSeries()
261-
for label_name, label_value in chain(resource_labels, labels):
261+
for label_name, label_value in sorted(
262+
chain(resource_labels, labels)
263+
):
262264
# Previous implementation did not str() the names...
263265
ts.labels.append(self._label(label_name, str(label_value)))
264266
for value, timestamp in samples:

exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py

+34
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
PrometheusRemoteWriteMetricsExporter,
2323
)
2424
from opentelemetry.exporter.prometheus_remote_write.gen.types_pb2 import ( # pylint: disable=E0611
25+
Label,
26+
Sample,
2527
TimeSeries,
2628
)
2729
from opentelemetry.sdk.metrics.export import (
@@ -155,6 +157,38 @@ def test_parse_metric(metric, prom_rw):
155157
assert sample.value in values
156158

157159

160+
def test_convert_to_timeseries(prom_rw):
161+
resource_labels = (("service_name", "foo"), ("bool_value", True))
162+
sample_sets = {
163+
(("foo", "bar"), ("baz", 42), ("__name__", "test_histogram_tu")): [
164+
(1, 1641946016139)
165+
],
166+
(("baz", "42"), ("foo", "bar")): [(4, 1641946016139)],
167+
}
168+
timeseries = prom_rw._convert_to_timeseries(sample_sets, resource_labels)
169+
assert timeseries == [
170+
TimeSeries(
171+
labels=[
172+
Label(name="__name__", value="test_histogram_tu"),
173+
Label(name="baz", value="42"),
174+
Label(name="bool_value", value="True"),
175+
Label(name="foo", value="bar"),
176+
Label(name="service_name", value="foo"),
177+
],
178+
samples=[Sample(value=1, timestamp=1641946016139)],
179+
),
180+
TimeSeries(
181+
labels=[
182+
Label(name="baz", value="42"),
183+
Label(name="bool_value", value="True"),
184+
Label(name="foo", value="bar"),
185+
Label(name="service_name", value="foo"),
186+
],
187+
samples=[Sample(value=4, timestamp=1641946016139)],
188+
),
189+
]
190+
191+
158192
class TestValidation(unittest.TestCase):
159193
# Test cases to ensure exporter parameter validation works as intended
160194
def test_valid_standard_param(self):

0 commit comments

Comments
 (0)