8000 Allow for other ways for values to be managed. · shamrin/client_python@115e1f1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 115e1f1

Browse files
committed
Allow for other ways for values to be managed.
1 parent 787d9a1 commit 115e1f1

File tree

1 file changed

+72
-59
lines changed

1 file changed

+72
-59
lines changed

prometheus_client/core.py

Lines changed: 72 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,34 @@ def add_sample(self, name, labels, value):
8888
self._samples.append((name, labels, value))
8989

9090

91+
class _MutexValue(object):
92+
'''A float protected by a mutex.'''
93+
94+
def __init__(self, name, labelnames, labelvalues):
95+
self._value = 0.0
96+
self._lock = Lock()
97+
98+
def inc(self, amount):
99+
with self._lock:
100+
self._value += amount
101+
102+
def set(self, value):
103+
with self._lock:
104+
self._value = value
105+
106+
def get(self):
107+
with self._lock:
108+
return self._value
109+
110+
_ValueClass = _MutexValue
111+
112+
91113
class _LabelWrapper(object):
92114
'''Handles labels for the wrapped metric.'''
93-
def __init__(self, wrappedClass, labelnames, **kwargs):
115+
def __init__(self, wrappedClass, name, labelnames, **kwargs):
94116
self._wrappedClass = wrappedClass
95117
self._type = wrappedClass._type
118+
self._name = name
96119
self._labelnames = labelnames
97120
self._kwargs = kwargs
98121
self._lock = Lock()
@@ -122,7 +145,7 @@ def labels(self, *labelvalues):
122145
labelvalues = tuple([unicode(l) for l in labelvalues])
123146
with self._lock:
124147
if labelvalues not in self._metrics:
125-
self._metrics[labelvalues] = self._wrappedClass(**self._kwargs)
148+
self._metrics[labelvalues] = self._wrappedClass(self._name, self._labelnames, labelvalues, **self._kwargs)
126149
return self._metrics[labelvalues]
127150

128151
def remove(self, *labelvalues):
@@ -145,24 +168,25 @@ def _samples(self):
145168
def _MetricWrapper(cls):
146169
'''Provides common functionality for metrics.'''
147170
def init(name, documentation, labelnames=(), namespace='', subsystem='', registry=REGISTRY, **kwargs):
171+
full_name = ''
172+
if namespace:
173+
full_name += namespace + '_'
174+
if subsystem:
175+
full_name += subsystem + '_'
176+
full_name += name
177+
148178
if labelnames:
179+
labelnames = tuple(labelnames)
149180
for l in labelnames:
150181
if not _METRIC_LABEL_NAME_RE.match(l):
151182
raise ValueError('Invalid label metric name: ' + l)
152183
if _RESERVED_METRIC_LABEL_NAME_RE.match(l):
153184
raise ValueError('Reserved label metric name: ' + l)
154185
if l in cls._reserved_labelnames:
155186
raise ValueError('Reserved label metric name: ' + l)
156-
collector = _LabelWrapper(cls, labelnames, **kwargs)
187+
collector = _LabelWrapper(cls, name, labelnames, **kwargs)
157188
else:
158-
collector = cls(**kwargs)
159-
160-
full_name = ''
161-
if namespace:
162-
full_name += namespace + '_'
163-
if subsystem:
164-
full_name += subsystem + '_'
165-
full_name += name
189+
collector = cls(name, labelnames, (), **kwargs)
166190

167191
if not _METRIC_NAME_RE.match(full_name):
168192
raise ValueError('Invalid metric name: ' + full_name)
@@ -186,16 +210,14 @@ class Counter(object):
186210
_type = 'counter'
187211
_reserved_labelnames = []
188212

189-
def __init__(self):
190-
self._value = 0.0
191-
self._lock = Lock()
213+
def __init__(self, name, labelnames, labelvalues):
214+
self._value = _ValueClass(name, labelnames, labelvalues)
192215

193216
def inc(self, amount=1):
194217
'''Increment counter by the given amount.'''
195218
if amount < 0:
196219
raise ValueError('Counters can only be incremented by non-negative amounts.')
197-
with self._lock:
198-
self._value += amount
220+
self._value.inc(amount)
199221

