8000 Catch repeated metadata, and metadata after samples. · sxlstevengit/client_python@0b4e983 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0b4e983

Browse files
committed
Catch repeated metadata, and metadata after samples.
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
1 parent 95c7285 commit 0b4e983

File tree

2 files changed

+34
-27
lines changed

2 files changed

+34
-27
lines changed

prometheus_client/openmetrics/parser.py

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ def build_metric(name, documentation, typ, unit, samples):
244244
if name in seen_metrics:
245245
raise ValueError("Duplicate metric: " + name)
246246
seen_metrics.add(name)
247+
if typ is None:
248+
typ = 'untyped'
249+
if documentation is None:
250+
documentation = ''
251+
if unit is None:
252+
unit = ''
247253
if unit and not name.endswith("_" + unit):
248254
raise ValueError("Unit does not match metric name: " + name)
249255
if unit and typ in ['info', 'stateset']:
@@ -252,9 +258,7 @@ def build_metric(name, documentation, typ, unit, samples):
252258
# TODO: check labelvalues are valid utf8
253259
# TODO: check samples are appropriately grouped and ordered
254260
# TODO: check info/stateset values are 1/0
255-
# TODO: check for metadata in middle of samples
256261
# TODO: Check histogram bucket rules being followed
257-
# TODO: Check for duplicate metrics
258262
# TODO: Check for dupliate samples
259263
# TODO: Check for decresing timestamps
260264
metric.samples = samples
@@ -273,29 +277,29 @@ def build_metric(name, documentation, typ, unit, samples):
273277
parts = line.split(' ', 3)
274278
if len(parts) < 4:
275279
raise ValueError("Invalid line: " + line)
280+
if parts[2] == name and samples:
281+
raise ValueError("Received metadata after samples: " + line)
282+
if parts[2] != name:
283+
if name != '':
284+
yield build_metric(name, documentation, typ, unit, samples)
285+
# New metric
286+
name = parts[2]
287+
unit = None
288+
typ = None
289+
documentation = None
290+
samples = []
291+
allowed_names = [parts[2]]
292+
276293
if parts[1] == 'HELP':
277-
if parts[2] != name:
278-
if name != '':
279-
yield build_metric(name, documentation, typ, unit, samples)
280-
# New metric
281-
name = parts[2]
282-
unit = ''
283-
typ = 'untyped'
284-
samples = []
285-
allowed_names = [parts[2]]
294+
if documentation is not None:
295+
raise ValueError("More than one HELP for metric: " + line)
286296
if len(parts) == 4:
287297
documentation = _unescape_help(parts[3])
288298
elif len(parts) == 3:
289299
raise ValueError("Invalid line: " + line)
290300
elif parts[1] == 'TYPE':
291-
if parts[2] != name:
292-
if name != '':
293-
yield build_metric(name, documentation, typ, unit, samples)
294-
# New metric
295-
name = parts[2]
296-
documentation = ''
297-
unit = ''
298-
samples = []
301+
if typ is not None:
302+
raise ValueError("More than one TYPE for metric: " + line)
299303
typ = parts[3]
300304
allowed_names = {
301305
'counter': ['_total', '_created'],
@@ -306,14 +310,8 @@ def build_metric(name, documentation, typ, unit, samples):
306310
}.get(typ, [''])
307311
allowed_names = [name + n for n in allowed_names]
308312
elif parts[1] == 'UNIT':
309-
if parts[2] != name:
310-
if name != '':
311-
yield build_metric(name, documentation, typ, unit, samples)
312-
# New metric
313-
name = parts[2]
314-
typ = 'untyped'
315-
samples = []
316-
allowed_names = [parts[2]]
313+
if unit is not None:
314+
raise ValueError("More than one UNIT for metric: " + line)
317315
unit = parts[3]
318316
else:
319317
raise ValueError("Invalid line: " + line)

tests/openmetrics/test_parser.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,15 @@ def test_invalid_input(self):
431431
('# UNIT a_seconds seconds \n# EOF\n'),
432432
('# TYPE x_u info\n# UNIT x_u u\n# EOF\n'),
433433
('# TYPE x_u stateset\n# UNIT x_u u\n# EOF\n'),
434+
# Metadata in wrong place.
435+
('# HELP a x\na 1\n# TYPE a gauge\n# EOF\n'),
436+
('# TYPE a gauge\na 1\n# HELP a gauge\n# EOF\n'),
437+
('# TYPE a_s gauge\na_s 1\n# UNIT a_s s\n# EOF\n'),
438+
# Repeated metadata.
439+
('# HELP a \n# HELP a \n# EOF\n'),
440+
('# HELP a x\n# HELP a x\n# EOF\n'),
441+
('# TYPE a untyped\n# TYPE a untyped\n# EOF\n'),
442+
('# UNIT a_s s\n# UNIT a_s s\n# EOF\n'),
434443
# Bad metric names.
435444
('0a 1\n# EOF\n'),
436445
('a.b 1\n# EOF\n'),

0 commit comments

Comments
 (0)
0