Re-organize prometheus tests into the unit testing category

pull/2069/head
derekpierre 2020-06-01 14:18:11 -04:00
parent 28b29edd70
commit d282900bd0
4 changed files with 261 additions and 282 deletions

View File

@ -1,75 +0,0 @@
from __future__ import unicode_literals
from prometheus_client.utils import floatToGoString
from twisted.web.resource import Resource
from prometheus_client.registry import REGISTRY
import json
from prometheus_client.core import Timestamp
class MetricsEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Timestamp):
return obj.__float__()
return json.JSONEncoder.default(self, obj)
class JSONMetricsResource(Resource):
"""
Twisted ``Resource`` that serves metrics in JSON.
"""
isLeaf = True
def __init__(self, registry=REGISTRY):
self.registry = registry
def render_GET(self, request):
request.setHeader(b'Content-Type', "text/json")
return self.generate_latest_json()
@staticmethod
def get_exemplar(sample, metric):
if not sample.exemplar:
return {}
elif metric.type not in ('histogram', 'gaugehistogram') \
or not sample.name.endswith('_bucket'):
raise ValueError(
"Metric {} has exemplars, but is not a "
"histogram bucket".format(metric.name)
)
return {
"labels": sample.exemplar.labels,
"value": floatToGoString(sample.exemplar.value),
"timestamp": sample.exemplar.timestamp
}
def get_sample(self, sample, metric):
return {
"sample_name": sample.name,
"labels": sample.labels,
"value": floatToGoString(sample.value),
"timestamp": sample.timestamp,
"exemplar": self.get_exemplar(sample, metric)
}
def get_metric(self, metric):
return {
"samples": [self.get_sample(sample, metric) for sample in metric.samples],
"help": metric.documentation,
"type": metric.type
}
def generate_latest_json(self):
"""
Returns the metrics from the registry
in latest JSON format as a string.
"""
output = {}
for metric in self.registry.collect():
try:
output[metric.name] = self.get_metric(metric)
except Exception as exception:
exception.args = (exception.args or ('',)) + (metric,)
raise
json_dump = json.dumps(output, cls=MetricsEncoder).encode('utf-8')
return json_dump

View File

