예제 #1
0
    def test_counter_exemplars_empty_brackets(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{} 0 123 # {a="b"} 0.5
# EOF
""")
        cfm = CounterMetricFamily("a", "help")
        cfm.add_sample("a_total", {}, 0.0, Timestamp(123, 0), Exemplar({"a": "b"}, 0.5))
        self.assertEqual([cfm], list(families))
예제 #2
0
    def test_uint64_counter(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total 9223372036854775808
# EOF
""")
        self.assertEqual(
            [CounterMetricFamily("a", "help", value=9223372036854775808)],
            list(families))
예제 #3
0
    def test_simple_summary(self):
        families = text_string_to_metric_families("""# TYPE a summary
# HELP a help
a_count 1
a_sum 2
# EOF
""")
        summary = SummaryMetricFamily("a", "help", count_value=1, sum_value=2)
        self.assertEqual([summary], list(families))
예제 #4
0
    def test_labels_with_curly_braces(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{foo="bar",bar="b{a}z"} 1
# EOF
""")
        metric_family = CounterMetricFamily("a", "help", labels=["foo", "bar"])
        metric_family.add_metric(["bar", "b{a}z"], 1)
        self.assertEqual([metric_family], list(families))
예제 #5
0
    def test_simple_gaugehistogram(self):
        families = text_string_to_metric_families("""# TYPE a gaugehistogram
# HELP a help
a_bucket{le="1"} 0
a_bucket{le="+Inf"} 3
a_gcount 3
a_gsum 2
# EOF
""")
        self.assertEqual([GaugeHistogramMetricFamily("a", "help", gsum_value=2, buckets=[("1", 0.0), ("+Inf", 3.0)])], list(families))
예제 #6
0
    def test_negative_bucket_histogram(self):
        families = text_string_to_metric_families("""# TYPE a histogram
# HELP a help
a_bucket{le="-1.0"} 0
a_bucket{le="1.0"} 1
a_bucket{le="+Inf"} 3
# EOF
""")
        self.assertEqual([HistogramMetricFamily("a", "help", buckets=[("-1.0", 0.0), ("1.0", 1.0), ("+Inf", 3.0)])],
                         list(families))
예제 #7
0
    def test_unit_gauge(self):
        families = text_string_to_metric_families("""# TYPE a_seconds gauge
# UNIT a_seconds seconds
# HELP a_seconds help
a_seconds 1
# EOF
""")
        self.assertEqual(
            [GaugeMetricFamily("a_seconds", "help", value=1, unit='seconds')],
            list(families))
예제 #8
0
    def test_labels_and_infinite(self):
        families = text_string_to_metric_families("""# TYPE a gauge
# HELP a help
a{foo="bar"} +Inf
a{foo="baz"} -Inf
# EOF
""")
        metric_family = GaugeMetricFamily("a", "help", labels=["foo"])
        metric_family.add_metric(["bar"], float('inf'))
        metric_family.add_metric(["baz"], float('-inf'))
        self.assertEqual([metric_family], list(families))
예제 #9
0
    def test_escaping(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a he\\n\\\\l\\tp
a_total{foo="b\\"a\\nr"} 1
a_total{foo="b\\\\a\\z"} 2
# EOF
""")
        metric_family = CounterMetricFamily("a", "he\n\\l\\tp", labels=["foo"])
        metric_family.add_metric(["b\"a\nr"], 1)
        metric_family.add_metric(["b\\a\\z"], 2)
        self.assertEqual([metric_family], list(families))
예제 #10
0
    def test_empty_label(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{foo="bar"} 1
a_total{foo=""} 2
# EOF
""")
        metric_family = CounterMetricFamily("a", "help", labels=["foo"])
        metric_family.add_metric(["bar"], 1)
        metric_family.add_metric([""], 2)
        self.assertEqual([metric_family], list(families))
예제 #11
0
    def test_hash_in_label_value(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{foo="foo # bar"} 1
a_total{foo="} foo # bar # "} 1
# EOF
""")
        a = CounterMetricFamily("a", "help", labels=["foo"])
        a.add_metric(["foo # bar"], 1)
        a.add_metric(["} foo # bar # "], 1)
        self.assertEqual([a], list(families))
