Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions prometheus_client/openmetrics/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ def text_fd_to_metric_families(fd):
allowed_names = []
eof = False

seen_names = set()
seen_names = {}
seen_metadata = {}
type_suffixes = {
'counter': ['_total', '_created'],
'summary': ['', '_count', '_sum', '_created'],
Expand All @@ -484,10 +485,15 @@ def text_fd_to_metric_families(fd):
def build_metric(name, documentation, typ, unit, samples):
if typ is None:
typ = 'unknown'
metadata = (typ, unit)
if name in seen_metadata and seen_metadata[name] != metadata:
raise ValueError("Clashing name: " + name)
seen_metadata[name] = metadata
for suffix in set(type_suffixes.get(typ, []) + [""]):
if name + suffix in seen_names:
sample_name = name + suffix
if sample_name in seen_names and seen_names[sample_name] != name:
raise ValueError("Clashing name: " + name + suffix)
seen_names.add(name + suffix)
seen_names[sample_name] = name
if documentation is None:
documentation = ''
if unit is None:
Expand Down
23 changes: 23 additions & 0 deletions tests/openmetrics/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,29 @@ def test_untyped(self):
]
self.assertEqual([m], list(families))

def test_repeated_metric_family(self):
families = list(text_string_to_metric_families("""# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{instance="a",quantile="0.0"} 1.0
go_gc_duration_seconds_sum{instance="a"} 1.0
go_gc_duration_seconds_count{instance="a"} 1.0
# TYPE up gauge
up{instance="a"} 1.0
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{instance="b",quantile="0.0"} 2.0
go_gc_duration_seconds_sum{instance="b"} 2.0
go_gc_duration_seconds_count{instance="b"} 1.0
# EOF
"""))

self.assertEqual(
["go_gc_duration_seconds", "up", "go_gc_duration_seconds"],
[family.name for family in families],
)
self.assertEqual(
{"instance": "b", "quantile": "0.0"},
families[2].samples[0].labels,
)

def test_type_help_switched(self):
families = text_string_to_metric_families("""# HELP a help
# TYPE a counter
Expand Down