示例#1
0
    def test_create_counter(self):
        """ check creating counter using api functions """
        # Create a metrics with no metric instances
        mf = pmp.create_counter(self.counter_metric_name,
                                self.counter_metric_help, [])
        self.assertIsInstance(mf, pmp.MetricFamily)
        self.assertEqual(len(mf.metric), 0)

        # Create it with metrics
        mf = pmp.create_counter(self.counter_metric_name,
                                self.counter_metric_help,
                                self.counter_metric_data)
        self.assertIsInstance(mf, pmp.MetricFamily)
        self.assertEqual(mf.name, self.counter_metric_name)
        self.assertEqual(mf.help, self.counter_metric_help)
        self.assertEqual(mf.type, self.counter_metric_type)

        # Create another and check equal
        mf_ = pmp.create_counter(self.counter_metric_name,
                                 self.counter_metric_help,
                                 self.counter_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_counter(
            self.counter_metric_name,
            self.counter_metric_help,
            self.counter_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 Counter with const_labels
        mf_ = pmp.create_counter(
            self.counter_metric_name,
            self.counter_metric_help,
            self.counter_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_)
示例#2
0
    def test_no_metric_instances_present_binary(self):
        """ Check marshalling a collector with no metrics instances present """

        c = Counter(
            name=self.counter_metric_name,
            doc=self.counter_metric_help,
            const_labels=self.const_labels,
        )

        f = binary.BinaryFormatter()

        result = f.marshall_collector(c)
        self.assertIsInstance(result, pmp.MetricFamily)

        # Construct the result expected to receive when the counter
        # collector is marshalled.
        expected_result = pmp.create_counter(self.counter_metric_name,
                                             self.counter_metric_help, [])

        self.assertEqual(result, expected_result)
示例#3
0
    def test_counter_format_binary(self):

        # Check simple metric
        c = Counter(name=self.counter_metric_name,
                    doc=self.counter_metric_help)

        # Add data to the collector
        for labels, value in self.counter_metric_data:
            c.set_value(labels, value)

        f = binary.BinaryFormatter()

        result = f.marshall_collector(c)
        self.assertIsInstance(result, pmp.MetricFamily)

        # Construct the result expected to receive when the counter
        # collector is marshalled.
        expected_result = pmp.create_counter(self.counter_metric_name,
                                             self.counter_metric_help,
                                             self.counter_metric_data)

        self.assertEqual(result, expected_result)

        ######################################################################

        # Check metric with constant labels
        c = Counter(
            name=self.counter_metric_name,
            doc=self.counter_metric_help,
            const_labels=self.const_labels,
        )

        # Add data to the collector
        for labels, value in self.counter_metric_data:
            c.set_value(labels, value)

        f = binary.BinaryFormatter()

        result = f.marshall_collector(c)
        self.assertIsInstance(result, pmp.MetricFamily)

        # Construct the result to expected to receive when the counter
        # collector is marshalled.
        expected_result = pmp.create_counter(
            self.counter_metric_name,
            self.counter_metric_help,
            self.counter_metric_data,
            const_labels=self.const_labels,
        )

        self.assertEqual(result, expected_result)

        ######################################################################

        # Check metric with timestamps
        with unittest.mock.patch.object(pmp.utils,
                                        "_timestamp_ms",
                                        return_value=TEST_TIMESTAMP):

            c = Counter(name=self.counter_metric_name,
                        doc=self.counter_metric_help)

            # Add data to the collector
            for labels, value in self.counter_metric_data:
                c.set_value(labels, value)

            f = binary.BinaryFormatter(timestamp=True)

            result = f.marshall_collector(c)
            self.assertIsInstance(result, pmp.MetricFamily)

            # Construct the result to expected to receive when the counter
            # collector is marshalled.
            expected_result = pmp.create_counter(
                self.counter_metric_name,
                self.counter_metric_help,
                self.counter_metric_data,
                timestamp=True,
            )

            self.assertEqual(result, expected_result)
示例#4
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)