@ -19,12 +19,19 @@ try:
from prometheus_client import Gauge, Enum, Counter, Info, Histogram, Summary
except ImportError:
raise ImportError('prometheus_client is not installed - Install it and try again.')
import json
from typing import List, Union, Tuple
from prometheus_client.core import Timestamp
from prometheus_client.registry import REGISTRY
from prometheus_client.utils import floatToGoString
from twisted.internet import reactor, task
from twisted.web.resource import Resource
import nucypher
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent, WorkLockAgent, PolicyManagerAgent
from nucypher.blockchain.eth.actors import NucypherTokenActor
from typing import List, Union, Tuple
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent, WorkLockAgent, PolicyManagerAgent
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
ContractAgents = Union[StakingEscrowAgent, WorkLockAgent, PolicyManagerAgent]
@ -37,6 +44,75 @@ class PrometheusMetricsConfig:
self.listen_address = listen_address
class MetricsEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Timestamp):
return obj.__float__()
return json.JSONEncoder.default(self, obj)
class JSONMetricsResource(Resource):
"""
Twisted ``Resource`` that serves metrics in JSON.
"""
isLeaf = True
def __init__(self, registry=REGISTRY):
self.registry = registry
def render_GET(self, request):
request.setHeader(b'Content-Type', "text/json")
return self.generate_latest_json()
@staticmethod
def get_exemplar(sample, metric):
if not sample.exemplar:
return {}
elif metric.type not in ('histogram', 'gaugehistogram') \
or not sample.name.endswith('_bucket'):
raise ValueError(
"Metric {} has exemplars, but is not a "
"histogram bucket".format(metric.name)
)
return {
"labels": sample.exemplar.labels,
"value": floatToGoString(sample.exemplar.value),
"timestamp": sample.exemplar.timestamp
}
def get_sample(self, sample, metric):
return {
"sample_name": sample.name,
"labels": sample.labels,
"value": floatToGoString(sample.value),
"timestamp": sample.timestamp,
"exemplar": self.get_exemplar(sample, metric)
}
def get_metric(self, metric):
return {
"samples": [self.get_sample(sample, metric) for sample in metric.samples],
"help": metric.documentation,
"type": metric.type
}
def generate_latest_json(self):
"""
Returns the metrics from the registry
in latest JSON format as a string.
"""
output = {}
for metric in self.registry.collect():
try:
output[metric.name] = self.get_metric(metric)
except Exception as exception:
exception.args = (exception.args or ('',)) + (metric,)
raise
json_dump = json.dumps(output, cls=MetricsEncoder).encode('utf-8')
return json_dump
class BaseEventMetricsCollector:
def __init__(self, staker_address: str, worker_address: str, contract_agent: ContractAgents, event_name: str,
@ -292,7 +368,6 @@ def initialize_prometheus_exporter(ursula, prometheus_config: PrometheusMetricsC
from prometheus_client.twisted import MetricsResource
from twisted.web.resource import Resource
from twisted.web.server import Site
from .json_metrics_export import JSONMetricsResource
metrics_prefix = prometheus_config.metrics_prefix

View File

@ -1,204 +0,0 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import unicode_literals
import json
import sys
import time
import unittest
from prometheus_client import (
CollectorRegistry, Counter, Enum,
Gauge, Histogram, Info, Metric, Summary,
)
from prometheus_client.core import GaugeHistogramMetricFamily, Timestamp
from nucypher.utilities.json_metrics_export import JSONMetricsResource
class TestGenerateJSON(unittest.TestCase):
def setUp(self):
self.registry = CollectorRegistry()
self.json_exporter = JSONMetricsResource(self.registry)
# Mock time so _created values are fixed.
self.old_time = time.time
time.time = lambda: 123.456
def tearDown(self):
time.time = self.old_time
def custom_collector(self, metric_family):
class CustomCollector(object):
def collect(self):
return [metric_family]
self.registry.register(CustomCollector())
def test_counter(self):
c = Counter('cc', 'A counter', registry=self.registry)
c.inc()
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc_total", "labels": {}, "value": "1.0",
"timestamp": null, "exemplar": {}}, {"sample_name": "cc_created", "labels": {}, "value": "123.456",
"timestamp": null, "exemplar": {}}], "help": "A counter", "type": "counter"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_counter_name_unit_append(self):
c = Counter('requests', 'Request counter', unit="total", registry=self.registry)
c.inc()
self.assertEqual(json.loads("""{"requests_total": {"samples": [{"sample_name": "requests_total", "labels": {
}, "value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "requests_created", "labels": {},
"value": "123.456", "timestamp": null, "exemplar": {}}], "help": "Request counter", "type": "counter"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_counter_total(self):
c = Counter('cc_total', 'A counter', registry=self.registry)
c.inc()
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc_total", "labels": {}, "value": "1.0",
"timestamp": null, "exemplar": {}}, {"sample_name": "cc_created", "labels": {}, "value": "123.456",
"timestamp": null, "exemplar": {}}], "help": "A counter", "type": "counter"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_gauge(self):
g = Gauge('gg', 'A gauge', registry=self.registry)
g.set(17)
self.assertEqual(json.loads("""{"gg": {"samples": [{"sample_name": "gg", "labels": {}, "value": "17.0",
"timestamp": null, "exemplar": {}}], "help": "A gauge", "type": "gauge"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_summary(self):
s = Summary('ss', 'A summary', ['a', 'b'], registry=self.registry)
s.labels('c', 'd').observe(17)
self.assertEqual(json.loads("""{"ss": {"samples": [{"sample_name": "ss_count", "labels": {"a": "c",
"b": "d"}, "value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "ss_sum", "labels": {"a": "c",
"b": "d"}, "value": "17.0", "timestamp": null, "exemplar": {}}, {"sample_name": "ss_created", "labels": {"a":
"c", "b": "d"}, "value": "123.456", "timestamp": null, "exemplar": {}}], "help": "A summary",
"type": "summary"}}"""), json.loads(self.json_exporter.generate_latest_json()))
@unittest.skipIf(sys.version_info < (2, 7), "Test requires Python 2.7+.")
def test_histogram(self):
s = Histogram('hh', 'A histogram', registry=self.registry)
s.observe(0.05)
self.assertEqual(json.loads("""{"hh": {"samples": [{"sample_name": "hh_bucket", "labels": {"le": "0.005"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.01"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.025"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.05"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.075"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.1"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.25"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.5"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.75"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "1.0"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "2.5"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "5.0"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "7.5"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "10.0"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "+Inf"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_count", "labels": {}, "value": "1.0",
"timestamp": null, "exemplar": {}}, {"sample_name": "hh_sum", "labels": {}, "value": "0.05", "timestamp":
null, "exemplar": {}}, {"sample_name": "hh_created", "labels": {}, "value": "123.456", "timestamp": null,
"exemplar": {}}], "help": "A histogram", "type": "histogram"}}"""), json.loads(
self.json_exporter.generate_latest_json()))
def test_gaugehistogram(self):
self.custom_collector(GaugeHistogramMetricFamily('gh', 'help', buckets=[('1.0', 4), ('+Inf', 5)], gsum_value=7))
self.assertEqual(json.loads("""{"gh": {"samples": [{"sample_name": "gh_bucket", "labels": {"le": "1.0"},
"value": "4.0", "timestamp": null, "exemplar": {}}, {"sample_name": "gh_bucket", "labels": {"le": "+Inf"},
"value": "5.0", "timestamp": null, "exemplar": {}}, {"sample_name": "gh_gcount", "labels": {},
"value": "5.0", "timestamp": null, "exemplar": {}}, {"sample_name": "gh_gsum", "labels": {}, "value": "7.0",
"timestamp": null, "exemplar": {}}], "help": "help", "type": "gaugehistogram"}}"""), json.loads(
self.json_exporter.generate_latest_json()))
def test_info(self):
i = Info('ii', 'A info', ['a', 'b'], registry=self.registry)
i.labels('c', 'd').info({'foo': 'bar'})
self.assertEqual(json.loads("""{"ii": {"samples": [{"sample_name": "ii_info", "labels": {"a": "c", "b": "d",
"foo": "bar"}, "value": "1.0", "timestamp": null, "exemplar": {}}], "help": "A info", "type": "info"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_enum(self):
i = Enum('ee', 'An enum', ['a', 'b'], registry=self.registry, states=['foo', 'bar'])
i.labels('c', 'd').state('bar')
self.assertEqual(
json.loads("""{"ee": {"samples": [{"sample_name": "ee", "labels": {"a": "c", "b": "d", "ee": "foo"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "ee", "labels": {"a":
"c", "b": "d", "ee": "bar"}, "value": "1.0", "timestamp": null, "exemplar": {}}],
"help": "An enum","type": "stateset"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_unicode(self):
c = Gauge('cc', '\u4500', ['l'], registry=self.registry)
c.labels('\u4500').inc()
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc", "labels": {"l": "\\u4500"}, "value":
"1.0", "timestamp": null, "exemplar": {}}], "help": "\\u4500",
"type": "gauge"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_escaping(self):
g = Gauge('cc', 'A\ngaug\\e', ['a'], registry=self.registry)
g.labels('\\x\n"').inc(1)
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc", "labels": {"a": "\\\\x\\n\\""},
"value": "1.0", "timestamp": null, "exemplar": {}}], "help": "A\\ngaug\\\\e",
"type": "gauge"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_nonnumber(self):
class MyNumber(object):
def __repr__(self):
return "MyNumber(123)"
def __float__(self):
return 123.0
class MyCollector(object):
def collect(self):
metric = Metric("nonnumber", "Non number", 'untyped')
metric.add_sample("nonnumber", {}, MyNumber())
yield metric
self.registry.register(MyCollector())
self.assertEqual(json.loads("""{"nonnumber": {"samples": [{"sample_name": "nonnumber", "labels": {}, "value":
"123.0", "timestamp": null, "exemplar": {}}], "help": "Non number", "type": "unknown"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_timestamp(self):
class MyCollector(object):
def collect(self):
metric = Metric("ts", "help", 'untyped')
metric.add_sample("ts", {"foo": "a"}, 0, 123.456)
metric.add_sample("ts", {"foo": "b"}, 0, -123.456)
metric.add_sample("ts", {"foo": "c"}, 0, 123)
metric.add_sample("ts", {"foo": "d"}, 0, Timestamp(123, 456000000))
metric.add_sample("ts", {"foo": "e"}, 0, Timestamp(123, 456000))
metric.add_sample("ts", {"foo": "f"}, 0, Timestamp(123, 456))
yield metric
self.registry.register(MyCollector())
self.assertEqual(json.loads("""{"ts": {"samples": [{"sample_name": "ts", "labels": {"foo": "a"}, "value":
"0.0", "timestamp": 123.456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "b"}, "value": "0.0",
"timestamp": -123.456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "c"}, "value": "0.0",
"timestamp": 123, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "d"}, "value": "0.0", "timestamp":
123.456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "e"}, "value": "0.0", "timestamp":
123.000456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "f"}, "value": "0.0", "timestamp":
123.000000456, "exemplar": {}}], "help": "help", "type": "unknown"}}"""), json.loads(
self.json_exporter.generate_latest_json()))
if __name__ == '__main__':
unittest.main()

View File

@ -15,6 +15,20 @@
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import unicode_literals
import json
import sys
import time
import unittest
from prometheus_client import (
CollectorRegistry, Counter, Enum,
Gauge, Histogram, Info, Metric, Summary,
)
from prometheus_client.core import GaugeHistogramMetricFamily, Timestamp
from nucypher.utilities.prometheus import JSONMetricsResource
from nucypher.utilities.prometheus import PrometheusMetricsConfig
TEST_PREFIX = 'test_prefix'
@ -29,3 +43,172 @@ def test_prometheus_metrics_config():
assert prometheus_config.port == 2020
assert prometheus_config.metrics_prefix == TEST_PREFIX
assert listen_address == listen_address
class TestGenerateJSON(unittest.TestCase):
def setUp(self):
self.registry = CollectorRegistry()
self.json_exporter = JSONMetricsResource(self.registry)
# Mock time so _created values are fixed.
self.old_time = time.time
time.time = lambda: 123.456
def tearDown(self):
time.time = self.old_time
def custom_collector(self, metric_family):
class CustomCollector(object):
def collect(self):
return [metric_family]
self.registry.register(CustomCollector())
def test_counter(self):
c = Counter('cc', 'A counter', registry=self.registry)
c.inc()
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc_total", "labels": {}, "value": "1.0",
"timestamp": null, "exemplar": {}}, {"sample_name": "cc_created", "labels": {}, "value": "123.456",
"timestamp": null, "exemplar": {}}], "help": "A counter", "type": "counter"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_counter_name_unit_append(self):
c = Counter('requests', 'Request counter', unit="total", registry=self.registry)
c.inc()
self.assertEqual(json.loads("""{"requests_total": {"samples": [{"sample_name": "requests_total", "labels": {
}, "value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "requests_created", "labels": {},
"value": "123.456", "timestamp": null, "exemplar": {}}], "help": "Request counter", "type": "counter"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_counter_total(self):
c = Counter('cc_total', 'A counter', registry=self.registry)
c.inc()
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc_total", "labels": {}, "value": "1.0",
"timestamp": null, "exemplar": {}}, {"sample_name": "cc_created", "labels": {}, "value": "123.456",
"timestamp": null, "exemplar": {}}], "help": "A counter", "type": "counter"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_gauge(self):
g = Gauge('gg', 'A gauge', registry=self.registry)
g.set(17)
self.assertEqual(json.loads("""{"gg": {"samples": [{"sample_name": "gg", "labels": {}, "value": "17.0",
"timestamp": null, "exemplar": {}}], "help": "A gauge", "type": "gauge"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_summary(self):
s = Summary('ss', 'A summary', ['a', 'b'], registry=self.registry)
s.labels('c', 'd').observe(17)
self.assertEqual(json.loads("""{"ss": {"samples": [{"sample_name": "ss_count", "labels": {"a": "c",
"b": "d"}, "value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "ss_sum", "labels": {"a": "c",
"b": "d"}, "value": "17.0", "timestamp": null, "exemplar": {}}, {"sample_name": "ss_created", "labels": {"a":
"c", "b": "d"}, "value": "123.456", "timestamp": null, "exemplar": {}}], "help": "A summary",
"type": "summary"}}"""), json.loads(self.json_exporter.generate_latest_json()))
@unittest.skipIf(sys.version_info < (2, 7), "Test requires Python 2.7+.")
def test_histogram(self):
s = Histogram('hh', 'A histogram', registry=self.registry)
s.observe(0.05)
self.assertEqual(json.loads("""{"hh": {"samples": [{"sample_name": "hh_bucket", "labels": {"le": "0.005"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.01"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.025"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.05"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.075"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.1"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.25"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.5"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "0.75"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "1.0"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "2.5"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "5.0"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "7.5"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "10.0"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_bucket", "labels": {"le": "+Inf"},
"value": "1.0", "timestamp": null, "exemplar": {}}, {"sample_name": "hh_count", "labels": {}, "value": "1.0",
"timestamp": null, "exemplar": {}}, {"sample_name": "hh_sum", "labels": {}, "value": "0.05", "timestamp":
null, "exemplar": {}}, {"sample_name": "hh_created", "labels": {}, "value": "123.456", "timestamp": null,
"exemplar": {}}], "help": "A histogram", "type": "histogram"}}"""), json.loads(
self.json_exporter.generate_latest_json()))
def test_gaugehistogram(self):
self.custom_collector(GaugeHistogramMetricFamily('gh', 'help', buckets=[('1.0', 4), ('+Inf', 5)], gsum_value=7))
self.assertEqual(json.loads("""{"gh": {"samples": [{"sample_name": "gh_bucket", "labels": {"le": "1.0"},
"value": "4.0", "timestamp": null, "exemplar": {}}, {"sample_name": "gh_bucket", "labels": {"le": "+Inf"},
"value": "5.0", "timestamp": null, "exemplar": {}}, {"sample_name": "gh_gcount", "labels": {},
"value": "5.0", "timestamp": null, "exemplar": {}}, {"sample_name": "gh_gsum", "labels": {}, "value": "7.0",
"timestamp": null, "exemplar": {}}], "help": "help", "type": "gaugehistogram"}}"""), json.loads(
self.json_exporter.generate_latest_json()))
def test_info(self):
i = Info('ii', 'A info', ['a', 'b'], registry=self.registry)
i.labels('c', 'd').info({'foo': 'bar'})
self.assertEqual(json.loads("""{"ii": {"samples": [{"sample_name": "ii_info", "labels": {"a": "c", "b": "d",
"foo": "bar"}, "value": "1.0", "timestamp": null, "exemplar": {}}], "help": "A info", "type": "info"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_enum(self):
i = Enum('ee', 'An enum', ['a', 'b'], registry=self.registry, states=['foo', 'bar'])
i.labels('c', 'd').state('bar')
self.assertEqual(
json.loads("""{"ee": {"samples": [{"sample_name": "ee", "labels": {"a": "c", "b": "d", "ee": "foo"},
"value": "0.0", "timestamp": null, "exemplar": {}}, {"sample_name": "ee", "labels": {"a":
"c", "b": "d", "ee": "bar"}, "value": "1.0", "timestamp": null, "exemplar": {}}],
"help": "An enum","type": "stateset"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_unicode(self):
c = Gauge('cc', '\u4500', ['l'], registry=self.registry)
c.labels('\u4500').inc()
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc", "labels": {"l": "\\u4500"}, "value":
"1.0", "timestamp": null, "exemplar": {}}], "help": "\\u4500",
"type": "gauge"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_escaping(self):
g = Gauge('cc', 'A\ngaug\\e', ['a'], registry=self.registry)
g.labels('\\x\n"').inc(1)
self.assertEqual(json.loads("""{"cc": {"samples": [{"sample_name": "cc", "labels": {"a": "\\\\x\\n\\""},
"value": "1.0", "timestamp": null, "exemplar": {}}], "help": "A\\ngaug\\\\e",
"type": "gauge"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_nonnumber(self):
class MyNumber(object):
def __repr__(self):
return "MyNumber(123)"
def __float__(self):
return 123.0
class MyCollector(object):
def collect(self):
metric = Metric("nonnumber", "Non number", 'untyped')
metric.add_sample("nonnumber", {}, MyNumber())
yield metric
self.registry.register(MyCollector())
self.assertEqual(json.loads("""{"nonnumber": {"samples": [{"sample_name": "nonnumber", "labels": {}, "value":
"123.0", "timestamp": null, "exemplar": {}}], "help": "Non number", "type": "unknown"}}"""),
json.loads(self.json_exporter.generate_latest_json()))
def test_timestamp(self):
class MyCollector(object):
def collect(self):
metric = Metric("ts", "help", 'untyped')
metric.add_sample("ts", {"foo": "a"}, 0, 123.456)
metric.add_sample("ts", {"foo": "b"}, 0, -123.456)
metric.add_sample("ts", {"foo": "c"}, 0, 123)
metric.add_sample("ts", {"foo": "d"}, 0, Timestamp(123, 456000000))
metric.add_sample("ts", {"foo": "e"}, 0, Timestamp(123, 456000))
metric.add_sample("ts", {"foo": "f"}, 0, Timestamp(123, 456))
yield metric
self.registry.register(MyCollector())
self.assertEqual(json.loads("""{"ts": {"samples": [{"sample_name": "ts", "labels": {"foo": "a"}, "value":
"0.0", "timestamp": 123.456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "b"}, "value": "0.0",
"timestamp": -123.456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "c"}, "value": "0.0",
"timestamp": 123, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "d"}, "value": "0.0", "timestamp":
123.456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "e"}, "value": "0.0", "timestamp":
123.000456, "exemplar": {}}, {"sample_name": "ts", "labels": {"foo": "f"}, "value": "0.0", "timestamp":
123.000000456, "exemplar": {}}], "help": "help", "type": "unknown"}}"""), json.loads(
self.json_exporter.generate_latest_json()))