async def fetch_metrics(
    url: str, fmt: str = None, interval: float = 1.0, loop: BaseEventLoop = None
):
    """ Fetch metrics from the service endpoint using different formats.

    This coroutine runs 'n' times, with a brief interval in between, before
    exiting.
    """
    if fmt is None:
        # Randomly choose a format to request metrics in.
        choice = random.choice((TEXT, BINARY))
    else:
        assert fmt in header_kinds
        choice = fmt

    print(f"fetching metrics in {choice} format")
    async with aiohttp.ClientSession() as session:
        async with session.get(url, headers={ACCEPT: header_kinds[choice]}) as resp:
            assert resp.status == 200
            content = await resp.read()
            content_type = resp.headers.get(CONTENT_TYPE)
            print("Content-Type: {}".format(content_type))
            print("size: {}".format(len(content)))
            if choice == "text":
                print(content.decode())
            else:
                print(content)
                # Decode the binary metrics into protobuf objects
                print(prometheus_metrics_proto.decode(content))

    # schedule another fetch
    loop.call_later(interval, fetch_task, url, fmt, interval, loop)
Beispiel #2
0
    async def test_counter(self):
        """ check counter metric export """

        # Add some metrics
        data = (
            ({
                "data": 1
            }, 100),
            ({
                "data": "2"
            }, 200),
            ({
                "data": 3
            }, 300),
            ({
                "data": 1
            }, 400),
        )
        c = Counter("test_counter", "Test Counter.", {"test": "test_counter"})
        self.server.register(c)

        for i in data:
            c.set(i[0], i[1])

        expected_data = """# HELP test_counter Test Counter.
# TYPE test_counter counter
test_counter{data="1",test="test_counter"} 400
test_counter{data="2",test="test_counter"} 200
test_counter{data="3",test="test_counter"} 300
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(self.metrics_url,
                                   headers={ACCEPT:
                                            text.TEXT_CONTENT_TYPE}) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(text.TEXT_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(self.metrics_url,
                                   headers={
                                       ACCEPT: binary.BINARY_CONTENT_TYPE
                                   }) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(binary.BINARY_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 1)
                mf = metrics[0]
                self.assertIsInstance(mf, pmp.MetricFamily)
                self.assertEqual(mf.type, pmp.COUNTER)
                self.assertEqual(len(mf.metric), 3)
Beispiel #3
0
    async def test_histogram(self):
        """ check histogram metric export """

        # Add some metrics
        data = [3, 5.2, 13, 4]
        label = {"data": 1}

        h = Histogram(
            "histogram_test",
            "Test Histogram.",
            {"type": "test_histogram"},
            buckets=[5.0, 10.0, 15.0],
        )
        self.server.register(h)

        for i in data:
            h.add(label, i)

        expected_data = """# HELP histogram_test Test Histogram.
