Skip to content

Commit be5e767

Browse files
committed
fix(metrics): stringify attribute keys at the OTLP wire boundary
Series identity already str()s keys, but the payload emitted the raw object — a numeric key violates OTLP's string KeyValue.key and strict decoders reject or drop the attribute. Generated-By: PostHog Code Task-Id: 0d65d94c-c18a-4d84-93f6-18eb54876551
1 parent 11c557c commit be5e767

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

posthog/metrics_capture.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ def _to_otlp_any_value(value: Any) -> dict:
9696

9797

9898
def _to_otlp_key_value_list(attributes: dict) -> list:
99+
# str(key): OTLP KeyValue.key is a string field — strict decoders reject numeric
100+
# keys — and the series identity already stringifies keys the same way.
99101
return [
100-
{"key": key, "value": _to_otlp_any_value(value)}
102+
{"key": str(key), "value": _to_otlp_any_value(value)}
101103
for key, value in attributes.items()
102104
if value is not None
103105
]

posthog/test/test_metrics.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,19 @@ class TestMetricsCrashSafety:
271271
def test_hostile_attributes_do_not_raise(self, client, attributes):
272272
client.metrics.count("hostile", 1, attributes=attributes) # must not raise
273273

274+
def test_non_string_attribute_keys_stringify_on_the_wire(self, client):
275+
# Series identity str()s keys, but the wire must too — OTLP KeyValue.key is a
276+
# string field and strict decoders reject numeric keys.
277+
client.metrics.count("m", 1, attributes={"a": 1, 2: "x"})
278+
279+
payload, _, _ = flush_and_capture(client)
280+
281+
(metric,) = metrics_from(payload)
282+
(dp,) = metric["sum"]["dataPoints"]
283+
keys = {attr["key"] for attr in dp["attributes"]}
284+
assert keys == {"a", "2"}
285+
assert all(isinstance(attr["key"], str) for attr in dp["attributes"])
286+
274287
def test_list_attribute_records_as_array_value(self, client):
275288
client.metrics.count("arr", 1, attributes={"tags": ["a", "b"]})
276289

0 commit comments

Comments
 (0)