12
12
import sys
13
13
import time
14
14
import types
15
-
15
+ from collections import namedtuple
16
16
from threading import Lock
17
17
from timeit import default_timer
18
- from collections import namedtuple
19
18
20
19
from .decorator import decorate
21
20
22
-
23
21
if sys .version_info > (3 ,):
24
22
unicode = str
25
23
46
44
47
45
class Timestamp (object ):
48
46
'''A nanosecond-resolution timestamp.'''
47
+
49
48
def __init__ (self , sec , nsec ):
50
49
if nsec < 0 or nsec >= 1e9 :
51
50
raise ValueError ("Invalid value for nanoseconds in Timestamp: {}" .format (nsec ))
@@ -74,7 +73,7 @@ def __gt__(self, other):
74
73
75
74
76
75
Exemplar = namedtuple ('Exemplar' , ['labels' , 'value' , 'timestamp' ])
77
- Exemplar .__new__ .__defaults__ = (None , )
76
+ Exemplar .__new__ .__defaults__ = (None ,)
78
77
79
78
80
79
class CollectorRegistry (object ):
@@ -84,6 +83,7 @@ class CollectorRegistry(object):
84
83
Metric objects. The returned metrics should be consistent with the Prometheus
85
84
exposition formats.
86
85
'''
86
+
87
87
def __init__ (self , auto_describe = False ):
88
88
self ._collector_to_names = {}
89
89
self ._names_to_collectors = {}
@@ -175,6 +175,7 @@ def restricted_registry(self, names):
175
175
class RestrictedRegistry (object ):
176
176
def collect (self ):
177
177
return metrics
178
+
178
179
return RestrictedRegistry ()
179
180
180
181
def get_sample_value (self , name , labels = None ):
@@ -194,8 +195,10 @@ def get_sample_value(self, name, labels=None):
194
195
REGISTRY = CollectorRegistry (auto_describe = True )
195
196
'''The default registry.'''
196
197
197
- _METRIC_TYPES = ('counter' , 'gauge' , 'summary' , 'histogram' ,
198
- 'gaugehistogram' , 'unknown' , 'info' , 'stateset' )
198
+ _METRIC_TYPES = (
199
+ 'counter' , 'gauge' , 'summary' , 'histogram' ,
200
+ 'gaugehistogram' , 'unknown' , 'info' , 'stateset' ,
201
+ )
199
202
200
203
201
204
class Metric (object ):
@@ -206,6 +209,7 @@ class Metric(object):
206
209
Custom collectors should use GaugeMetricFamily, CounterMetricFamily
207
210
and SummaryMetricFamily instead.
208
211
'''
212
+
209
213
def __init__ (self , name , documentation , typ , unit = '' ):
210
214
if unit and not name .endswith ("_" + unit ):
211
215
name += "_" + unit
@@ -236,14 +240,20 @@ def __eq__(self, other):
236
240
self .samples == other .samples )
237
241
238
242
def __repr__ (self ):
239
- return "Metric(%s, %s, %s, %s, %s)" % (self .name , self .documentation ,
240
- self .type , self .unit , self .samples )
243
+ return "Metric(%s, %s, %s, %s, %s)" % (
244
+ self .name ,
245
+ self .documentation ,
246
+ self .type ,
247
+ self .unit ,
248
+ self .samples ,
249
+ )
241
250
242
251
243
252
class UnknownMetricFamily (Metric ):
244
253
'''A single unknwon metric and its samples.
245
254
For use by custom collectors.
246
255
'''
256
+
247
257
def __init__ (self , name , documentation , value = None , labels = None , unit = '' ):
248
258
Metric .__init__ (self , name , documentation , 'unknown' , unit )
249
259
if labels is not None and value is not None :
@@ -262,18 +272,21 @@ def add_metric(self, labels, value, timestamp=None):
262
272
'''
263
273
self .samples .append (Sample (self .name , dict (zip (self ._labelnames , labels )), value , timestamp ))
264
274
275
+
265
276
# For backward compatibility.
266
277
UntypedMetricFamily = UnknownMetricFamily
267
278
279
+
268
280
class CounterMetricFamily (Metric ):
269
281
'''A single counter and its samples.
270
282
271
283
For use by custom collectors.
272
284
'''
285
+
273
286
def __init__ (self , name , documentation , value = None , labels = None , created = None , unit = '' ):
274
287
# Glue code for pre-OpenMetrics metrics.
275
288
if name .endswith ('_total' ):
276
- name = name [:- 6 ]
289
+ name = name [:- 6 ]
277
290
Metric .__init__ (self , name , documentation , 'counter' , unit )
278
291
if labels is not None and value is not None :
279
292
raise ValueError ('Can only specify at most one of value and labels.' )
@@ -301,6 +314,7 @@ class GaugeMetricFamily(Metric):
301
314
302
315
For use by custom collectors.
303
316
'''
317
+
304
318
def __init__ (self , name , documentation , value = None , labels = None , unit = '' ):
305
319
Metric .__init__ (self , name , documentation , 'gauge' , unit )
306
320
if labels is not None and value is not None :
@@ -326,6 +340,7 @@ class SummaryMetricFamily(Metric):
326
340
327
341
For use by custom collectors.
328
342
'''
343
+
329
344
def __init__ (self , name , documentation , count_value = None , sum_value = None , labels = None , unit = '' ):
330
345
Metric .__init__ (self , name , documentation , 'summary' , unit )
331
346
if (sum_value is None ) != (count_value is None ):
@@ -355,6 +370,7 @@ class HistogramMetricFamily(Metric):
355
370
356
371
For use by custom collectors.
357
372
'''
373
+
358
374
def __init__ (self , name , documentation , buckets = None , sum_value = None , labels = None , unit = '' ):
359
375
Metric .__init__ (self , name , documentation , 'histogram' , unit )
360
376
if (sum_value is None ) != (buckets is None ):
@@ -383,19 +399,26 @@ def add_metric(self, labels, buckets, sum_value, timestamp=None):
383
399
exemplar = None
384
400
if len (b ) == 3 :
385
401
exemplar = b [2 ]
386
- self .samples .append (Sample (self .name + '_bucket' ,
402
+ self .samples .append (Sample (
403
+ self .name + '_bucket' ,
387
404
dict (list (zip (self ._labelnames , labels )) + [('le' , bucket )]),
388
- value , timestamp , exemplar ))
405
+ value ,
406
+ timestamp ,
407
+ exemplar ,
408
+ ))
389
409
# +Inf is last and provides the count value.
390
- self .samples .append (Sample (self .name + '_count' , dict (zip (self ._labelnames , labels )), buckets [- 1 ][1 ], timestamp ))
391
- self .samples .append (Sample (self .name + '_sum' , dict (zip (self ._labelnames , labels )), sum_value , timestamp ))
410
+ self .samples .extend ([
411
+ Sample (self .name + '_count' , dict (zip (self ._labelnames , labels )), buckets [- 1 ][1 ], timestamp ),
412
+ Sample (self .name + '_sum' , dict (zip (self ._labelnames , labels )), sum_value , timestamp ),
413
+ ])
392
414
393
415
394
416
class GaugeHistogramMetricFamily (Metric ):
395
417
'''A single gauge histogram and its samples.
396
418
397
419
For use by custom collectors.
398
420
'''
421
+
399
422
def __init__ (self , name , documentation , buckets = None , gsum_value = None , labels = None , unit = '' ):
400
423
Metric .__init__ (self , name , documentation , 'gaugehistogram' , unit )
401
424
if labels is not None and buckets is not None :
@@ -421,15 +444,18 @@ def add_metric(self, labels, buckets, gsum_value, timestamp=None):
421
444
dict (list (zip (self ._labelnames , labels )) + [('le' , bucket )]),
422
445
value , timestamp ))
423
446
# +Inf is last and provides the count value.
424
- self .samples .append (Sample (self .name + '_gcount' , dict (zip (self ._labelnames , labels )), buckets [- 1 ][1 ], timestamp ))
425
- self .samples .append (Sample (self .name + '_gsum' , dict (zip (self ._labelnames , labels )), gsum_value , timestamp ))
447
+ self .samples .extend ([
448
+ Sample (self .name + '_gcount' , dict (zip (self ._labelnames , labels )), buckets [- 1 ][1 ], timestamp ),
449
+ Sample (self .name + '_gsum' , dict (zip (self ._labelnames , labels )), gsum_value , timestamp ),
450
+ ])
426
451
427
452
428
453
class InfoMetricFamily (Metric ):
429
10000
454
'''A single info and its samples.
430
455
431
456
For use by custom collectors.
432
457
'''
458
+
433
459
def __init__ (self , name , documentation , value = None , labels = None ):
434
460
Metric .__init__ (self , name , documentation , 'info' )
435
461
if labels is not None and value is not None :
@@ -447,15 +473,20 @@ def add_metric(self, labels, value, timestamp=None):
447
473
labels: A list of label values
448
474
value: A dict of labels
449
475
'''
450
- self .samples .append (Sample (self .name + '_info' ,
451
- dict (dict (zip (self ._labelnames , labels )), ** value ), 1 , timestamp ))
476
+ self .samples .append (Sample (
477
+ self .name + '_info' ,
478
+ dict (dict (zip (self ._labelnames , labels )), ** value ),
479
+ 1 ,
480
+ timestamp ,
481
+ ))
452
482
453
483
454
484
class StateSetMetricFamily (Metric ):
455
485
'''A single stateset and its samples.
456
486
457
487
For use by custom collectors.
458
488
'''
489
+
459
490
def __init__ (self , name , documentation , value = None , labels = None ):
460
491
Metric .__init__ (self , name , documentation , 'stateset' )
461
492
if labels is not None and value is not None :
@@ -476,8 +507,12 @@ def add_metric(self, labels, value, timestamp=None):
476
507
labels = tuple (labels )
477
508
for state , enabled in sorted (value .items ()):
478
509
v = (1 if enabled else 0 )
479
- self .samples .append (Sample (self .name ,
480
- dict (zip (self ._labelnames + (self .name ,), labels + (state ,))), v , timestamp ))
510
+ self .samples .append (Sample (
511
+ self .name ,
512
+ dict (zip (self ._labelnames + (self .name ,), labels + (state ,))),
513
+ v ,
514
+ timestamp ,
515
+ ))
481
516
482
517
483
518
class _MutexValue (object ):
@@ -524,6 +559,7 @@ class _MmapedDict(object):
524
559
525
560
Not thread safe.
526
561
"""
562
+
527
563
def __init__ (self , filename , read_mode = False ):
528
564
self ._f = open (filename , 'rb' if read_mode else 'a+b' )
529
565
if os .fstat (self ._f .fileno ()).st_size == 0 :
@@ -691,6 +727,7 @@ def get(self):
691
727
692
728
class _LabelWrapper (object ):
693
729
'''Handles labels for the wrapped metric.'''
730
+
694
731
def __init__ (self , wrappedClass , name , labelnames , ** kwargs ):
695
732
self ._wrappedClass = wrappedClass
696
733
self ._type = wrappedClass ._type
@@ -740,7 +777,12 @@ def labels(self, *labelvalues, **labelkwargs):
740
777
labelvalues = tuple (unicode (l ) for l in labelvalues )
741
778
with self ._lock :
742
779
if labelvalues not in self ._metrics :
743
- self ._metrics [labelvalues ] = self ._wrappedClass (self ._name , self ._labelnames , labelvalues , ** self ._kwargs )
780
+ self ._metrics [labelvalues ] = self ._wrappedClass (
781
+ self ._name ,
782
+ self ._labelnames ,
783
+ labelvalues ,
784
+ ** self ._kwargs
785
+ )
744
786
return self ._metrics [labelvalues ]
745
787
746
788
def remove (self , * labelvalues ):
@@ -762,6 +804,7 @@ def _samples(self):
762
804
763
805
def _MetricWrapper (cls ):
764
806
'''Provides common functionality for metrics.'''
807
+
765
808
def init (name , documentation , labelnames = (), namespace = '' , subsystem = '' , unit = '' , registry = REGISTRY , ** kwargs ):
766
809
full_name = ''
767
810
if namespace :
@@ -796,13 +839,15 @@ def init(name, documentation, labelnames=(), namespace='', subsystem='', unit=''
796
839
797
840
def describe ():
798
841
return [Metric (full_name , documentation , cls ._type )]
842
+
799
843
collector .describe = describe
800
844
801
845
def collect ():
802
846
metric = Metric (full_name , documentation , cls ._type , unit )
803
847
for suffix , labels , value in collector ._samples ():
804
848
metric .add_sample (full_name + suffix , labels , value )
805
849
return [metric ]
850
+
806
851
collector .collect = collect
807
852
808
853
if registry :
@@ -851,7 +896,7 @@ def f():
851
896
852
897
def __init__ (self , name , labelnames , labelvalues ):
853
898
if name .endswith ('_total' ):
854
- name = name [:- 6 ]
899
+ name = name [:- 6 ]
855
900
self ._value = _ValueClass (self ._type , name , name + '_total' , labelnames , labelvalues )
856
901
self ._created = time .time ()
857
902
@@ -871,8 +916,10 @@ def count_exceptions(self, exception=Exception):
871
916
return _ExceptionCounter (self , exception )
872
917
873
918
def _samples (self ):
874
- return (('_total' , {}, self ._value .get ()),
875
- ('_created' , {}, self ._created ))
919
+ return (
920
+ ('_total' , {}, self ._value .get ()),
921
+ ('_created' , {}, self ._created ),
922
+ )
876
923
877
924
878
925
@_MetricWrapper
@@ -963,12 +1010,14 @@ def set_function(self, f):
963
1010
The function must return a float, and may be called from
964
1011
multiple threads. All other methods of the Gauge become NOOPs.
965
1012
'''
1013
+
966
1014
def samples (self ):
967
- return (('' , {}, float (f ())), )
1015
+ return (('' , {}, float (f ())),)
1016
+
968
1017
self ._samples = types .MethodType (samples , self )
969
1018
970
1019
def _samples (self ):
971
- return (('' , {}, self ._value .get ()), )
1020
+ return (('' , {}, self ._value .get ()),)
972
1021
973
1022
974
1023
@_MetricWrapper
@@ -1095,7 +1144,13 @@ def __init__(self, name, labelnames, labelvalues, buckets=(.005, .01, .025, .05,
1095
1144
self ._buckets = []
1096
1145
bucket_labelnames = labelnames + ('le' ,)
1097
1146
for b in buckets :
1098
- self ._buckets .append (_ValueClass (self ._type , name , name + '_bucket' , bucket_labelnames , labelvalues + (_floatToGoString (b ),)))
1147
+ self ._buckets .append (_ValueClass (
1148
+ self ._type ,
1149
+ name ,
1150
+ name + '_bucket' ,
1151
+ bucket_labelnames ,
1152
+ labelvalues + (_floatToGoString (b ),),
1153
+ ))
1099
1154
1100
1155
def observe (self , amount ):
1101
1156
'''Observe the given amount.'''
@@ -1157,10 +1212,9 @@ def info(self, val):
1157
1212
with self ._lock :
1158
1213
self ._value = dict (val )
1159
1214
1160
-
1161
1215
def _samples (self ):
1162
1216
with self ._lock :
1163
- return (('_info' , self ._value , 1.0 ,), )
1217
+ return (('_info' , self ._value , 1.0 ,),)
1164
1218
1165
1219
1166
1220
@_MetricWrapper
@@ -1197,8 +1251,11 @@ def state(self, state):
1197
1251
1198
1252
def _samples (self ):
1199
1253
with self ._lock :
1200
- return [('' , {self ._name : s }, 1 if i == self ._value else 0 ,)
1201
- for i , s in enumerate (self ._states )]
1254
+ return [
1255
+ ('' , {self ._name : s }, 1 if i == self ._value else 0 ,)
1256
+ for i , s
1257
+ in enumerate (self ._states )
1258
+ ]
1202
1259
1203
1260
1204
1261
class _ExceptionCounter (object ):
@@ -1217,6 +1274,7 @@ def __call__(self, f):
1217
1274
def wrapped (func , * args , ** kwargs ):
1218
1275
with self :
1219
1276
return func (* args , ** kwargs )
1277
+
1220
1278
return decorate (f , wrapped )
1221
1279
1222
1280
@@ -1234,6 +1292,7 @@ def __call__(self, f):
1234
1292
def wrapped (func , * args , ** kwargs ):
1235
1293
with self :
1236
1294
return func (* args , ** kwargs )
1295
+
1237
1296
return decorate (f , wrapped )
1238
1297
1239
1298
@@ -1258,4 +1317,5 @@ def wrapped(func, *args, **kwargs):
1258
1317
# ensures thread safety and reentrancy.
1259
1318
with self ._new_timer ():
1260
1319
return func (* args , ** kwargs )
1320
+
1261
1321
return decorate (f , wrapped )
0 commit comments