예제 #12
0
    def test_simple_histogram_float_values(self):
        families = text_string_to_metric_families("""# TYPE a histogram
# HELP a help
a_bucket{le="1.0"} 0.0
a_bucket{le="+Inf"} 3.0
a_count 3.0
a_sum 2.0
# EOF
""")
        self.assertEqual([HistogramMetricFamily("a", "help", sum_value=2, buckets=[("1.0", 0.0), ("+Inf", 3.0)])],
                         list(families))
예제 #13
0
    def test_info_timestamps(self):
        families = text_string_to_metric_families("""# TYPE a info
# HELP a help
a_info{a="1",foo="bar"} 1 1
a_info{a="2",foo="bar"} 1 0
# EOF
""")
        imf = InfoMetricFamily("a", "help")
        imf.add_sample("a_info", {"a": "1", "foo": "bar"}, 1, Timestamp(1, 0))
        imf.add_sample("a_info", {"a": "2", "foo": "bar"}, 1, Timestamp(0, 0))
        self.assertEqual([imf], list(families))
예제 #14
0
    def test_simple_stateset(self):
        families = text_string_to_metric_families("""# TYPE a stateset
# HELP a help
a{a="bar"} 0
a{a="foo"} 1.0
# EOF
""")
        self.assertEqual(
            [StateSetMetricFamily("a", "help", {
                'foo': True,
                'bar': False
            })], list(families))
예제 #15
0
    def test_negative_bucket_gaugehistogram(self):
        families = text_string_to_metric_families("""# TYPE a gaugehistogram
# HELP a help
a_bucket{le="-1.0"} 1
a_bucket{le="1.0"} 2
a_bucket{le="+Inf"} 3
a_gcount 3
a_gsum -5
# EOF
""")
        self.assertEqual([GaugeHistogramMetricFamily("a", "help", gsum_value=-5, buckets=[("-1.0", 1.0), ("1.0", 2.0), ("+Inf", 3.0)])],
                         list(families))
예제 #16
0
    def test_histogram_noncanonical(self):
        families = text_string_to_metric_families("""# TYPE a histogram
# HELP a help
a_bucket{le="0.00000000001"} 0
a_bucket{le="1.1e-4"} 0
a_bucket{le="1.1e-3"} 0
a_bucket{le="100000000000.0"} 0
a_bucket{le="+Inf"} 3
a_count 3
a_sum 2
# EOF
""")
        list(families)
예제 #17
0
    def test_gaugehistogram_exemplars(self):
        families = text_string_to_metric_families("""# TYPE a gaugehistogram
# HELP a help
a_bucket{le="1.0"} 0 123 # {a="b"} 0.5
a_bucket{le="2.0"} 2 123 # {a="c"} 0.5
a_bucket{le="+Inf"} 3 123 # {a="d"} 4 123
# EOF
""")
        hfm = GaugeHistogramMetricFamily("a", "help")
        hfm.add_sample("a_bucket", {"le": "1.0"}, 0.0, Timestamp(123, 0), Exemplar({"a": "b"}, 0.5))
        hfm.add_sample("a_bucket", {"le": "2.0"}, 2.0, Timestamp(123, 0), Exemplar({"a": "c"}, 0.5)),
        hfm.add_sample("a_bucket", {"le": "+Inf"}, 3.0, Timestamp(123, 0), Exemplar({"a": "d"}, 4, Timestamp(123, 0)))
        self.assertEqual([hfm], list(families))
예제 #18
0
    def test_histogram_exemplars(self):
        families = text_string_to_metric_families("""# TYPE a histogram
# HELP a help
a_bucket{le="1"} 0 # {a="b"} 0.5
a_bucket{le="2"} 2 # {a="c"} 0.5
a_bucket{le="+Inf"} 3 # {a="1234567890123456789012345678901234567890123456789012345678"} 4 123
# EOF
""")
        hfm = HistogramMetricFamily("a", "help")
        hfm.add_sample("a_bucket", {"le": "1"}, 0.0, None, Exemplar({"a": "b"}, 0.5))
        hfm.add_sample("a_bucket", {"le": "2"}, 2.0, None, Exemplar({"a": "c"}, 0.5)),
        hfm.add_sample("a_bucket", {"le": "+Inf"}, 3.0, None, Exemplar({"a": "1234567890123456789012345678901234567890123456789012345678"}, 4, Timestamp(123, 0)))
        self.assertEqual([hfm], list(families))
