mirror of https://github.com/nucypher/nucypher.git
Re-organize prometheus tests into the unit testing category
parent
28b29edd70
commit
d282900bd0
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
|
@ -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()))
|
||||
|
|
Loading…
Reference in New Issue