200222
def count_exceptions(self, exception=Exception):
201223
'''Count exceptions in a block of code or function.
@@ -226,33 +248,28 @@ def wrapped(*args, **kwargs):
226248
return ExceptionCounter(self)
227249

228250
def _samples(self):
229-
with self._lock:
230-
return (('', {}, self._value), )
251+
return (('', {}, self._value.get()), )
231252

232253

233254
@_MetricWrapper
234255
class Gauge(object):
235256
_type = 'gauge'
236257
_reserved_labelnames = []
237258

238-
def __init__(self):
239-
self._value = 0.0
240-
self._lock = Lock()
259+
def __init__(self, name, labelnames, labelvalues):
260+
self._value = _ValueClass(name, labelnames, labelvalues)
241261

242262
def inc(self, amount=1):
243263
'''Increment gauge by the given amount.'''
244-
with self._lock:
245-
self._value += amount
264+
self._value.inc(amount)
246265

247266
def dec(self, amount=1):
248267
'''Decrement gauge by the given amount.'''
249-
with self._lock:
250-
self._value -= amount
268+
self._value.inc(-amount)
251269

252270
def set(self, value):
253271
'''Set gauge to the given value.'''
254-
with self._lock:
255-
self._value = float(value)
272+
self._value.set(float(value))
256273

257274
def set_to_current_time(self):
258275
'''Set gauge to the current unixtime.'''
@@ -323,25 +340,22 @@ def samples(self):
323340
self._samples = types.MethodType(samples, self)
324341

325342
def _samples(self):
326-
with self._lock:
327-
return (('', {}, self._value), )
343+
return (('', {}, self._value.get()), )
328344

329345

330346
@_MetricWrapper
331347
class Summary(object):
332348
_type = 'summary'
333349
_reserved_labelnames = ['quantile']
334350

335-
def __init__(self):
336-
self._count = 0.0
337-
self._sum = 0.0
338-
self._lock = Lock()
351+
def __init__(self, name, labelnames, labelvalues):
352+
self._count = _ValueClass(name + '_count', labelnames, labelvalues)
353+
self._sum = _ValueClass(name + '_sum', labelnames, labelvalues)
339354

340355
def observe(self, amount):
341356
'''Observe the given amount.'''
342-
with self._lock:
343-
self._count += 1
344-
self._sum += amount
357+
self._count.inc(1)
358+
self._sum.inc(amount)
345359

346360
def time(self):
347361
'''Time a block of code or function, and observe the duration in seconds.
@@ -370,10 +384,9 @@ def wrapped(*args, **kwargs):
370384
return Timer(self)
371385

372386
def _samples(self):
373-
with self._lock:
374-
return (
375-
('_count', {}, self._count),
376-
('_sum', {}, self._sum))
387+
return (
388+
('_count', {}, self._count.get()),
389+
('_sum', {}, self._sum.get()))
377390

378391

379392
def _floatToGoString(d):
@@ -390,9 +403,8 @@ class Histogram(object):
390403
_type = 'histogram'
391404
_reserved_labelnames = ['histogram']
392405

393-
def __init__(self, buckets=(.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 2.5, 5.0, 7.5, 10.0, _INF)):
394-
self._sum = 0.0
395-
self._lock = Lock()
406+
def __init__(self, name, labelnames, labelvalues, buckets=(.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 2.5, 5.0, 7.5, 10.0, _INF)):
407+
self._sum = _ValueClass(name + '_sum', labelnames, labelvalues)
396408
buckets = [float(b) for b in buckets]
397409
if buckets != sorted(buckets):
398410
# This is probably an error on the part of the user,
@@ -403,16 +415,18 @@ def __init__(self, buckets=(.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 2
403415
if len(buckets) < 2:
404416
raise ValueError('Must have at least two buckets')
405417
self._upper_bounds = buckets
406-
self._buckets = [0.0] * len(buckets)
418+
self._buckets = []
419+
bucket_labelnames = labelnames + ('le',)
420+
for b in buckets:
421+
self._buckets.append(_ValueClass(name + '_bucket', bucket_labelnames, labelvalues + (_floatToGoString(b),)))
407422

408423
def observe(self, amount):
409424
'''Observe the given amount.'''
410-
with self._lock:
411-
self._sum += amount
412-
for i, bound in enumerate(self._upper_bounds):
413-
if amount <= bound:
414-
self._buckets[i] += 1
415-
break
425+
self._sum.inc(amount)
426+
for i, bound in enumerate(self._upper_bounds):
427+
if amount <= bound:
428+
self._buckets[i].inc(1)
429+
break
416430

417431
def time(self):
418432
'''Time a block of code or function, and observe the duration in seconds.
@@ -441,13 +455,12 @@ def wrapped(*args, **kwargs):
441455
return Timer(self)
442456

443457
def _samples(self):
444-
with self._lock:
445-
samples = []
446-
acc = 0
447-
for i, bound in enumerate(self._upper_bounds):
448-
acc += self._buckets[i]
449-
samples.append(('_bucket', {'le': _floatToGoString(bound)}, acc))
450-
samples.append(('_count', {}, acc))
451-
samples.append(('_sum', {}, self._sum))
452-
return tuple(samples)
458+
samples = []
459+
acc = 0
460+
for i, bound in enumerate(self._upper_bounds):
461+
acc += self._buckets[i].get()
462+
samples.append(('_bucket', {'le': _floatToGoString(bound)}, acc))
463+
samples.append(('_count', {}, acc))
464+
samples.append(('_sum', {}, self._sum.get()))
465+
return tuple(samples)
453466

0 commit comments

Comments
 (0)
0