8000 fix: error if the metrics are not observable (#666) · ethervoid/client_python@9a24236 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9a24236

Browse files
authored
fix: error if the metrics are not observable (prometheus#666)
Signed-off-by: Pietro De Nicolao <pd@bendingspoons.com>
1 parent 921fd67 commit 9a24236

File tree

2 files changed

+63
-20
lines changed

2 files changed

+63
-20
lines changed

prometheus_client/metrics.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ def _metric_init(self):
258258

259259
def inc(self, amount=1):
260260
"""Increment counter by the given amount."""
261+
self._raise_if_not_observable()
261262
if amount < 0:
262263
raise ValueError('Counters can only be incremented by non-negative amounts.')
263264
self._value.inc(amount)
@@ -353,14 +354,17 @@ def _metric_init(self):
353354

354355
def inc(self, amount=1):
355356
"""Increment gauge by the given amount."""
357+
self._raise_if_not_observable()
356358
self._value.inc(amount)
357359

358360
def dec(self, amount=1):
359361
"""Decrement gauge by the given amount."""
362+
self._raise_if_not_observable()
360363
self._value.inc(-amount)
361364

362365
def set(self, value):
363366
"""Set gauge to the given value."""
367+
self._raise_if_not_observable()
364368
self._value.set(float(value))
365369

366370
def set_to_current_time(self):
@@ -392,6 +396,8 @@ def set_function(self, f):
392396
multiple threads. All other methods of the Gauge become NOOPs.
393397
"""
394398

399+
self._raise_if_not_observable()
400+
395401
def samples(self):
396402
return (('', {}, float(f())),)
397403

@@ -450,6 +456,7 @@ def observe(self, amount):
450456
https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
451457
for details.
452458
"""
459+
self._raise_if_not_observable()
453460
self._count.inc(1)
454461
self._sum.inc(amount)
455462

@@ -567,6 +574,7 @@ def observe(self, amount):
567574
https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
568575
for details.
569576
"""
577+
self._raise_if_not_observable()
570578
self._sum.inc(amount)
571579
for i, bound in enumerate(self._upper_bounds):
572580
if amount <= bound:

tests/test_core.py

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@
1919
import unittest
2020

2121

22+
def assert_not_observable(fn, *args, **kwargs):
23+
"""
24+
Assert that a function call falls with a ValueError exception containing
25+
'missing label values'
26+
"""
27+
28+
try:
29+
fn(*args, **kwargs)
30+
except ValueError as e:
31+
assert 'missing label values' in str(e)
32+
return
33+
34+
assert False, "Did not raise a 'missing label values' exception"
35+
36+
2237
class TestCounter(unittest.TestCase):
2338
def setUp(self):
2439
self.registry = CollectorRegistry()
@@ -36,7 +51,6 @@ def test_repr(self):
3651

3752
def test_negative_increment_raises(self):
3853
self.assertRaises(ValueError, self.counter.inc, -1)
39-
4054

4155
def test_function_decorator(self):
4256
@self.counter.count_exceptions(ValueError)
@@ -76,18 +90,21 @@ def test_block_decorator(self):
7690

7791
def test_count_exceptions_not_observable(self):
7892
counter = Counter('counter', 'help', labelnames=('label',), registry=self.registry)
93+
assert_not_observable(counter.count_exceptions)
7994

80-
try:
81-
counter.count_exceptions()
82-
except ValueError as e:
83-
self.assertIn('missing label values', str(e))
95+
def test_inc_not_observable(self):
96+
""".inc() must fail if the counter is not observable."""
97+
98+
counter = Counter('counter', 'help', labelnames=('label',), registry=self.registry)
99+
assert_not_observable(counter.inc)
84100

85101

86102
class TestGauge(unittest.TestCase):
87103
def setUp(self):
88104
self.registry = CollectorRegistry()
89105
self.gauge = Gauge('g', 'help', registry=self.registry)
90-
106+
self.gauge_with_label < 9E88 span class=pl-c1>= Gauge('g2', 'help', labelnames=("label1",), registry=self.registry)
107+
91108
def test_repr(self):
92109
self.assertEqual(repr(self.gauge), "prometheus_client.metrics.Gauge(g)")
93110

@@ -100,6 +117,21 @@ def test_gauge(self):
100117
self.gauge.set(9)
101118
self.assertEqual(9, self.registry.get_sample_value('g'))
102119

120+
def test_inc_not_observable(self):
121+
""".inc() must fail if the gauge is not observable."""
122+
123+
assert_not_observable(self.gauge_with_label.inc)
124+
125+
def test_dec_not_observable(self):
126+
""".dec() must fail if the gauge is not observable."""
127+
128+
assert_not_observable(self.gauge_with_label.dec)
129+
130+
def test_set_not_observable(self):
131+
""".set() must fail if the gauge is not observable."""
132+
133+
assert_not_observable(self.gauge_with_label.set, 1)
134+
103135
def test_inprogress_function_decorator(self):
104136
self.assertEqual(0, self.registry.get_sample_value('g'))
105137

@@ -127,6 +159,11 @@ def test_gauge_function(self):
127159
x['a'] = None
128160
self.assertEqual(1, self.registry.get_sample_value('g'))
129161

162+
def test_set_function_not_observable(self):
163+
""".set_function() must fail if the gauge is not observable."""
164+
165+
assert_not_observable(self.gauge_with_label.set_function, lambda: 1)
166+
130167
def test_time_function_decorator(self):
131168
self.assertEqual(0, self.registry.get_sample_value('g'))
132169

@@ -167,25 +204,18 @@ def test_time_block_decorator(self):
167204

168205
def test_track_in_progress_not_observable(self):
169206
g = Gauge('test', 'help', labelnames=('label',), registry=self.registry)
170-
171-
try:
172-
g.track_inprogress()
173-
except ValueError as e:
174-
self.assertIn('missing label values', str(e))
207+
assert_not_observable(g.track_inprogress)
175208

176209
def test_timer_not_observable(self):
177210
g = Gauge('test', 'help', labelnames=('label',), registry=self.registry)
178-
179-
try:
180-
g.time()
181-
except ValueError as e:
182-
self.assertIn('missing label values', str(e))
211+
assert_not_observable(g.time)
183212

184213

185214
class TestSummary(unittest.TestCase):
186215
def setUp(self):
187216
self.registry = CollectorRegistry()
188217
self.summary = Summary('s', 'help', registry=self.registry)
218+
self.summary_with_labels = Summary('s_with_labels', 'help', labelnames=("label1",), registry=self.registry)
189219

190220
def test_repr(self):
191221
self.assertEqual(repr(self.summary), "prometheus_client.metrics.Summary(s)")
@@ -197,6 +227,10 @@ def test_summary(self):
197227
self.assertEqual(1, self.registry.get_sample_value('s_count'))
198228
self.assertEqual(10, self.registry.get_sample_value('s_sum'))
199229

230+
def test_summary_not_observable(self):
231+
""".observe() must fail if the Summary is not observable."""
232+
assert_not_observable(self.summary_with_labels.observe, 1)
233+
200234
def test_function_decorator(self):
201235
self.assertEqual(0, self.registry.get_sample_value('s_count'))
202236

@@ -267,10 +301,7 @@ def test_block_decorator(self):
267301
def test_timer_not_observable(self):
268302
s = Summary('test', 'help', labelnames=('label',), registry=self.registry)
269303

270-
try:
271-
s.time()
272-
except ValueError as e:
273-
self.assertIn('missing label values', str(e))
304+
assert_not_observable(s.time)
274305

275306

276307
class TestHistogram(unittest.TestCase):
@@ -315,6 +346,10 @@ def test_histogram(self):
315346
self.assertEqual(3, self.registry.get_sample_value('h_count'))
316347
self.assertEqual(float("inf"), self.registry.get_sample_value('h_sum'))
317348

349+
def test_histogram_not_observable(self):
350+
""".observe() must fail if the Summary is not observable."""
351+
assert_not_observable(self.labels.observe, 1)
352+
318353
def test_setting_buckets(self):
319354
h = Histogram('h', 'help', registry=None, buckets=[0, 1, 2])
320355
self.assertEqual([0.0, 1.0, 2.0, float("inf")], h._upper_bounds)

0 commit comments

Comments
 (0)
0