1212import sys
1313import time
1414import types
15-
15+ from collections import namedtuple
1616from threading import Lock
1717from timeit import default_timer
18- from collections import namedtuple
1918
2019from .decorator import decorate
2120
22-
2321if sys .version_info > (3 ,):
2422 unicode = str
2523
4644
4745class Timestamp (object ):
4846 '''A nanosecond-resolution timestamp.'''
47+
4948 def __init__ (self , sec , nsec ):
5049 if nsec < 0 or nsec >= 1e9 :
5150 raise ValueError ("Invalid value for nanoseconds in Timestamp: {}" .format (nsec ))
@@ -74,7 +73,7 @@ def __gt__(self, other):
7473
7574
7675Exemplar = namedtuple ('Exemplar' , ['labels' , 'value' , 'timestamp' ])
77- Exemplar .__new__ .__defaults__ = (None , )
76+ Exemplar .__new__ .__defaults__ = (None ,)
7877
7978
8079class CollectorRegistry (object ):
@@ -84,6 +83,7 @@ class CollectorRegistry(object):
8483 Metric objects. The returned metrics should be consistent with the Prometheus
8584 exposition formats.
8685 '''
86+
8787 def __init__ (self , auto_describe = False ):
8888 self ._collector_to_names = {}
8989 self ._names_to_collectors = {}
@@ -175,6 +175,7 @@ def restricted_registry(self, names):
175175 class RestrictedRegistry (object ):
176176 def collect (self ):
177177 return metrics
178+
178179 return RestrictedRegistry ()
179180
180181 def get_sample_value (self , name , labels = None ):
@@ -194,8 +195,10 @@ def get_sample_value(self, name, labels=None):
194195REGISTRY = CollectorRegistry (auto_describe = True )
195196'''The default registry.'''
196197
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+ )
199202
200203
201204class Metric (object ):
@@ -206,6 +209,7 @@ class Metric(object):
206209 Custom collectors should use GaugeMetricFamily, CounterMetricFamily
207210 and SummaryMetricFamily instead.
208211 '''
212+
209213 def __init__ (self , name , documentation , typ , unit = '' ):
210214 if unit and not name .endswith ("_" + unit ):
211215 name += "_" + unit
@@ -236,14 +240,20 @@ def __eq__(self, other):
236240 self .samples == other .samples )
237241
238242 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+ )
241250
242251
243252class UnknownMetricFamily (Metric ):
244253 '''A single unknwon metric and its samples.
245254 For use by custom collectors.
246255 '''
256+
247257 def __init__ (self , name , documentation , value = None , labels = None , unit = '' ):
248258 Metric .__init__ (self , name , documentation , 'unknown' , unit )
249259 if labels is not None and value is not None :
@@ -262,18 +272,21 @@ def add_metric(self, labels, value, timestamp=None):
262272 '''
263273 self .samples .append (Sample (self .name , dict (zip (self ._labelnames , labels )), value , timestamp ))
264274
275+
265276# For backward compatibility.
266277UntypedMetricFamily = UnknownMetricFamily
267278
279+
268280class CounterMetricFamily (Metric ):
269281 '''A single counter and its samples.
270282
271283 For use by custom collectors.
272284 '''
285+
273286 def __init__ (self , name , documentation , value = None , labels = None , created = None , unit = '' ):
274287 # Glue code for pre-OpenMetrics metrics.
275288 if name .endswith ('_total' ):
276- name = name [:- 6 ]
289+ name = name [:- 6 ]
277290 Metric .__init__ (self , name , documentation , 'counter' , unit )
278291 if labels is not None and value is not None :
279292 raise ValueError ('Can only specify at most one of value and labels.' )
@@ -301,6 +314,7 @@ class GaugeMetricFamily(Metric):
301314
302315 For use by custom collectors.
303316 '''
317+
304318 def __init__ (self , name , documentation , value = None , labels = None , unit = '' ):
305319 Metric .__init__ (self , name , documentation , 'gauge' , unit )
306320 if labels is not None and value is not None :
@@ -326,6 +340,7 @@ class SummaryMetricFamily(Metric):
326340
327341 For use by custom collectors.
328342 '''
343+
329344 def __init__ (self , name , documentation , count_value = None , sum_value = None , labels = None , unit = '' ):
330345 Metric .__init__ (self , name , documentation , 'summary' , unit )
331346 if (sum_value is None ) != (count_value is None ):
@@ -355,6 +370,7 @@ class HistogramMetricFamily(Metric):
355370
356371 For use by custom collectors.
357372 '''
373+
358374 def __init__ (self , name , documentation , buckets = None , sum_value = None , labels = None , unit = '' ):
359375 Metric .__init__ (self , name , documentation , 'histogram' , unit )
360376 if (sum_value is None ) != (buckets is None ):
@@ -383,19 +399,26 @@ def add_metric(self, labels, buckets, sum_value, timestamp=None):
383399 exemplar = None
384400 if len (b ) == 3 :
385401 exemplar = b [2 ]
386- self .samples .append (Sample (self .name + '_bucket' ,
402+ self .samples .append (Sample (
403+ self .name + '_bucket' ,
387404 dict (list (zip (self ._labelnames , labels )) + [('le' , bucket )]),
388- value , timestamp , exemplar ))
405+ value ,
406+ timestamp ,
407+ exemplar ,
408+ ))
389409 # +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+ ])
392414
393415
394416class GaugeHistogramMetricFamily (Metric ):
395417 '''A single gauge histogram and its samples.
396418
397419 For use by custom collectors.
398420 '''
421+
399422 def __init__ (self , name , documentation , buckets = None , gsum_value = None , labels = None , unit = '' ):
400423 Metric .__init__ (self , name , documentation , 'gaugehistogram' , unit )
401424 if labels is not None and buckets is not None :
@@ -421,15 +444,18 @@ def add_metric(self, labels, buckets, gsum_value, timestamp=None):
421444 dict (list (zip (self ._labelnames , labels )) + [('le' , bucket )]),
422445 value , timestamp ))
423446 # +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+ ])
426451
427452
428453class InfoMetricFamily (Metric ):
429454 '''A single info and its samples.
430455
431456 For use by custom collectors.
432457 '''
458+
433459 def __init__ (self , name , documentation , value = None , labels = None ):
434460 Metric .__init__ (self , name , documentation , 'info' )
435461 if labels is not None and value is not None :
@@ -447,15 +473,20 @@ def add_metric(self, labels, value, timestamp=None):
447473 labels: A list of label values
448474 value: A dict of labels
449475 '''
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+ ))
452482
453483
454484class StateSetMetricFamily (Metric ):
455485 '''A single stateset and its samples.
456486
457487 For use by custom collectors.
458488 '''
489+
459490 def __init__ (self , name , documentation , value = None , labels = None ):
460491 Metric .__init__ (self , name , documentation , 'stateset' )
461492 if labels is not None and value is not None :
@@ -476,8 +507,12 @@ def add_metric(self, labels, value, timestamp=None):
476507 labels = tuple (labels )
477508 for state , enabled in sorted (value .items ()):
478509 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+ ))
481516
482517
483518class _MutexValue (object ):
@@ -524,6 +559,7 @@ class _MmapedDict(object):
524559
525560 Not thread safe.
526561 """
562+
527563 def __init__ (self , filename , read_mode = False ):
528564 self ._f = open (filename , 'rb' if read_mode else 'a+b' )
529565 if os .fstat (self ._f .fileno ()).st_size == 0 :
@@ -691,6 +727,7 @@ def get(self):
691727
692728class _LabelWrapper (object ):
693729 '''Handles labels for the wrapped metric.'''
730+
694731 def __init__ (self , wrappedClass , name , labelnames , ** kwargs ):
695732 self ._wrappedClass = wrappedClass
696733 self ._type = wrappedClass ._type
@@ -740,7 +777,12 @@ def labels(self, *labelvalues, **labelkwargs):
740777 labelvalues = tuple (unicode (l ) for l in labelvalues )
741778 with self ._lock :
742779 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+ )
744786 return self ._metrics [labelvalues ]
745787
746788 def remove (self , * labelvalues ):
@@ -762,6 +804,7 @@ def _samples(self):
762804
763805def _MetricWrapper (cls ):
764806 '''Provides common functionality for metrics.'''
807+
765808 def init (name , documentation , labelnames = (), namespace = '' , subsystem = '' , unit = '' , registry = REGISTRY , ** kwargs ):
766809 full_name = ''
767810 if namespace :
@@ -796,13 +839,15 @@ def init(name, documentation, labelnames=(), namespace='', subsystem='', unit=''
796839
797840 def describe ():
798841 return [Metric (full_name , documentation , cls ._type )]
842+
799843 collector .describe = describe
800844
801845 def collect ():
802846 metric = Metric (full_name , documentation , cls ._type , unit )
803847 for suffix , labels , value in collector ._samples ():
804848 metric .add_sample (full_name + suffix , labels , value )
805849 return [metric ]
850+
806851 collector .collect = collect
807852
808853 if registry :
@@ -851,7 +896,7 @@ def f():
851896
852897 def __init__ (self , name , labelnames , labelvalues ):
853898 if name .endswith ('_total' ):
854- name = name [:- 6 ]
899+ name = name [:- 6 ]
855900 self ._value = _ValueClass (self ._type , name , name + '_total' , labelnames , labelvalues )
856901 self ._created = time .time ()
857902
@@ -871,8 +916,10 @@ def count_exceptions(self, exception=Exception):
871916 return _ExceptionCounter (self , exception )
872917
873918 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+ )
876923
877924
878925@_MetricWrapper
@@ -963,12 +1010,14 @@ def set_function(self, f):
9631010 The function must return a float, and may be called from
9641011 multiple threads. All other methods of the Gauge become NOOPs.
9651012 '''
1013+
9661014 def samples (self ):
967- return (('' , {}, float (f ())), )
1015+ return (('' , {}, float (f ())),)
1016+
9681017 self ._samples = types .MethodType (samples , self )
9691018
9701019 def _samples (self ):
971- return (('' , {}, self ._value .get ()), )
1020+ return (('' , {}, self ._value .get ()),)
9721021
9731022
9741023@_MetricWrapper
@@ -1095,7 +1144,13 @@ def __init__(self, name, labelnames, labelvalues, buckets=(.005, .01, .025, .05,
10951144 self ._buckets = []
10961145 bucket_labelnames = labelnames + ('le' ,)
10971146 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+ ))
10991154
11001155 def observe (self , amount ):
11011156 '''Observe the given amount.'''
@@ -1157,10 +1212,9 @@ def info(self, val):
11571212 with self ._lock :
11581213 self ._value = dict (val )
11591214
1160-
11611215 def _samples (self ):
11621216 with self ._lock :
1163- return (('_info' , self ._value , 1.0 ,), )
1217+ return (('_info' , self ._value , 1.0 ,),)
11641218
11651219
11661220@_MetricWrapper
@@ -1197,8 +1251,11 @@ def state(self, state):
11971251
11981252 def _samples (self ):
11991253 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+ ]
12021259
12031260
12041261class _ExceptionCounter (object ):
@@ -1217,6 +1274,7 @@ def __call__(self, f):
12171274 def wrapped (func , * args , ** kwargs ):
12181275 with self :
12191276 return func (* args , ** kwargs )
1277+
12201278 return decorate (f , wrapped )
12211279
12221280
@@ -1234,6 +1292,7 @@ def __call__(self, f):
12341292 def wrapped (func , * args , ** kwargs ):
12351293 with self :
12361294 return func (* args , ** kwargs )
1295+
12371296 return decorate (f , wrapped )
12381297
12391298
@@ -1258,4 +1317,5 @@ def wrapped(func, *args, **kwargs):
12581317 # ensures thread safety and reentrancy.
12591318 with self ._new_timer ():
12601319 return func (* args , ** kwargs )
1320+
12611321 return decorate (f , wrapped )
0 commit comments