2424_MINUS_INF = float ("-inf" )
2525
2626
27-
2827class CollectorRegistry (object ):
2928 '''Metric collector registry.
30-
29+
3130 Collectors must have a no-argument method 'collect' that returns a list of
3231 Metric objects. The returned metrics should be consistent with the Prometheus
3332 exposition formats.
@@ -57,7 +56,7 @@ def collect(self):
5756
5857 def get_sample_value (self , name , labels = None ):
5958 '''Returns the sample value, or None if not found.
60-
59+
6160 This is inefficient, and intended only for use in unittests.
6261 '''
6362 if labels is None :
@@ -74,6 +73,7 @@ def get_sample_value(self, name, labels=None):
7473
7574_METRIC_TYPES = ('counter' , 'gauge' , 'summary' , 'histogram' , 'untyped' )
7675
76+
7777class Metric (object ):
7878 '''A single metric and it's samples.'''
7979 def __init__ (self , name , documentation , typ ):
@@ -168,10 +168,12 @@ def collect():
168168
169169 return init
170170
171+
171172@_MetricWrapper
172173class Counter (object ):
173174 _type = 'counter'
174175 _reserved_labelnames = []
176+
175177 def __init__ (self ):
176178 self ._value = 0.0
177179 self ._lock = Lock ()
@@ -193,10 +195,14 @@ def count_exceptions(self, exception=Exception):
193195 class ExceptionCounter (object ):
194196 def __init__ (self , counter ):
195197 self ._counter = counter
196- def __enter__ (self ): pass
198+
199+ def __enter__ (self ):
200+ pass
201+
197202 def __exit__ (self , typ , value , traceback ):
198203 if isinstance (value , exception ):
199204 self ._counter .inc ()
205+
200206 def __call__ (self , f ):
201207 @wraps (f )
202208 def wrapped (* args , ** kwargs ):
@@ -209,10 +215,12 @@ def _samples(self):
209215 with self ._lock :
210216 return (('' , {}, self ._value ), )
211217
218+
212219@_MetricWrapper
213220class Gauge (object ):
214221 _type = 'gauge'
215222 _reserved_labelnames = []
223+
216224 def __init__ (self ):
217225 self ._value = 0.0
218226 self ._lock = Lock ()
@@ -246,10 +254,13 @@ def track_inprogress(self):
246254 class InprogressTracker (object ):
247255 def __init__ (self , gauge ):
248256 self ._gauge = gauge
257+
249258 def __enter__ (self ):
250259 self ._gauge .inc ()
260+
251261 def __exit__ (self , typ , value , traceback ):
252262 self ._gauge .dec ()
263+
253264 def __call__ (self , f ):
254265 @wraps (f )
255266 def wrapped (* args , ** kwargs ):
@@ -262,10 +273,12 @@ def _samples(self):
262273 with self ._lock :
263274 return (('' , {}, self ._value ), )
264275
276+
265277@_MetricWrapper
266278class Summary (object ):
267279 _type = 'summary'
268280 _reserved_labelnames = ['quantile' ]
281+
269282 def __init__ (self ):
270283 self ._count = 0.0
271284 self ._sum = 0.0
@@ -285,11 +298,14 @@ def time(self):
285298 class Timer (object ):
286299 def __init__ (self , summary ):
287300 self ._summary = summary
301+
288302 def __enter__ (self ):
289303 self ._start = time .time ()
304+
290305 def __exit__ (self , typ , value , traceback ):
291306 # Time can go backwards.
292307 self ._summary .observe (max (time .time () - self ._start , 0 ))
308+
293309 def __call__ (self , f ):
294310 @wraps (f )
295311 def wrapped (* args , ** kwargs ):
@@ -304,6 +320,7 @@ def _samples(self):
304320 ('_count' , {}, self ._count ),
305321 ('_sum' , {}, self ._sum ))
306322
323+
307324def _floatToGoString (d ):
308325 if d == _INF :
309326 return '+Inf'
@@ -312,14 +329,16 @@ def _floatToGoString(d):
312329 else :
313330 return repr (d )
314331
332+
315333@_MetricWrapper
316334class Histogram (object ):
317335 _type = 'histogram'
318336 _reserved_labelnames = ['histogram' ]
337+
319338 def __init__ (self , buckets = (.005 , .01 , .025 , .05 , .075 , .1 , .25 , .5 , .75 , 1.0 , 2.5 , 5.0 , 7.5 , 10.0 , _INF )):
320339 self ._sum = 0.0
321340 self ._lock = Lock ()
322- buckets = [float (b ) for b in buckets ]
341+ buckets = [float (b ) for b in buckets ]
323342 if buckets != sorted (buckets ):
324343 # This is probably an error on the part of the user,
325344 # so raise rather than sorting for them.
@@ -348,11 +367,14 @@ def time(self):
348367 class Timer (object ):
349368 def __init__ (self , histogram ):
350369 self ._histogram = histogram
370+
351371 def __enter__ (self ):
352372 self ._start = time .time ()
373+
353374 def __exit__ (self , typ , value , traceback ):
354375 # Time can go backwards.
355376 self ._histogram .observe (max (time .time () - self ._start , 0 ))
377+
356378 def __call__ (self , f ):
357379 @wraps (f )
358380 def wrapped (* args , ** kwargs ):
@@ -372,10 +394,11 @@ def _samples(self):
372394 samples .append (('_sum' , {}, self ._sum ))
373395 return tuple (samples )
374396
375-
397+
376398CONTENT_TYPE_LATEST = 'text/plain; version=0.0.4; charset=utf-8'
377399'''Content type of the latest text format'''
378400
401+
379402def generate_latest (registry = REGISTRY ):
380403 '''Returns the metrics from the registry in latest text format as a string.'''
381404 output = []
@@ -402,6 +425,7 @@ def do_GET(self):
402425 self .end_headers ()
403426 self .wfile .write (generate_latest (REGISTRY ))
404427
428+
405429def write_to_textfile (path , registry ):
406430 '''Write metrics to the given path.
407431
@@ -417,13 +441,13 @@ def write_to_textfile(path, registry):
417441if __name__ == '__main__' :
418442 c = Counter ('cc' , 'A counter' )
419443 c .inc ()
420-
444+
421445 g = Gauge ('gg' , 'A gauge' )
422446 g .set (17 )
423-
447+
424448 s = Summary ('ss' , 'A summary' , ['a' , 'b' ])
425449 s .labels ('c' , 'd' ).observe (17 )
426-
450+
427451 h = Histogram ('hh' , 'A histogram' )
428452 h .observe (.6 )
429453
0 commit comments