# TYPE histogram_test histogram
histogram_test_bucket{data="1",le="5.0",type="test_histogram"} 2.0
histogram_test_bucket{data="1",le="10.0",type="test_histogram"} 3.0
histogram_test_bucket{data="1",le="15.0",type="test_histogram"} 4.0
histogram_test_bucket{data="1",le="+Inf",type="test_histogram"} 4.0
histogram_test_count{data="1",type="test_histogram"} 4.0
histogram_test_sum{data="1",type="test_histogram"} 25.2
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(self.metrics_url,
                                   headers={ACCEPT:
                                            text.TEXT_CONTENT_TYPE}) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(text.TEXT_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(self.metrics_url,
                                   headers={
                                       ACCEPT: binary.BINARY_CONTENT_TYPE
                                   }) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(binary.BINARY_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 1)
                mf = metrics[0]
                self.assertIsInstance(mf, pmp.MetricFamily)
                self.assertEqual(mf.type, pmp.HISTOGRAM)
                self.assertEqual(len(mf.metric), 1)
                self.assertEqual(len(mf.metric[0].histogram.bucket), 4)
Beispiel #4
0
    async def test_histogram(self):
        """ check histogram metric export """

        # Add some metrics
        data = [3, 5.2, 13, 4]
        label = {"data": 1}

        h = Histogram(
            "histogram_test",
            "Test Histogram.",
            {"type": "test_histogram"},
            buckets=[5.0, 10.0, 15.0],
        )
        self.server.register(h)

        for i in data:
            h.add(label, i)

        expected_data = """# HELP histogram_test Test Histogram.
# TYPE histogram_test histogram
histogram_test_bucket{data="1",le="5.0",type="test_histogram"} 2.0
histogram_test_bucket{data="1",le="10.0",type="test_histogram"} 3.0
histogram_test_bucket{data="1",le="15.0",type="test_histogram"} 4.0
histogram_test_bucket{data="1",le="+Inf",type="test_histogram"} 4.0
histogram_test_count{data="1",type="test_histogram"} 4.0
histogram_test_sum{data="1",type="test_histogram"} 25.2
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(
                self.metrics_url, headers={ACCEPT: TEXT_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(TEXT_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(
                self.metrics_url, headers={ACCEPT: BINARY_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(BINARY_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 1)
                mf = metrics[0]
                self.assertIsInstance(mf, pmp.MetricFamily)
                self.assertEqual(mf.type, pmp.HISTOGRAM)
                self.assertEqual(len(mf.metric), 1)
                self.assertEqual(len(mf.metric[0].histogram.bucket), 4)
Beispiel #5
0
    async def test_summary(self):
        """ check summary metric export """

        # Add some metrics
        data = [3, 5.2, 13, 4]
        label = {"data": 1}

        s = Summary("test_summary", "Test Summary.", {"test": "test_summary"})
        self.server.register(s)

        for i in data:
            s.add(label, i)

        expected_data = """# HELP test_summary Test Summary.
# TYPE test_summary summary
test_summary{data="1",quantile="0.5",test="test_summary"} 4.0
test_summary{data="1",quantile="0.9",test="test_summary"} 5.2
test_summary{data="1",quantile="0.99",test="test_summary"} 5.2
test_summary_count{data="1",test="test_summary"} 4
test_summary_sum{data="1",test="test_summary"} 25.2
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(self.metrics_url,
                                   headers={ACCEPT:
                                            text.TEXT_CONTENT_TYPE}) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(text.TEXT_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(self.metrics_url,
                                   headers={
                                       ACCEPT: binary.BINARY_CONTENT_TYPE
                                   }) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(binary.BINARY_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 1)
                mf = metrics[0]
                self.assertIsInstance(mf, pmp.MetricFamily)
                self.assertEqual(mf.type, pmp.SUMMARY)
                self.assertEqual(len(mf.metric), 1)
                self.assertEqual(len(mf.metric[0].summary.quantile), 3)
Beispiel #6
0
    async def test_summary(self):
        """ check summary metric export """

        # Add some metrics
        data = [3, 5.2, 13, 4]
        label = {"data": 1}

        s = Summary("test_summary", "Test Summary.", {"test": "test_summary"})
        self.server.register(s)

        for i in data:
            s.add(label, i)

        expected_data = """# HELP test_summary Test Summary.
# TYPE test_summary summary
test_summary{data="1",quantile="0.5",test="test_summary"} 4.0
test_summary{data="1",quantile="0.9",test="test_summary"} 5.2
test_summary{data="1",quantile="0.99",test="test_summary"} 5.2
test_summary_count{data="1",test="test_summary"} 4
test_summary_sum{data="1",test="test_summary"} 25.2
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(
                self.metrics_url, headers={ACCEPT: TEXT_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(TEXT_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(
                self.metrics_url, headers={ACCEPT: BINARY_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(BINARY_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 1)
                mf = metrics[0]
                self.assertIsInstance(mf, pmp.MetricFamily)
                self.assertEqual(mf.type, pmp.SUMMARY)
                self.assertEqual(len(mf.metric), 1)
                self.assertEqual(len(mf.metric[0].summary.quantile), 3)
Beispiel #7
0
    async def test_gauge(self):
        """ check gauge metric export """

        # Add some metrics
        data = (
            ({"data": 1}, 100),
            ({"data": "2"}, 200),
            ({"data": 3}, 300),
            ({"data": 1}, 400),
        )
        g = Gauge("test_gauge", "Test Gauge.", {"test": "test_gauge"})
        self.server.register(g)

        for i in data:
            g.set(i[0], i[1])

        expected_data = """# HELP test_gauge Test Gauge.
# TYPE test_gauge gauge
test_gauge{data="1",test="test_gauge"} 400
test_gauge{data="2",test="test_gauge"} 200
test_gauge{data="3",test="test_gauge"} 300
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(
                self.metrics_url, headers={ACCEPT: TEXT_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(TEXT_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(
                self.metrics_url, headers={ACCEPT: BINARY_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(BINARY_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 1)
                mf = metrics[0]
                self.assertIsInstance(mf, pmp.MetricFamily)
                self.assertEqual(mf.type, pmp.GAUGE)
                self.assertEqual(len(mf.metric), 3)
Beispiel #8
0
    def test_encode_histogram(self):
        """ check encode of histogram matches expected output """
        valid_result = (b"\x97\x01\n\x0ehistogram_test\x12\x0cA histogram."
                        b'\x18\x04"u\n\r\n\x08h_sample\x12\x011\n\x10\n'
                        b"\x0bh_subsample\x12\x01b\n\x11\n\x04type\x12\t"
                        b"histogram:?\x08\x06\x11\x00\x00\x00\x00\x00\x00G@"
                        b"\x1a\x0b\x08\x03\x11\x00\x00\x00\x00\x00\x00\x14@"
                        b"\x1a\x0b\x08\x02\x11\x00\x00\x00\x00\x00\x00$@\x1a"
                        b"\x0b\x08\x01\x11\x00\x00\x00\x00\x00\x00.@\x1a\x0b"
                        b"\x08\x00\x11\x00\x00\x00\x00\x00\x00\xf0\x7f")
        metric_name = "histogram_test"
        metric_help = "A histogram."
        metric_type = pmp.HISTOGRAM
        # buckets typically have a POS_INF upper bound to catch values
        # beyond the largest bucket bound. Simulate this behavior.
        POS_INF = float("inf")
        metric_data = ((
            {
                "h_sample": "1",
                "h_subsample": "b"
            },
            {
                5.0: 3,
                10.0: 2,
                15.0: 1,
                POS_INF: 0,
                "count": 6,
                "sum": 46.0
            },
        ), )
        mf = pmp.utils.create_metric_family(
            metric_name,
            metric_help,
            metric_type,
            metric_data,
            const_labels={"type": "histogram"},
        )
        payload = pmp.encode(mf)
        self.assertIsInstance(payload, bytes)
        self.assertEqual(valid_result, payload)

        # Check Histogram can be round-tripped through encode and decode
        _mf = pmp.decode(payload)[0]
        self.assertEqual(mf, _mf)
Beispiel #9
0
    def test_encode_summary(self):
        """ check encode of summary matches expected output """
        valid_result = (b"\x99\x01\n\x0csummary_test\x12\nA summary."
                        b'\x18\x02"{\n\r\n\x08s_sample\x12\x011\n\x10\n'
                        b"\x0bs_subsample\x12\x01b\n\x0f\n\x04type\x12\x07"
                        b'summary"G\x08\x16\x11\x00\x00\x00\x00\x90"\xf8@'
                        b"\x1a\x12\t\x00\x00\x00\x00\x00\x00\xe0?\x11\x00"
                        b"\x00\x00\x00\x00\x8b\xb0@\x1a\x12\t\xcd\xcc\xcc"
                        b"\xcc\xcc\xcc\xec?\x11\x00\x00\x00\x00\x00v\xb1@"
                        b"\x1a\x12\t\xaeG\xe1z\x14\xae\xef?\x11\x00\x00\x00"
                        b"\x00\x00\xa5\xb1@")
        metric_name = "summary_test"
        metric_help = "A summary."
        metric_type = pmp.SUMMARY
        metric_data = ((
            {
                "s_sample": "1",
                "s_subsample": "b"
            },
            {
                0.5: 4235.0,
                0.9: 4470.0,
                0.99: 4517.0,
                "count": 22,
                "sum": 98857.0
            },
        ), )
        mf = pmp.utils.create_metric_family(
            metric_name,
            metric_help,
            metric_type,
            metric_data,
            const_labels={"type": "summary"},
        )
        payload = pmp.encode(mf)
        self.assertIsInstance(payload, bytes)
        self.assertEqual(valid_result, payload)

        # Check Summary can be round-tripped through encode and decode
        _mf = pmp.decode(payload)[0]
        self.assertEqual(mf, _mf)
    def test_encode_gauge(self):
        ''' check encode of gauge matches expected output '''
        valid_result = (b'U\n\ngauge_test\x12\x08A gauge.\x18\x01";'
                        b'\n\r\n\x08g_sample\x12\x011\n\x10\n\x0bg_subsample'
                        b'\x12\x01b\n\r\n\x04type\x12\x05gauge\x12\t\t\x00'
                        b'\x00\x00\x00\x00\x00\x89@')
        metric_name = "gauge_test"
        metric_help = "A gauge."
        metric_type = pmp.GAUGE
        metric_data = (({'g_sample': '1', 'g_subsample': 'b'}, 800), )
        mf = pmp.utils.create_metric_family(metric_name,
                                            metric_help,
                                            metric_type,
                                            metric_data,
                                            const_labels={'type': "gauge"})
        payload = pmp.encode(mf)
        self.assertIsInstance(payload, bytes)
        self.assertEqual(valid_result, payload)

        # Check Gauge can be round-tripped through encode and decode
        _mf = pmp.decode(payload)[0]
        self.assertEqual(mf, _mf)
    def test_encode_counter(self):
        ''' check encode of counter matches expected output '''
        valid_result = (b'[\n\x0ccounter_test\x12\nA counter.\x18\x00"=\n\r'
                        b'\n\x08c_sample\x12\x011\n\x10\n\x0bc_subsample\x12'
                        b'\x01b\n\x0f\n\x04type\x12\x07counter\x1a\t\t\x00\x00'
                        b'\x00\x00\x00\x00y@')
        metric_name = "counter_test"
        metric_help = "A counter."
        metric_type = pmp.COUNTER
        metric_data = (({'c_sample': '1', 'c_subsample': 'b'}, 400), )
        mf = pmp.utils.create_metric_family(metric_name,
                                            metric_help,
                                            metric_type,
                                            metric_data,
                                            const_labels={'type': "counter"})
        payload = pmp.encode(mf)
        self.assertIsInstance(payload, bytes)
        self.assertEqual(valid_result, payload)

        # Check Counter can be round-tripped through encode and decode
        _mf = pmp.decode(payload)[0]
        self.assertEqual(mf, _mf)
Beispiel #12
0
    def test_histogram(self):
        ''' check creating histogram using utils functions '''
        # Create a metrics with no metric instances
        mf = pmp.utils.create_metric_family(self.histogram_metric_name,
                                            self.histogram_metric_help,
                                            self.histogram_metric_type, [])
        self.assertIsInstance(mf, pmp.MetricFamily)
        self.assertEqual(len(mf.metric), 0)

        # Create it with metrics
        mf = pmp.utils.create_metric_family(self.histogram_metric_name,
                                            self.histogram_metric_help,
                                            self.histogram_metric_type,
                                            self.histogram_metric_data)
        self.assertIsInstance(mf, pmp.MetricFamily)
        self.assertEqual(mf.name, self.histogram_metric_name)
        self.assertEqual(mf.help, self.histogram_metric_help)
        self.assertEqual(mf.type, self.histogram_metric_type)

        # Create another and check equal
        mf_ = pmp.utils.create_metric_family(self.histogram_metric_name,
                                             self.histogram_metric_help,
                                             self.histogram_metric_type,
                                             self.histogram_metric_data)
        self.assertIsInstance(mf_, pmp.MetricFamily)

        self.assertEqual(mf, mf_)

        for m in mf_.metric:
            self.assertEqual(m.timestamp_ms, 0)

        # Create another with timestamp
        mf_ = pmp.create_histogram(self.histogram_metric_name,
                                   self.histogram_metric_help,
                                   self.histogram_metric_data,
                                   timestamp=True)
        self.assertIsInstance(mf_, pmp.MetricFamily)

        for m in mf_.metric:
            self.assertNotEqual(m.timestamp_ms, 0)

        self.assertNotEqual(mf, mf_)

        # Create Histogram with const_labels
        mf_ = pmp.utils.create_metric_family(self.histogram_metric_name,
                                             self.histogram_metric_help,
                                             self.histogram_metric_type,
                                             self.histogram_metric_data,
                                             const_labels=self.const_labels)
        self.assertIsInstance(mf_, pmp.MetricFamily)

        # Check that const_label is present in the LabelPair associated
        # with each metric instance.
        for m in mf_.metric:
            labels = [lp.name for lp in m.label]
            self.assertIn('app', labels)

        self.assertNotEqual(mf, mf_)

        # Check Histogram can be round-tripped through encode and decode
        payload = pmp.encode(mf)
        self.assertIsInstance(payload, bytes)
        _mf = pmp.decode(payload)[0]
        self.assertEqual(mf, _mf)
Beispiel #13
0
def main():

    # Define some labels that we want added to all metrics. These labels are
    # independent of the instance labels that define a metric as unique.
    # These could be used to add hostname, app name, etc.
    const_labels = {'host': 'examplehost', 'app': 'my_app'}

    # Create a Counter metric to track logged in users. This counter has
    # 5 separate instances.
    # We'll make use of the optional const_labels argument to add extra
    # constant labels.
    # We will also add a timestamp to the metric instances.
    # We will request that the labels be sorted.
    cm = pmp.create_counter('logged_users_total',
                            'Logged users in the application.', (
                                ({
                                    'country': "sp",
                                    "device": "desktop"
                                }, 520),
                                ({
                                    'country': "us",
                                    "device": "mobile"
                                }, 654),
                                ({
                                    'country': "uk",
                                    "device": "desktop"
                                }, 1001),
                                ({
                                    'country': "de",
                                    "device": "desktop"
                                }, 995),
                                ({
                                    'country': "zh",
                                    "device": "desktop"
                                }, 520),
                            ),
                            timestamp=True,
                            const_labels=const_labels,
                            ordered=True)

    # Create a Gauge metric, similar to the counter above.
    gm = pmp.create_gauge('logged_users_total',
                          'Logged users in the application.', (
                              ({
                                  'country': "sp",
                                  "device": "desktop"
                              }, 520),
                              ({
                                  'country': "us",
                                  "device": "mobile"
                              }, 654),
                              ({
                                  'country': "uk",
                                  "device": "desktop"
                              }, 1001),
                              ({
                                  'country': "de",
                                  "device": "desktop"
                              }, 995),
                              ({
                                  'country': "zh",
                                  "device": "desktop"
                              }, 520),
                          ),
                          timestamp=True,
                          const_labels=const_labels,
                          ordered=True)

    # Now lets create a Summary and Histogram metric object. These forms
    # of metrics are slightly more complicated.
    #
    # Remember, the collection of metrics and the management of Summary
    # Quantiles and Histogram Buckets are outside the scope of
    # functionality provided by this package.
    #
    # The following examples assume they are taking the data values from
    # a management library that can also emit the sum and count fields
    # expected for both Summary and Histogram metrics.

    # Create a Summary metric. The values for a summary are slightly
    # different to a Counter or Gauge. They are composed of a dict representing
    # the various quantile values of the metric. The count and sum are
    # expected to be present in this dict.
    sm = pmp.create_summary('request_payload_size_bytes',
                            'Request payload size in bytes.', (
                                ({
                                    'route': '/'
                                }, {
                                    0.5: 4.0,
                                    0.9: 5.2,
                                    0.99: 5.2,
                                    'sum': 25.2,
                                    'count': 4
                                }),
                                ({
                                    'route': '/data'
                                }, {
                                    0.5: 4.0,
                                    0.9: 5.2,
                                    0.99: 5.2,
                                    'sum': 25.2,
                                    'count': 4
                                }),
                            ),
                            timestamp=True,
                            const_labels=const_labels,
                            ordered=True)

    # Create a Histogram metric. The values for a histogram are slightly
    # different to a Counter or Gauge. They are composed of a dict representing
    # the various bucket values of the metric. The cumulative count and sum
    # values are expected to be present in this dict.
    #
    # Libraries manageing buckets typically have add a POS_INF upper bound to
    # catch values beyond the largest bucket bound. Simulate this behavior in
    # the data below.
    POS_INF = float("inf")

    hm = pmp.create_histogram('request_latency_seconds',
                              'Request latency in seconds.', (
                                  ({
                                      'route': '/'
                                  }, {
                                      5.0: 3,
                                      10.0: 2,
                                      15.0: 1,
                                      POS_INF: 0,
                                      'count': 6,
                                      'sum': 46.0
                                  }),
                                  ({
                                      'route': '/data'
                                  }, {
                                      5.0: 3,
                                      10.0: 2,
                                      15.0: 1,
                                      POS_INF: 0,
                                      'count': 6,
                                      'sum': 46.0
                                  }),
                              ),
                              timestamp=True,
                              const_labels=const_labels,
                              ordered=True)

    # Serialize a sequence of metrics into a payload suitable for network
    # transmission.
    input_metrics = (cm, gm, sm, hm)
    payload = pmp.encode(*input_metrics)
    assert isinstance(payload, bytes)

    # De-serialize the payload into a sequence of MetricsFamily objects.
    recovered_metrics = pmp.decode(payload)

    # Confirm that the round trip re-produced the same number of metrics
    # and that the metrics are identical.
    assert len(recovered_metrics) == len(input_metrics)
    for recovered_metric, input_metric in zip(recovered_metrics,
                                              input_metrics):
        assert recovered_metric == input_metric

    for metric in input_metrics:
        print(metric)
    def test_encode_decode(self):
        ''' check encode and decode functions '''

        # check passing no metrics raises an exception
        input_metrics = None
        with self.assertRaises(Exception) as ctx:
            payload = pmp.encode(input_metrics)
        self.assertIn('Expected metrics to be instances of MetricFamily, got ',
                      str(ctx.exception))

        cm = pmp.create_counter(self.counter_metric_name,
                                self.counter_metric_help,
                                self.counter_metric_data)
        self.assertIsInstance(cm, pmp.MetricFamily)

        gm = pmp.create_gauge(self.gauge_metric_name, self.gauge_metric_help,
                              self.gauge_metric_data)
        self.assertIsInstance(gm, pmp.MetricFamily)

        sm = pmp.create_summary(self.summary_metric_name,
                                self.summary_metric_help,
                                self.summary_metric_data)
        self.assertIsInstance(sm, pmp.MetricFamily)

        hm = pmp.create_histogram(self.histogram_metric_name,
                                  self.histogram_metric_help,
                                  self.histogram_metric_data)
        self.assertIsInstance(hm, pmp.MetricFamily)

        # check encode can take a single valid metric
        input_metrics = [cm]
        payload = pmp.encode(input_metrics[0])
        self.assertIsInstance(payload, bytes)
        # check round-trip
        metrics = pmp.decode(payload)
        self.assertIsInstance(metrics, list)
        self.assertEqual(len(metrics), len(input_metrics))
        for m_in, m_out in zip(input_metrics, metrics):
            self.assertEqual(m_in, m_out)

        # check passing invalid type raises an exception
        input_metrics = ['a']
        with self.assertRaises(Exception) as ctx:
            payload = pmp.encode(*input_metrics)
        self.assertIn('Expected metrics to be instances of MetricFamily, got ',
                      str(ctx.exception))

        # check parser can take multiple valid metrics
        input_metrics = (cm, gm, sm, hm)
        payload = pmp.encode(*input_metrics)
        self.assertIsInstance(payload, bytes)
        # check round-trip
        metrics = pmp.decode(payload)
        self.assertIsInstance(metrics, list)
        self.assertEqual(len(metrics), len(input_metrics))
        for m_in, m_out in zip(input_metrics, metrics):
            self.assertEqual(m_in, m_out)

        # check decoding empty bytes returns empty list
        metrics = pmp.decode(b'')
        self.assertIsInstance(metrics, list)
        self.assertEqual(len(metrics), 0)
Beispiel #15
0
    async def test_all(self):

        counter_data = (
            ({"c_sample": "1"}, 100),
            ({"c_sample": "2"}, 200),
            ({"c_sample": "3"}, 300),
            ({"c_sample": "1", "c_subsample": "b"}, 400),
        )

        gauge_data = (
            ({"g_sample": "1"}, 500),
            ({"g_sample": "2"}, 600),
            ({"g_sample": "3"}, 700),
            ({"g_sample": "1", "g_subsample": "b"}, 800),
        )

        summary_data = (
            ({"s_sample": "1"}, range(1000, 2000, 4)),
            ({"s_sample": "2"}, range(2000, 3000, 20)),
            ({"s_sample": "3"}, range(3000, 4000, 13)),
            ({"s_sample": "1", "s_subsample": "b"}, range(4000, 5000, 47)),
        )

        histogram_data = (
            ({"h_sample": "1"}, [3, 14]),
            ({"h_sample": "2"}, range(1, 20, 2)),
            ({"h_sample": "3"}, range(1, 20, 2)),
            ({"h_sample": "1", "h_subsample": "b"}, range(1, 20, 2)),
        )

        counter = Counter("counter_test", "A counter.", {"type": "counter"})
        gauge = Gauge("gauge_test", "A gauge.", {"type": "gauge"})
        summary = Summary("summary_test", "A summary.", {"type": "summary"})
        histogram = Histogram(
            "histogram_test",
            "A histogram.",
            {"type": "histogram"},
            buckets=[5.0, 10.0, 15.0],
        )

        self.server.register(counter)
        self.server.register(gauge)
        self.server.register(summary)
        self.server.register(histogram)

        # Add data
        [counter.set(c[0], c[1]) for c in counter_data]
        [gauge.set(g[0], g[1]) for g in gauge_data]
        [summary.add(i[0], s) for i in summary_data for s in i[1]]
        [histogram.observe(i[0], h) for i in histogram_data for h in i[1]]

        expected_data = """# HELP counter_test A counter.
# TYPE counter_test counter
counter_test{c_sample="1",type="counter"} 100
counter_test{c_sample="2",type="counter"} 200
counter_test{c_sample="3",type="counter"} 300
counter_test{c_sample="1",c_subsample="b",type="counter"} 400
# HELP gauge_test A gauge.
# TYPE gauge_test gauge
gauge_test{g_sample="1",type="gauge"} 500
gauge_test{g_sample="2",type="gauge"} 600
gauge_test{g_sample="3",type="gauge"} 700
gauge_test{g_sample="1",g_subsample="b",type="gauge"} 800
# HELP histogram_test A histogram.
# TYPE histogram_test histogram
histogram_test_bucket{h_sample="1",le="5.0",type="histogram"} 1.0
histogram_test_bucket{h_sample="1",le="10.0",type="histogram"} 1.0
histogram_test_bucket{h_sample="1",le="15.0",type="histogram"} 2.0
histogram_test_bucket{h_sample="1",le="+Inf",type="histogram"} 2.0
histogram_test_count{h_sample="1",type="histogram"} 2.0
histogram_test_sum{h_sample="1",type="histogram"} 17.0
histogram_test_bucket{h_sample="2",le="5.0",type="histogram"} 3.0
histogram_test_bucket{h_sample="2",le="10.0",type="histogram"} 5.0
histogram_test_bucket{h_sample="2",le="15.0",type="histogram"} 8.0
histogram_test_bucket{h_sample="2",le="+Inf",type="histogram"} 10.0
histogram_test_count{h_sample="2",type="histogram"} 10.0
histogram_test_sum{h_sample="2",type="histogram"} 100.0
histogram_test_bucket{h_sample="3",le="5.0",type="histogram"} 3.0
histogram_test_bucket{h_sample="3",le="10.0",type="histogram"} 5.0
histogram_test_bucket{h_sample="3",le="15.0",type="histogram"} 8.0
histogram_test_bucket{h_sample="3",le="+Inf",type="histogram"} 10.0
histogram_test_count{h_sample="3",type="histogram"} 10.0
histogram_test_sum{h_sample="3",type="histogram"} 100.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="5.0",type="histogram"} 3.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="10.0",type="histogram"} 5.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="15.0",type="histogram"} 8.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="+Inf",type="histogram"} 10.0
histogram_test_count{h_sample="1",h_subsample="b",type="histogram"} 10.0
histogram_test_sum{h_sample="1",h_subsample="b",type="histogram"} 100.0
# HELP summary_test A summary.
# TYPE summary_test summary
summary_test{quantile="0.5",s_sample="1",type="summary"} 1272.0
summary_test{quantile="0.9",s_sample="1",type="summary"} 1452.0
summary_test{quantile="0.99",s_sample="1",type="summary"} 1496.0
summary_test_count{s_sample="1",type="summary"} 250
summary_test_sum{s_sample="1",type="summary"} 374500.0
summary_test{quantile="0.5",s_sample="2",type="summary"} 2260.0
summary_test{quantile="0.9",s_sample="2",type="summary"} 2440.0
summary_test{quantile="0.99",s_sample="2",type="summary"} 2500.0
summary_test_count{s_sample="2",type="summary"} 50
summary_test_sum{s_sample="2",type="summary"} 124500.0
summary_test{quantile="0.5",s_sample="3",type="summary"} 3260.0
summary_test{quantile="0.9",s_sample="3",type="summary"} 3442.0
summary_test{quantile="0.99",s_sample="3",type="summary"} 3494.0
summary_test_count{s_sample="3",type="summary"} 77
summary_test_sum{s_sample="3",type="summary"} 269038.0
summary_test{quantile="0.5",s_sample="1",s_subsample="b",type="summary"} 4235.0
summary_test{quantile="0.9",s_sample="1",s_subsample="b",type="summary"} 4470.0
summary_test{quantile="0.99",s_sample="1",s_subsample="b",type="summary"} 4517.0
summary_test_count{s_sample="1",s_subsample="b",type="summary"} 22
summary_test_sum{s_sample="1",s_subsample="b",type="summary"} 98857.0
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(
                self.metrics_url, headers={ACCEPT: TEXT_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(TEXT_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(
                self.metrics_url, headers={ACCEPT: BINARY_CONTENT_TYPE}
            ) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(BINARY_CONTENT_TYPE, resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 4)
                for mf in metrics:
                    self.assertIsInstance(mf, pmp.MetricFamily)
                    if mf.type == pmp.COUNTER:
                        self.assertEqual(len(mf.metric), 4)
                    elif mf.type == pmp.GAUGE:
                        self.assertEqual(len(mf.metric), 4)
                    elif mf.type == pmp.SUMMARY:
                        self.assertEqual(len(mf.metric), 4)
                        self.assertEqual(len(mf.metric[0].summary.quantile), 3)
                    elif mf.type == pmp.HISTOGRAM:
                        self.assertEqual(len(mf.metric), 4)
                        self.assertEqual(len(mf.metric[0].histogram.bucket), 4)
Beispiel #16
0
    async def test_all(self):

        counter_data = (
            ({
                "c_sample": "1"
            }, 100),
            ({
                "c_sample": "2"
            }, 200),
            ({
                "c_sample": "3"
            }, 300),
            ({
                "c_sample": "1",
                "c_subsample": "b"
            }, 400),
        )

        gauge_data = (
            ({
                "g_sample": "1"
            }, 500),
            ({
                "g_sample": "2"
            }, 600),
            ({
                "g_sample": "3"
            }, 700),
            ({
                "g_sample": "1",
                "g_subsample": "b"
            }, 800),
        )

        summary_data = (
            ({
                "s_sample": "1"
            }, range(1000, 2000, 4)),
            ({
                "s_sample": "2"
            }, range(2000, 3000, 20)),
            ({
                "s_sample": "3"
            }, range(3000, 4000, 13)),
            ({
                "s_sample": "1",
                "s_subsample": "b"
            }, range(4000, 5000, 47)),
        )

        histogram_data = (
            ({
                "h_sample": "1"
            }, [3, 14]),
            ({
                "h_sample": "2"
            }, range(1, 20, 2)),
            ({
                "h_sample": "3"
            }, range(1, 20, 2)),
            ({
                "h_sample": "1",
                "h_subsample": "b"
            }, range(1, 20, 2)),
        )

        counter = Counter("counter_test", "A counter.", {"type": "counter"})
        gauge = Gauge("gauge_test", "A gauge.", {"type": "gauge"})
        summary = Summary("summary_test", "A summary.", {"type": "summary"})
        histogram = Histogram(
            "histogram_test",
            "A histogram.",
            {"type": "histogram"},
            buckets=[5.0, 10.0, 15.0],
        )

        self.server.register(counter)
        self.server.register(gauge)
        self.server.register(summary)
        self.server.register(histogram)

        # Add data
        [counter.set(c[0], c[1]) for c in counter_data]
        [gauge.set(g[0], g[1]) for g in gauge_data]
        [summary.add(i[0], s) for i in summary_data for s in i[1]]
        [histogram.observe(i[0], h) for i in histogram_data for h in i[1]]

        expected_data = """# HELP counter_test A counter.
# TYPE counter_test counter
counter_test{c_sample="1",type="counter"} 100
counter_test{c_sample="2",type="counter"} 200
counter_test{c_sample="3",type="counter"} 300
counter_test{c_sample="1",c_subsample="b",type="counter"} 400
# HELP gauge_test A gauge.
# TYPE gauge_test gauge
gauge_test{g_sample="1",type="gauge"} 500
gauge_test{g_sample="2",type="gauge"} 600
gauge_test{g_sample="3",type="gauge"} 700
gauge_test{g_sample="1",g_subsample="b",type="gauge"} 800
# HELP histogram_test A histogram.
# TYPE histogram_test histogram
histogram_test_bucket{h_sample="1",le="5.0",type="histogram"} 1.0
histogram_test_bucket{h_sample="1",le="10.0",type="histogram"} 1.0
histogram_test_bucket{h_sample="1",le="15.0",type="histogram"} 2.0
histogram_test_bucket{h_sample="1",le="+Inf",type="histogram"} 2.0
histogram_test_count{h_sample="1",type="histogram"} 2.0
histogram_test_sum{h_sample="1",type="histogram"} 17.0
histogram_test_bucket{h_sample="2",le="5.0",type="histogram"} 3.0
histogram_test_bucket{h_sample="2",le="10.0",type="histogram"} 5.0
histogram_test_bucket{h_sample="2",le="15.0",type="histogram"} 8.0
histogram_test_bucket{h_sample="2",le="+Inf",type="histogram"} 10.0
histogram_test_count{h_sample="2",type="histogram"} 10.0
histogram_test_sum{h_sample="2",type="histogram"} 100.0
histogram_test_bucket{h_sample="3",le="5.0",type="histogram"} 3.0
histogram_test_bucket{h_sample="3",le="10.0",type="histogram"} 5.0
histogram_test_bucket{h_sample="3",le="15.0",type="histogram"} 8.0
histogram_test_bucket{h_sample="3",le="+Inf",type="histogram"} 10.0
histogram_test_count{h_sample="3",type="histogram"} 10.0
histogram_test_sum{h_sample="3",type="histogram"} 100.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="5.0",type="histogram"} 3.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="10.0",type="histogram"} 5.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="15.0",type="histogram"} 8.0
histogram_test_bucket{h_sample="1",h_subsample="b",le="+Inf",type="histogram"} 10.0
histogram_test_count{h_sample="1",h_subsample="b",type="histogram"} 10.0
histogram_test_sum{h_sample="1",h_subsample="b",type="histogram"} 100.0
# HELP summary_test A summary.
# TYPE summary_test summary
summary_test{quantile="0.5",s_sample="1",type="summary"} 1272.0
summary_test{quantile="0.9",s_sample="1",type="summary"} 1452.0
summary_test{quantile="0.99",s_sample="1",type="summary"} 1496.0
summary_test_count{s_sample="1",type="summary"} 250
summary_test_sum{s_sample="1",type="summary"} 374500.0
summary_test{quantile="0.5",s_sample="2",type="summary"} 2260.0
summary_test{quantile="0.9",s_sample="2",type="summary"} 2440.0
summary_test{quantile="0.99",s_sample="2",type="summary"} 2500.0
summary_test_count{s_sample="2",type="summary"} 50
summary_test_sum{s_sample="2",type="summary"} 124500.0
summary_test{quantile="0.5",s_sample="3",type="summary"} 3260.0
summary_test{quantile="0.9",s_sample="3",type="summary"} 3442.0
summary_test{quantile="0.99",s_sample="3",type="summary"} 3494.0
summary_test_count{s_sample="3",type="summary"} 77
summary_test_sum{s_sample="3",type="summary"} 269038.0
summary_test{quantile="0.5",s_sample="1",s_subsample="b",type="summary"} 4235.0
summary_test{quantile="0.9",s_sample="1",s_subsample="b",type="summary"} 4470.0
summary_test{quantile="0.99",s_sample="1",s_subsample="b",type="summary"} 4517.0
summary_test_count{s_sample="1",s_subsample="b",type="summary"} 22
summary_test_sum{s_sample="1",s_subsample="b",type="summary"} 98857.0
"""

        async with aiohttp.ClientSession() as session:

            # Fetch as text
            async with session.get(self.metrics_url,
                                   headers={ACCEPT:
                                            text.TEXT_CONTENT_TYPE}) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(text.TEXT_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                self.assertEqual(expected_data, content.decode())

            # Fetch as binary
            async with session.get(self.metrics_url,
                                   headers={
                                       ACCEPT: binary.BINARY_CONTENT_TYPE
                                   }) as resp:
                self.assertEqual(resp.status, 200)
                content = await resp.read()
                self.assertEqual(binary.BINARY_CONTENT_TYPE,
                                 resp.headers.get(CONTENT_TYPE))
                metrics = pmp.decode(content)
                self.assertEqual(len(metrics), 4)
                for mf in metrics:
                    self.assertIsInstance(mf, pmp.MetricFamily)
                    if mf.type == pmp.COUNTER:
                        self.assertEqual(len(mf.metric), 4)
                    elif mf.type == pmp.GAUGE:
                        self.assertEqual(len(mf.metric), 4)
                    elif mf.type == pmp.SUMMARY:
                        self.assertEqual(len(mf.metric), 4)
                        self.assertEqual(len(mf.metric[0].summary.quantile), 3)
                    elif mf.type == pmp.HISTOGRAM:
                        self.assertEqual(len(mf.metric), 4)
                        self.assertEqual(len(mf.metric[0].histogram.bucket), 4)