예제 #19
0
    def test_exemplars_with_hash_in_label_values(self):
        families = text_string_to_metric_families("""# TYPE a histogram
# HELP a help
a_bucket{le="1.0",foo="bar # "} 0 # {a="b",foo="bar # bar"} 0.5
a_bucket{le="2.0",foo="bar # "} 2 # {a="c",foo="bar # bar"} 0.5
a_bucket{le="+Inf",foo="bar # "} 3 # {a="d",foo="bar # bar"} 4
# EOF
""")
        hfm = HistogramMetricFamily("a", "help")
        hfm.add_sample("a_bucket", {"le": "1.0", "foo": "bar # "}, 0.0, None, Exemplar({"a": "b", "foo": "bar # bar"}, 0.5))
        hfm.add_sample("a_bucket", {"le": "2.0", "foo": "bar # "}, 2.0, None, Exemplar({"a": "c", "foo": "bar # bar"}, 0.5))
        hfm.add_sample("a_bucket", {"le": "+Inf", "foo": "bar # "}, 3.0, None, Exemplar({"a": "d", "foo": "bar # bar"}, 4))
        self.assertEqual([hfm], list(families))
예제 #20
0
    def test_label_escaping(self):
        for escaped_val, unescaped_val in [('foo', 'foo'), ('\\foo', '\\foo'), ('\\\\foo', '\\foo'),
                                           ('foo\\\\', 'foo\\'), ('\\\\', '\\'), ('\\n', '\n'),
                                           ('\\\\n', '\\n'), ('\\\\\\n', '\\\n'), ('\\"', '"'), ('\\\\\\"', '\\"')]:
            families = list(text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{foo="%s",bar="baz"} 1
# EOF
""" % escaped_val))
            metric_family = CounterMetricFamily(
                "a", "help", labels=["foo", "bar"])
            metric_family.add_metric([unescaped_val, "baz"], 1)
            self.assertEqual([metric_family], list(families))
예제 #21
0
    def test_summary_quantiles(self):
        families = text_string_to_metric_families("""# TYPE a summary
# HELP a help
a_count 1
a_sum 2
a{quantile="0.5"} 0.7
# EOF
""")
        # The Python client doesn't support quantiles, but we
        # still need to be able to parse them.
        metric_family = SummaryMetricFamily("a", "help", count_value=1, sum_value=2)
        metric_family.add_sample("a", {"quantile": "0.5"}, 0.7)
        self.assertEqual([metric_family], list(families))
예제 #22
0
    def test_roundtrip(self):
        text = """# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0.013300656000000001
go_gc_duration_seconds{quantile="0.25"} 0.013638736
go_gc_duration_seconds{quantile="0.5"} 0.013759906
go_gc_duration_seconds{quantile="0.75"} 0.013962066
go_gc_duration_seconds{quantile="1"} 0.021383540000000003
go_gc_duration_seconds_sum 56.12904785
go_gc_duration_seconds_count 7476.0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 166.0
# HELP prometheus_local_storage_indexing_batch_duration_milliseconds Quantiles for batch indexing duration in milliseconds.
# TYPE prometheus_local_storage_indexing_batch_duration_milliseconds summary
prometheus_local_storage_indexing_batch_duration_milliseconds{quantile="0.5"} NaN
prometheus_local_storage_indexing_batch_duration_milliseconds{quantile="0.9"} NaN
prometheus_local_storage_indexing_batch_duration_milliseconds{quantile="0.99"} NaN
prometheus_local_storage_indexing_batch_duration_milliseconds_sum 871.5665949999999
prometheus_local_storage_indexing_batch_duration_milliseconds_count 229.0
# HELP process_cpu_seconds Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds counter
process_cpu_seconds_total 29323.4
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 2478268416.0
# HELP prometheus_build_info A metric with a constant '1' value labeled by version, revision, and branch from which Prometheus was built.
# TYPE prometheus_build_info gauge
prometheus_build_info{branch="HEAD",revision="ef176e5",version="0.16.0rc1"} 1.0
# HELP prometheus_local_storage_chunk_ops The total number of chunk operations by their type.
# TYPE prometheus_local_storage_chunk_ops counter
prometheus_local_storage_chunk_ops_total{type="clone"} 28.0
prometheus_local_storage_chunk_ops_total{type="create"} 997844.0
prometheus_local_storage_chunk_ops_total{type="drop"} 1345758.0
prometheus_local_storage_chunk_ops_total{type="load"} 1641.0
prometheus_local_storage_chunk_ops_total{type="persist"} 981408.0
prometheus_local_storage_chunk_ops_total{type="pin"} 32662.0
prometheus_local_storage_chunk_ops_total{type="transcode"} 980180.0
prometheus_local_storage_chunk_ops_total{type="unpin"} 32662.0
# EOF
"""
        families = list(text_string_to_metric_families(text))

        class TextCollector(object):
            def collect(self):
                return families

        registry = CollectorRegistry()
        registry.register(TextCollector())
        self.assertEqual(text.encode('utf-8'), generate_latest(registry))
예제 #23
0
    def test_untyped(self):
        # https://github.com/prometheus/client_python/issues/79
        families = text_string_to_metric_families("""# HELP redis_connected_clients Redis connected clients
# TYPE redis_connected_clients unknown
redis_connected_clients{instance="rough-snowflake-web",port="6380"} 10.0
redis_connected_clients{instance="rough-snowflake-web",port="6381"} 12.0
# EOF
""")
        m = Metric("redis_connected_clients", "Redis connected clients", "untyped")
        m.samples = [
            Sample("redis_connected_clients", {"instance": "rough-snowflake-web", "port": "6380"}, 10),
            Sample("redis_connected_clients", {"instance": "rough-snowflake-web", "port": "6381"}, 12),
        ]
        self.assertEqual([m], list(families))
예제 #24
0
    def test_duplicate_timestamps(self):
        families = text_string_to_metric_families("""# TYPE a gauge
# HELP a help
a{a="1",foo="bar"} 1 0.0000000000
a{a="1",foo="bar"} 2 0.0000000001
a{a="1",foo="bar"} 3 0.0000000010
a{a="2",foo="bar"} 4 0.0000000000
a{a="2",foo="bar"} 5 0.0000000001
# EOF
""")
        imf = GaugeMetricFamily("a", "help")
        imf.add_sample("a", {"a": "1", "foo": "bar"}, 1, Timestamp(0, 0))
        imf.add_sample("a", {"a": "1", "foo": "bar"}, 3, Timestamp(0, 1))
        imf.add_sample("a", {"a": "2", "foo": "bar"}, 4, Timestamp(0, 0))
        self.assertEqual([imf], list(families))
예제 #25
0
def parses_as_openmetrics():
    """
    Create a matcher that matches a ``str`` string that can be parsed as an
    OpenMetrics response and includes a certain well-known value expected by
    the tests.

    :return: A matcher.
    """
    # The parser throws if it does not like its input.
    # Wrapped in a list() to drain the generator.
    return AfterPreprocessing(
        lambda body: list(parser.text_string_to_metric_families(body)),
        AfterPreprocessing(
            lambda families: families[-1].name,
            Equals("tahoe_stats_storage_server_total_bucket_count"),
        ),
    )
예제 #26
0
    def test_timestamps(self):
        families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{foo="1"} 1 000
a_total{foo="2"} 1 0.0
a_total{foo="3"} 1 1.1
a_total{foo="4"} 1 12345678901234567890.1234567890
a_total{foo="5"} 1 1.5e3
# TYPE b counter
# HELP b help
b_total 2 1234567890
# EOF
""")
        a = CounterMetricFamily("a", "help", labels=["foo"])
        a.add_metric(["1"], 1, timestamp=Timestamp(0, 0))
        a.add_metric(["2"], 1, timestamp=Timestamp(0, 0))
        a.add_metric(["3"], 1, timestamp=Timestamp(1, 100000000))
        a.add_metric(["4"], 1, timestamp=Timestamp(12345678901234567890, 123456789))
        a.add_metric(["5"], 1, timestamp=1500.0)
        b = CounterMetricFamily("b", "help")
        b.add_metric([], 2, timestamp=Timestamp(1234567890, 0))
        self.assertEqual([a, b], list(families))
