From f04dd397d7c244d097ddab30e0eda86e7f093da7 Mon Sep 17 00:00:00 2001 From: Brian Brazil Date: Fri, 20 Feb 2015 07:27:42 +0000 Subject: [PATCH] Make code and tests for for python 3 too. --- README.md | 12 ++++++ prometheus_client/__init__.py | 24 +++++++---- tests/test_client.py | 78 +++++++++++++++++++---------------- 3 files changed, 69 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index ca0b3fda..6455d820 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ There are several options for exporting metrics. Metrics are usuall exposed over HTTP, to be read by the Prometheus server. For example: +Python 2: + ```python from prometheus_client import MetricsHandler from BaseHTTPServer import HTTPServer @@ -124,6 +126,16 @@ httpd = HTTPServer(server_address, MetricsHandler) httpd.serve_forever() ``` +Python 3: + +```python +from prometheus_client import MetricsHandler +from http.server import HTTPServer +server_address = ('', 8000) +httpd = HTTPServer(server_address, MetricsHandler) +httpd.serve_forever() +``` + Visit [http://localhost:8000/](http://localhost:8000/) to view the metrics. ## Node exporter textfile collector diff --git a/prometheus_client/__init__.py b/prometheus_client/__init__.py index e100b274..8a87285d 100644 --- a/prometheus_client/__init__.py +++ b/prometheus_client/__init__.py @@ -1,12 +1,18 @@ #!/usr/bin/python +from __future__ import unicode_literals + import copy import re import os import time import threading from contextlib import contextmanager -from BaseHTTPServer import BaseHTTPRequestHandler +try: + from BaseHTTPServer import BaseHTTPRequestHandler +except ImportError: + # Python 3 + from http.server import BaseHTTPRequestHandler from functools import wraps from threading import Lock @@ -116,7 +122,7 @@ def remove(self, *labelvalues): def _samples(self): with self._lock: metrics = self._metrics.copy() - for labels, metric in metrics.iteritems(): + for labels, metric in metrics.items(): for suffix, _, value in metric._samples(): yield (suffix, dict(zip(self._labelnames, labels)), value) @@ -298,18 +304,18 @@ def generate_latest(registry=REGISTRY): '''Returns the metrics from the registry in latest text format as a string.''' output = [] for metric in registry.collect(): - output.append(u'# HELP %s %s' % ( + output.append('# HELP {0} {1}'.format( metric._name, metric._documentation.replace('\\', r'\\').replace('\n', r'\n'))) - output.append(u'\n# TYPE %s %s\n' % (metric._name, metric._type)) + output.append('\n# TYPE {0} {1}\n'.format(metric._name, metric._type)) for name, labels, value in metric._samples: if labels: - labelstr = u'{%s}' % ','.join( - [u'%s="%s"' % ( + labelstr = '{{{0}}}'.format(','.join( + ['{0}="{1}"'.format( k, v.replace('\\', r'\\').replace('\n', r'\n').replace('\'', r'\'')) - for k, v in labels.items()]) + for k, v in labels.items()])) else: - labelstr = u'' - output.append(u'%s%s %s\n' % (name, labelstr, value)) + labelstr = '' + output.append('{0}{1} {2}\n'.format(name, labelstr, value)) return ''.join(output).encode('utf-8') diff --git a/tests/test_client.py b/tests/test_client.py index 2eae2725..9bf82edb 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals import unittest from prometheus_client import Gauge, Counter, Summary @@ -9,11 +10,11 @@ def setUp(self): self.counter = Counter('c', 'help', registry=self.registry) def test_increment(self): - self.assertEquals(0, self.registry.get_sample_value('c')) + self.assertEqual(0, self.registry.get_sample_value('c')) self.counter.inc() - self.assertEquals(1, self.registry.get_sample_value('c')) + self.assertEqual(1, self.registry.get_sample_value('c')) self.counter.inc(7) - self.assertEquals(8, self.registry.get_sample_value('c')) + self.assertEqual(8, self.registry.get_sample_value('c')) def test_negative_increment_raises(self): self.assertRaises(ValueError, self.counter.inc, -1) @@ -29,17 +30,17 @@ def f(r): f(False) except TypeError: pass - self.assertEquals(0, self.registry.get_sample_value('c')) + self.assertEqual(0, self.registry.get_sample_value('c')) try: f(True) except ValueError: raised = True - self.assertEquals(1, self.registry.get_sample_value('c')) + self.assertEqual(1, self.registry.get_sample_value('c')) def test_block_decorator(self): with self.counter.count_exceptions(): pass - self.assertEquals(0, self.registry.get_sample_value('c')) + self.assertEqual(0, self.registry.get_sample_value('c')) raised = False try: with self.counter.count_exceptions(): @@ -47,7 +48,7 @@ def test_block_decorator(self): except: raised = True self.assertTrue(raised) - self.assertEquals(1, self.registry.get_sample_value('c')) + self.assertEqual(1, self.registry.get_sample_value('c')) class TestGauge(unittest.TestCase): def setUp(self): @@ -55,27 +56,27 @@ def setUp(self): self.gauge = Gauge('g', 'help', registry=self.registry) def test_gauge(self): - self.assertEquals(0, self.registry.get_sample_value('g')) + self.assertEqual(0, self.registry.get_sample_value('g')) self.gauge.inc() - self.assertEquals(1, self.registry.get_sample_value('g')) + self.assertEqual(1, self.registry.get_sample_value('g')) self.gauge.dec(3) - self.assertEquals(-2, self.registry.get_sample_value('g')) + self.assertEqual(-2, self.registry.get_sample_value('g')) self.gauge.set(9) - self.assertEquals(9, self.registry.get_sample_value('g')) + self.assertEqual(9, self.registry.get_sample_value('g')) def test_function_decorator(self): - self.assertEquals(0, self.registry.get_sample_value('g')) + self.assertEqual(0, self.registry.get_sample_value('g')) @self.gauge.track_inprogress() def f(): - self.assertEquals(1, self.registry.get_sample_value('g')) + self.assertEqual(1, self.registry.get_sample_value('g')) f() - self.assertEquals(0, self.registry.get_sample_value('g')) + self.assertEqual(0, self.registry.get_sample_value('g')) def test_block_decorator(self): - self.assertEquals(0, self.registry.get_sample_value('g')) + self.assertEqual(0, self.registry.get_sample_value('g')) with self.gauge.track_inprogress(): - self.assertEquals(1, self.registry.get_sample_value('g')) - self.assertEquals(0, self.registry.get_sample_value('g')) + self.assertEqual(1, self.registry.get_sample_value('g')) + self.assertEqual(0, self.registry.get_sample_value('g')) class TestSummary(unittest.TestCase): def setUp(self): @@ -83,25 +84,25 @@ def setUp(self): self.summary = Summary('s', 'help', registry=self.registry) def test_summary(self): - self.assertEquals(0, self.registry.get_sample_value('s_count')) - self.assertEquals(0, self.registry.get_sample_value('s_sum')) + self.assertEqual(0, self.registry.get_sample_value('s_count')) + self.assertEqual(0, self.registry.get_sample_value('s_sum')) self.summary.observe(10) - self.assertEquals(1, self.registry.get_sample_value('s_count')) - self.assertEquals(10, self.registry.get_sample_value('s_sum')) + self.assertEqual(1, self.registry.get_sample_value('s_count')) + self.assertEqual(10, self.registry.get_sample_value('s_sum')) def test_function_decorator(self): - self.assertEquals(0, self.registry.get_sample_value('s_count')) + self.assertEqual(0, self.registry.get_sample_value('s_count')) @self.summary.time() def f(): pass f() - self.assertEquals(1, self.registry.get_sample_value('s_count')) + self.assertEqual(1, self.registry.get_sample_value('s_count')) def test_block_decorator(self): - self.assertEquals(0, self.registry.get_sample_value('s_count')) + self.assertEqual(0, self.registry.get_sample_value('s_count')) with self.summary.time(): pass - self.assertEquals(1, self.registry.get_sample_value('s_count')) + self.assertEqual(1, self.registry.get_sample_value('s_count')) class TestMetricWrapper(unittest.TestCase): def setUp(self): @@ -111,18 +112,18 @@ def setUp(self): def test_child(self): self.counter.labels('x').inc() - self.assertEquals(1, self.registry.get_sample_value('c', {'l': 'x'})) + self.assertEqual(1, self.registry.get_sample_value('c', {'l': 'x'})) self.two_labels.labels('x', 'y').inc(2) - self.assertEquals(2, self.registry.get_sample_value('two', {'a': 'x', 'b': 'y'})) + self.assertEqual(2, self.registry.get_sample_value('two', {'a': 'x', 'b': 'y'})) def test_remove(self): self.counter.labels('x').inc() self.counter.labels('y').inc(2) - self.assertEquals(1, self.registry.get_sample_value('c', {'l': 'x'})) - self.assertEquals(2, self.registry.get_sample_value('c', {'l': 'y'})) + self.assertEqual(1, self.registry.get_sample_value('c', {'l': 'x'})) + self.assertEqual(2, self.registry.get_sample_value('c', {'l': 'y'})) self.counter.remove('x') - self.assertEquals(None, self.registry.get_sample_value('c', {'l': 'x'})) - self.assertEquals(2, self.registry.get_sample_value('c', {'l': 'y'})) + self.assertEqual(None, self.registry.get_sample_value('c', {'l': 'x'})) + self.assertEqual(2, self.registry.get_sample_value('c', {'l': 'y'})) def test_incorrect_label_count_raises(self): self.assertRaises(ValueError, self.counter.labels) @@ -133,7 +134,7 @@ def test_incorrect_label_count_raises(self): def test_namespace_subsystem_concatenated(self): c = Counter('c', 'help', namespace='a', subsystem='b', registry=self.registry) c.inc() - self.assertEquals(1, self.registry.get_sample_value('a_b_c')) + self.assertEqual(1, self.registry.get_sample_value('a_b_c')) def test_invalid_names_raise(self): self.assertRaises(ValueError, Counter, '', 'help') @@ -150,22 +151,27 @@ def setUp(self): def test_counter(self): c = Counter('cc', 'A counter', registry=self.registry) c.inc() - self.assertEquals('# HELP cc A counter\n# TYPE cc counter\ncc 1.0\n', generate_latest(self.registry)) + self.assertEqual(b'# HELP cc A counter\n# TYPE cc counter\ncc 1.0\n', generate_latest(self.registry)) def test_gauge(self): g = Gauge('gg', 'A gauge', registry=self.registry) g.set(17) - self.assertEquals('# HELP gg A gauge\n# TYPE gg gauge\ngg 17.0\n', generate_latest(self.registry)) + self.assertEqual(b'# HELP gg A gauge\n# TYPE gg gauge\ngg 17.0\n', generate_latest(self.registry)) def test_summary(self): s = Summary('ss', 'A summary', ['a', 'b'], registry=self.registry) s.labels('c', 'd').observe(17) - self.assertEquals('# HELP ss A summary\n# TYPE ss summary\nss_count{a="c",b="d"} 1.0\nss_sum{a="c",b="d"} 17.0\n', generate_latest(self.registry)) + self.assertEqual(b'# HELP ss A summary\n# TYPE ss summary\nss_count{a="c",b="d"} 1.0\nss_sum{a="c",b="d"} 17.0\n', generate_latest(self.registry)) + + def test_unicode(self): + c = Counter('cc', '\u4500', ['l'], registry=self.registry) + c.labels('\u4500').inc() + self.assertEqual(b'# HELP cc \xe4\x94\x80\n# TYPE cc counter\ncc{l="\xe4\x94\x80"} 1.0\n', generate_latest(self.registry)) def test_escaping(self): c = Counter('cc', 'A\ncount\\er', ['a'], registry=self.registry) c.labels('\\x\n').inc(1) - self.assertEquals('# HELP cc A\\ncount\\\\er\n# TYPE cc counter\ncc{a="\\\\x\\n"} 1.0\n', generate_latest(self.registry)) + self.assertEqual(b'# HELP cc A\\ncount\\\\er\n# TYPE cc counter\ncc{a="\\\\x\\n"} 1.0\n', generate_latest(self.registry)) if __name__ == '__main__':