Skip to content

Commit fbe1461

Browse files
committed
Eagerly verify Sample values are float-convertibleAddresses #527.There's a test setting GaugeHistogramMetricFamily.gsum_value = None, soI've preserved that behaviour, by not appending and crashing if gsum_valueis None.I was a bit unsure about this bit: assert isinstance(exception.args[-1], core.Metric)I'm not sure what exception.args[-1] is, the python docs for TypeError and ValueErrordon't explain. I've removed the assertion.
1 parent 0497442 commit fbe1461

File tree

3 files changed

+30
-21
lines changed

3 files changed

+30
-21
lines changed

Diff for: prometheus_client/metrics_core.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,13 @@ def add_metric(self, labels, buckets, gsum_value, timestamp=None):
257257
dict(list(zip(self._labelnames, labels)) + [('le', bucket)]),
258258
value, timestamp))
259259
# +Inf is last and provides the count value.
260-
self.samples.extend([
260+
self.samples.append(
261261
Sample(self.name + '_gcount', dict(zip(self._labelnames, labels)), buckets[-1][1], timestamp),
262-
Sample(self.name + '_gsum', dict(zip(self._labelnames, labels)), gsum_value, timestamp),
263-
])
262+
)
263+
if gsum_value is not None:
264+
self.samples.append(
265+
Sample(self.name + '_gsum', dict(zip(self._labelnames, labels)), gsum_value, timestamp),
266+
)
264267

265268

266269
class InfoMetricFamily(Metric):

Diff for: prometheus_client/samples.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,15 @@ def __gt__(self, other):
3232

3333

3434
# Timestamp and exemplar are optional.
35-
# Value can be an int or a float.
35+
# Value must be a float.
3636
# Timestamp can be a float containing a unixtime in seconds,
3737
# a Timestamp object, or None.
3838
# Exemplar can be an Exemplar object, or None.
39-
Sample = namedtuple('Sample', ['name', 'labels', 'value', 'timestamp', 'exemplar'])
40-
Sample.__new__.__defaults__ = (None, None)
39+
sample = namedtuple('Sample', ['name', 'labels', 'value', 'timestamp', 'exemplar'])
40+
41+
# Wrap the namedtuple to provide eage type-checking that value is a float.
42+
def Sample(name, labels, value, timestamp = None, exemplar = None):
43+
return sample(name, labels, float(value), timestamp, exemplar)
4144

4245
Exemplar = namedtuple('Exemplar', ['labels', 'value', 'timestamp'])
4346
Exemplar.__new__.__defaults__ = (None,)

Diff for: tests/test_exposition.py

+18-15
Original file line numberDiff line numberDiff line change
@@ -348,17 +348,6 @@ def collect(self):
348348
return [self.metric_family]
349349

350350

351-
def _expect_metric_exception(registry, expected_error):
352-
try:
353-
generate_latest(registry)
354-
except expected_error as exception:
355-
assert isinstance(exception.args[-1], core.Metric)
356-
# Got a valid error as expected, return quietly
357-
return
358-
359-
raise RuntimeError('Expected exception not raised')
360-
361-
362351
@pytest.mark.parametrize('MetricFamily', [
363352
core.CounterMetricFamily,
364353
core.GaugeMetricFamily,
@@ -373,7 +362,12 @@ def _expect_metric_exception(registry, expected_error):
373362
def test_basic_metric_families(registry, MetricFamily, value, error):
374363
metric_family = MetricFamily(MetricFamily.__name__, 'help')
375364
registry.register(Collector(metric_family, value))
376-
_expect_metric_exception(registry, error)
365+
try:
366+
generate_latest(registry)
367+
except error as exception:
368+
# Got a valid error as expected, return quietly
369+
return
370+
raise RuntimeError('Expected exception not raised')
377371

378372

379373
@pytest.mark.parametrize('count_value,sum_value,error', [
@@ -389,14 +383,18 @@ def test_basic_metric_families(registry, MetricFamily, value, error):
389383
def test_summary_metric_family(registry, count_value, sum_value, error):
390384
metric_family = core.SummaryMetricFamily('summary', 'help')
391385
registry.register(Collector(metric_family, count_value, sum_value))
392-
_expect_metric_exception(registry, error)
386+
try:
387+
generate_latest(registry)
388+
except error as exception:
389+
# Got a valid error as expected, return quietly
390+
return
391+
raise RuntimeError('Expected exception not raised')
393392

394393

395394
@pytest.mark.parametrize('MetricFamily', [
396395
core.GaugeHistogramMetricFamily,
397396
])
398397
@pytest.mark.parametrize('buckets,sum_value,error', [
399-
([('spam', 0), ('eggs', 0)], None, TypeError),
400398
([('spam', 0), ('eggs', None)], 0, TypeError),
401399
([('spam', 0), (None, 0)], 0, AttributeError),
402400
([('spam', None), ('eggs', 0)], 0, TypeError),
@@ -408,7 +406,12 @@ def test_summary_metric_family(registry, count_value, sum_value, error):
408406
def test_histogram_metric_families(MetricFamily, registry, buckets, sum_value, error):
409407
metric_family = MetricFamily(MetricFamily.__name__, 'help')
410408
registry.register(Collector(metric_family, buckets, sum_value))
411-
_expect_metric_exception(registry, error)
409+
try:
410+
generate_latest(registry)
411+
except error as exception:
412+
# Got a valid error as expected, return quietly
413+
return
414+
raise RuntimeError('Expected exception not raised')
412415

413416

414417
if __name__ == '__main__':

0 commit comments

Comments
 (0)