@@ -244,6 +244,12 @@ def build_metric(name, documentation, typ, unit, samples):
244
244
if name in seen_metrics :
245
245
raise ValueError ("Duplicate metric: " + name )
246
246
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 = ''
247
253
if unit and not name .endswith ("_" + unit ):
248
254
raise ValueError ("Unit does not match metric name: " + name )
249
255
if unit and typ in ['info' , 'stateset' ]:
@@ -252,9 +258,7 @@ def build_metric(name, documentation, typ, unit, samples):
252
258
# TODO: check labelvalues are valid utf8
253
259
# TODO: check samples are appropriately grouped and ordered
254
260
# TODO: check info/stateset values are 1/0
255
- # TODO: check for metadata in middle of samples
256
261
# TODO: Check histogram bucket rules being followed
257
- # TODO: Check for duplicate metrics
258
262
# TODO: Check for dupliate samples
259
263
# TODO: Check for decresing timestamps
260
264
metric .samples = samples
@@ -273,29 +277,29 @@ def build_metric(name, documentation, typ, unit, samples):
273
277
parts = line .split (' ' , 3 )
274
278
if len (parts ) < 4 :
275
279
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
+
276
293
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 )
286
296
if len (parts ) == 4 :
287
297
documentation = _unescape_help (parts [3 ])
288
298
elif len (parts ) == 3 :
289
299
raise ValueError ("Invalid line: " + line )
290
300
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 )
299
303
typ = parts [3 ]
300
304
allowed_names = {
301
305
'counter' : ['_total' , '_created' ],
@@ -306,14 +310,8 @@ def build_metric(name, documentation, typ, unit, samples):
306
310
}.get (typ , ['' ])
307
311
allowed_names = [name + n for n in allowed_names ]
308
312
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 )
317
315
unit = parts [3 ]
318
316
else :
319
317
raise ValueError ("Invalid line: " + line )
0 commit comments