@@ -38,7 +38,7 @@ def unregister(self, metric):
38
38
self ._collectors .remove (collector )
39
39
40
40
def collect (self ):
41
- """ Yields metrics from the collectors in the registry."""
41
+ ''' Yields metrics from the collectors in the registry.'''
42
42
collectors = None
43
43
with self ._lock :
44
44
collectors = copy .copy (self ._collectors )
@@ -47,10 +47,10 @@ def collect(self):
47
47
yield metric
48
48
49
49
def get_sample_value (self , name , labels = None ):
50
- """ Returns the sample value, or None if not found.
50
+ ''' Returns the sample value, or None if not found.
51
51
52
52
This is inefficient, and intended only for use in unittests.
53
- """
53
+ '''
54
54
if labels is None :
55
55
labels = {}
56
56
for metric in self .collect ():
@@ -71,7 +71,7 @@ def __init__(self, name, documentation, typ):
71
71
self ._name = name
72
72
self ._documentation = documentation
73
73
if typ not in _METRIC_TYPES :
74
- raise ValueError (" Invalid metric type: " + typ )
74
+ raise ValueError (' Invalid metric type: ' + typ )
75
75
self ._type = typ
76
76
self ._samples = []
77
77
@@ -94,19 +94,19 @@ def __init__(self, wrappedClass, labelnames):
94
94
raise InvalidLabelName (l )
95
95
96
96
def labels (self , * labelvalues ):
97
- """ Return the child for the given labelset."""
97
+ ''' Return the child for the given labelset.'''
98
98
if len (labelvalues ) != len (self ._labelnames ):
99
- raise ValueError (" Incorrect label count" )
99
+ raise ValueError (' Incorrect label count' )
100
100
labelvalues = tuple (labelvalues )
101
101
with self ._lock :
102
102
if labelvalues not in self ._metrics :
103
103
self ._metrics [labelvalues ] = self ._wrappedClass ()
104
104
return self ._metrics [labelvalues ]
105
105
106
106
def remove (self , * labelvalues ):
107
- """ Remove the given labelset from the metric."""
107
+ ''' Remove the given labelset from the metric.'''
108
108
if len (labelvalues ) != len (self ._labelnames ):
109
- raise ValueError (" Incorrect label count" )
109
+ raise ValueError (' Incorrect label count' )
110
110
labelvalues = tuple (labelvalues )
111
111
with self ._lock :
112
112
del self ._metrics [labelvalues ]
@@ -125,9 +125,9 @@ def init(name, documentation, labelnames=(), namespace='', subsystem='', registr
125
125
if labelnames :
126
126
for l in labelnames :
127
127
if not _METRIC_LABEL_NAME_RE .match (l ):
128
- raise ValueError (" Invalid label metric name: " + l )
128
+ raise ValueError (' Invalid label metric name: ' + l )
129
129
if _RESERVED_METRIC_LABEL_NAME_RE .match (l ):
130
- raise ValueError (" Reserved label metric name: " + l )
130
+ raise ValueError (' Reserved label metric name: ' + l )
131
131
collector = _LabelWrapper (cls , labelnames )
132
132
else :
133
133
collector = cls ()
@@ -140,7 +140,7 @@ def init(name, documentation, labelnames=(), namespace='', subsystem='', registr
140
140
full_name += name
141
141
142
142
if not _METRIC_NAME_RE .match (full_name ):
143
- raise ValueError (" Invalid metric name: " + full_name )
143
+ raise ValueError (' Invalid metric name: ' + full_name )
144
144
145
145
def collect ():
146
146
metric = Metric (full_name , documentation , cls ._type )
@@ -162,28 +162,33 @@ def __init__(self):
162
162
self ._lock = Lock ()
163
163
164
164
def inc (self , amount = 1 ):
165
- """ Increment counter by the given amount."""
165
+ ''' Increment counter by the given amount.'''
166
166
if amount < 0 :
167
- raise ValueError (" Counters can only be incremented by non-negative amounts." )
167
+ raise ValueError (' Counters can only be incremented by non-negative amounts.' )
168
168
with self ._lock :
169
169
self ._value += amount
170
170
171
- @contextmanager
172
- def countBlockExceptions (self ):
173
- """Decorator to increment if a block raises an exception."""
174
- try :
175
- yield
176
- except Exception , e :
177
- self .inc ()
178
- raise e
179
-
180
- def countFunctionExceptions (self , f ):
181
- """Decorator to increment if a function raises an exception."""
182
- @wraps (f )
183
- def wrapper (* args , ** kwargs ):
184
- with self .countBlockExceptions ():
185
- return f (* args , ** kwargs )
186
- return wrapper
171
+ def countExceptions (self , exception = Exception ):
172
+ '''Count exceptions in a block of code or function.
173
+
174
+ Can be used as a function decorator or context manager.
175
+ Increments the counter when an exception of the given
176
+ type is raised up out of the code.
177
+ '''
178
+ class ExceptionCounter (object ):
179
+ def __init__ (self , counter ):
180
+ self ._counter = counter
181
+ def __enter__ (self ): pass
182
+ def __exit__ (self , typ , value , traceback ):
183
+ if isinstance (value , exception ):
184
+ self ._counter .inc ()
185
+ def __call__ (self , f ):
186
+ @wraps (f )
187
+ def wrapped (* args , ** kwargs ):
188
+ with self :
189
+ return f (* args , ** kwargs )
190
+ return wrapped
191
+ return ExceptionCounter (self )
187
192
188
193
def _samples (self ):
189
194
with self ._lock :
@@ -197,40 +202,45 @@ def __init__(self):
197
202
self ._lock = Lock ()
198
203
199
204
def inc (self , amount = 1 ):
200
- """ Increment gauge by the given amount."""
205
+ ''' Increment gauge by the given amount.'''
201
206
with self ._lock :
202
207
self ._value += amount
203
208
204
209
def dec (self , amount = 1 ):
205
- """ Decrement gauge by the given amount."""
210
+ ''' Decrement gauge by the given amount.'''
206
211
with self ._lock :
207
212
self ._value -= amount
208
213
209
214
def set (self , value ):
210
- """ Set gauge to the given value."""
215
+ ''' Set gauge to the given value.'''
211
216
with self ._lock :
212
217
self ._value = float (value )
213
218
214
219
def setToCurrentTime (self , value ):
215
- """ Set gauge to the current unixtime."""
220
+ ''' Set gauge to the current unixtime.'''
216
221
self .set (time .time ())
217
222
218
- @contextmanager
219
- def trackBlockInprogress (self ):
220
- """Decorator to track how many of a block are in progress."""
221
- self .inc ()
222
- try :
223
- yield
224
- finally :
225
- self .dec ()
226
-
227
- def trackFunctionInprogress (self , f ):
228
- """Decorator to track how many of a function are in progress."""
229
- @wraps (f )
230
- def wrapper (* args , ** kwargs ):
231
- with self .trackBlockInprogress ():
232
- return f (* args , ** kwargs )
233
- return wrapper
223
+ def trackInprogress (self ):
224
+ '''Track inprogress blocks of code or functions.
225
+
226
+ Can be used as a function decorator or context manager.
227
+ Increments the gauge when the code is entered,
228
+ and decrements when it is exited.
229
+ '''
230
+ class InprogressTracker (object ):
231
+ def __init__ (self , gauge ):
232
+ self ._gauge = gauge
233
+ def __enter__ (self ):
234
+ self ._gauge .inc ()
235
+ def __exit__ (self , typ , value , traceback ):
236
+ self ._gauge .dec ()
237
+ def __call__ (self , f ):
238
+ @wraps (f )
239
+ def wrapped (* args , ** kwargs ):
240
+ with self :
241
+ return f (* args , ** kwargs )
242
+ return wrapped
243
+ return InprogressTracker (self )
234
244
235
245
def _samples (self ):
236
246
with self ._lock :
@@ -245,28 +255,31 @@ def __init__(self):
245
255
self ._lock = Lock ()
246
256
247
257
def observe (self , amount ):
248
- """ Observe the given amount."""
258
+ ''' Observe the given amount.'''
249
259
with self ._lock :
250
260
self ._count += 1
251
261
self ._sum += amount
252
262
253
- @contextmanager
254
- def timeBlock (self ):
255
- """Context manager to time how long a block of code takes in seconds."""
256
- start = time .time ()
257
- try :
258
- yield
259
- finally :
260
- # Time can go backwards.
261
- self .observe (max (time .time () - start , 0 ))
262
-
263
- def timeFunction (self , f ):
264
- """Decorator to time long a function takes in seconds."""
265
- @wraps (f )
266
- def wrapper (* args , ** kwargs ):
267
- with self .timeBlock ():
268
- return f (* args , ** kwargs )
269
- return wrapper
263
+ def time (self ):
264
+ '''Time a block of code or function, and observe the duration in seconds.
265
+
266
+ Can be used as a function decorator or context manager.
267
+ '''
268
+ class Timer (object ):
269
+ def __init__ (self , summary ):
270
+ self ._summary = summary
271
+ def __enter__ (self ):
272
+ self ._start = time .time ()
273
+ def __exit__ (self , typ , value , traceback ):
274
+ # Time can go backwards.
275
+ self ._summary .observe (max (time .time () - self ._start , 0 ))
276
+ def __call__ (self , f ):
277
+ @wraps (f )
278
+ def wrapped (* args , ** kwargs ):
279
+ with self :
280
+ return f (* args , ** kwargs )
281
+ return wrapped
282
+ return Timer (self )
270
283
271
284
def _samples (self ):
272
285
with self ._lock :
@@ -276,11 +289,11 @@ def _samples(self):
276
289
277
290
278
291
279
- CONTENT_TYPE_004 = 'text-plain; version=0.0.4; charset=utf-8'
280
- '''Content type of the text format v0.0.4 '''
292
+ CONTENT_TYPE_LATEST = 'text-plain; version=0.0.4; charset=utf-8'
293
+ '''Content type of the latest text format'''
281
294
282
- def generate004 (registry = REGISTRY ):
283
- '''Returns the metrics from the registry in text format v0.0.4 as a string.'''
295
+ def generate_latest (registry = REGISTRY ):
296
+ '''Returns the metrics from the registry in latest text format as a string.'''
284
297
output = []
285
298
for metric in registry .collect ():
286
299
output .append (u'# HELP %s %s' % (
@@ -290,7 +303,7 @@ def generate004(registry=REGISTRY):
290
303
if labels :
291
304
labelstr = u'{%s}' % ',' .join (
292
305
[u'%s="%s"' % (
293
- k , v .replace ('\\ ' , r'\\' ).replace ('\n ' , r'\n' ).replace ('"' , r'\" ' ))
306
+ k , v .replace ('\\ ' , r'\\' ).replace ('\n ' , r'\n' ).replace ('\' ' , r'\' ' ))
294
307
for k , v in labels .items ()])
295
308
else :
296
309
labelstr = u''
@@ -301,9 +314,9 @@ def generate004(registry=REGISTRY):
301
314
class MetricsHandler (BaseHTTPRequestHandler ):
302
315
def do_GET (self ):
303
316
self .send_response (200 )
304
- self .send_header ('Content-Type' , CONTENT_TYPE_004 )
317
+ self .send_header ('Content-Type' , CONTENT_TYPE_LATEST )
305
318
self .end_headers ()
306
- self .wfile .write (generate004 (REGISTRY ))
319
+ self .wfile .write (generate_latest (REGISTRY ))
307
320
308
321
309
322
if __name__ == '__main__' :
0 commit comments