예제 #27
0
    def test_fallback_to_state_machine_label_parsing(self):
        from unittest.mock import patch

        from prometheus_client.openmetrics.parser import _parse_sample

        parse_sample_function = "prometheus_client.openmetrics.parser._parse_sample"
        parse_labels_function = "prometheus_client.openmetrics.parser._parse_labels"
        parse_remaining_function = "prometheus_client.openmetrics.parser._parse_remaining_text"
        state_machine_function = "prometheus_client.openmetrics.parser._parse_labels_with_state_machine"

        parse_sample_return_value = Sample("a_total", {"foo": "foo # bar"}, 1)
        with patch(parse_sample_function,
                   return_value=parse_sample_return_value) as mock:
            families = text_string_to_metric_families("""# TYPE a counter
# HELP a help
a_total{foo="foo # bar"} 1
# EOF
""")
            a = CounterMetricFamily("a", "help", labels=["foo"])
            a.add_metric(["foo # bar"], 1)
            self.assertEqual([a], list(families))
            mock.assert_called_once_with('a_total{foo="foo # bar"} 1')

        # First fallback case
        state_machine_return_values = [{
            "foo": "foo # bar"
        }, len('foo="foo # bar"}')]
        parse_remaining_values = [1, None, None]
        with patch(parse_labels_function) as mock1:
            with patch(state_machine_function,
                       return_value=state_machine_return_values) as mock2:
                with patch(parse_remaining_function,
                           return_value=parse_remaining_values) as mock3:
                    sample = _parse_sample('a_total{foo="foo # bar"} 1')
                    s = Sample("a_total", {"foo": "foo # bar"}, 1)
                    self.assertEqual(s, sample)
                    mock1.assert_not_called()
                    mock2.assert_called_once_with('foo="foo # bar"} 1')
                    mock3.assert_called_once_with('1')

        # Second fallback case
        state_machine_return_values = [{"le": "1.0"}, len('le="1.0"}')]
        parse_remaining_values = [
            0.0, Timestamp(123, 0),
            Exemplar({"a": "b"}, 0.5)
        ]
        with patch(parse_labels_function) as mock1:
            with patch(state_machine_function,
                       return_value=state_machine_return_values) as mock2:
                with patch(parse_remaining_function,
                           return_value=parse_remaining_values) as mock3:
                    sample = _parse_sample(
                        'a_bucket{le="1.0"} 0 123 # {a="b"} 0.5')
                    s = Sample("a_bucket", {"le": "1.0"}, 0.0,
                               Timestamp(123, 0), Exemplar({"a": "b"}, 0.5))
                    self.assertEqual(s, sample)
                    mock1.assert_not_called()
                    mock2.assert_called_once_with(
                        'le="1.0"} 0 123 # {a="b"} 0.5')
                    mock3.assert_called_once_with('0 123 # {a="b"} 0.5')

        # No need to fallback case
        parse_labels_return_values = {"foo": "foo#bar"}
        parse_remaining_values = [1, None, None]
        with patch(parse_labels_function,
                   return_value=parse_labels_return_values) as mock1:
            with patch(state_machine_function) as mock2:
                with patch(parse_remaining_function,
                           return_value=parse_remaining_values) as mock3:
                    sample = _parse_sample('a_total{foo="foo#bar"} 1')
                    s = Sample("a_total", {"foo": "foo#bar"}, 1)
                    self.assertEqual(s, sample)
                    mock1.assert_called_once_with('foo="foo#bar"')
                    mock2.assert_not_called()
                    mock3.assert_called_once_with('1')
예제 #28
0
    def test_no_newline_after_eof(self):
        families = text_string_to_metric_families("""# TYPE a gauge
# HELP a help
a 1
# EOF""")
        self.assertEqual([GaugeMetricFamily("a", "help", value=1)], list(families))
예제 #29
0
    def test_nan(self):
        families = text_string_to_metric_families("""a NaN
# EOF
""")
        self.assertTrue(math.isnan(list(families)[0].samples[0][2]))
예제 #30
0
import sys
from prometheus_client.openmetrics.parser import text_string_to_metric_families

input = sys.stdin.read()
families = text_string_to_metric_families(input)
print(list(families))