Esempio n. 1
0
    def test_summary(self):
        """Test that we can track summaries in Service303"""
        # Add a summary with a label to the regisry
        c = Summary('process_max_fds', 'A summary', ['result'], registry=self.registry)
        c.labels('success').observe(1.23)
        c.labels('failure').observe(2.34)

        # Build proto outputs
        summary1 = metrics_pb2.Summary(sample_count=1, sample_sum=1.23)
        summary2 = metrics_pb2.Summary(sample_count=1, sample_sum=2.34)
        metric1 = metrics_pb2.Metric(summary=summary1,
                                     timestamp_ms=1234000)
        metric2 = metrics_pb2.Metric(summary=summary2,
                                     timestamp_ms=1234000)
        family = metrics_pb2.MetricFamily(
            name=str(metricsd_pb2.process_max_fds),
            type=metrics_pb2.SUMMARY)
        metric1.label.add(
            name=str(metricsd_pb2.result),
            value='success')
        metric2.label.add(
            name=str(metricsd_pb2.result),
            value='failure')
        family.metric.extend([metric1, metric2])

        with unittest.mock.patch('time.time') as mock_time:
            mock_time.side_effect = lambda: 1234
            self.assertCountEqual(list(metrics_export.get_metrics(self.registry))[0].metric,
                             family.metric)
Esempio n. 2
0
    def test_histogram(self):
        """Test that we can track histogram in Service303"""
        # Add a histogram with a label to the regisry
        c = Histogram('process_max_fds',
                      'A summary', ['result'],
                      registry=self.registry,
                      buckets=[0, 2, float('inf')])
        c.labels('success').observe(1.23)
        c.labels('failure').observe(2.34)

        # Build proto outputs
        histogram1 = metrics_pb2.Histogram(sample_count=1, sample_sum=1.23)
        histogram1.bucket.add(upper_bound=0, cumulative_count=0)
        histogram1.bucket.add(upper_bound=2, cumulative_count=1)
        histogram1.bucket.add(upper_bound=float('inf'), cumulative_count=1)
        histogram2 = metrics_pb2.Histogram(sample_count=1, sample_sum=2.34)
        histogram2.bucket.add(upper_bound=0, cumulative_count=0)
        histogram2.bucket.add(upper_bound=2, cumulative_count=0)
        histogram2.bucket.add(upper_bound=float('inf'), cumulative_count=1)
        metric1 = metrics_pb2.Metric(histogram=histogram1,
                                     timestamp_ms=1234000)
        metric2 = metrics_pb2.Metric(histogram=histogram2,
                                     timestamp_ms=1234000)
        family = metrics_pb2.MetricFamily(name=str(
            metricsd_pb2.process_max_fds),
                                          type=metrics_pb2.HISTOGRAM)
        metric1.label.add(name=str(metricsd_pb2.result), value='success')
        metric2.label.add(name=str(metricsd_pb2.result), value='failure')
        family.metric.extend([metric1, metric2])

        with unittest.mock.patch('time.time') as mock_time:
            mock_time.side_effect = lambda: 1234
            self.assertCountEqual(
                list(metrics_export.get_metrics(self.registry))[0].metric,
                family.metric)
Esempio n. 3
0
    def test_gauge(self):
        """Test that we can track gauges in Service303"""
        # Add a gauge with a label to the regisry
        c = Gauge('process_max_fds', 'A gauge', ['result'],
                  registry=self.registry)

        # Create two series for value1 and value2
        c.labels('success').inc(1.23)
        c.labels('failure').inc(2.34)

        # Build proto outputs
        gauge1 = metrics_pb2.Gauge(value=1.23)
        gauge2 = metrics_pb2.Gauge(value=2.34)
        metric1 = metrics_pb2.Metric(gauge=gauge1,
                                     timestamp_ms=1234000)
        metric2 = metrics_pb2.Metric(gauge=gauge2,
                                     timestamp_ms=1234000)
        family = metrics_pb2.MetricFamily(
            name=str(metricsd_pb2.process_max_fds),
            type=metrics_pb2.GAUGE)
        metric1.label.add(
            name=str(metricsd_pb2.result),
            value='success')
        metric2.label.add(
            name=str(metricsd_pb2.result),
            value='failure')
        family.metric.extend([metric1, metric2])

        with unittest.mock.patch('time.time') as mock_time:
            mock_time.side_effect = lambda: 1234
            self.assertCountEqual(list(metrics_export.get_metrics(self.registry))[0].metric,
                             family.metric)
Esempio n. 4
0
def encode_counter_gauge(family, timestamp_ms):
    """
    Takes a Counter/Gauge family which is a collection of timeseries
    samples that share a name (uniquely identified by labels) and yields
    equivalent protobufs.

    Each timeseries corresponds to a single sample tuple of the format:
        (NAME, LABELS, VALUE)

    Arguments:
        family: a prometheus gauge metric family
        timestamp_ms: the timestamp to attach to the samples
    Returns:
        A Counter or Gauge prometheus MetricFamily protobuf
    """
    family_proto = metrics_pb2.MetricFamily()
    family_proto.type = \
        metrics_pb2.MetricType.Value(family.type.upper())
    for sample in family.samples:
        metric_proto = metrics_pb2.Metric()
        if family_proto.type == metrics_pb2.COUNTER:
            metric_proto.counter.value = sample[2]
        elif family_proto.type == metrics_pb2.GAUGE:
            metric_proto.gauge.value = sample[2]
        # Add meta-data to the timeseries
        metric_proto.timestamp_ms = timestamp_ms
        metric_proto.label.extend(
            _convert_labels_to_pb_pairs(sample[1].items()))
        # Append metric sample to family
        family_proto.metric.extend([metric_proto])
    return family_proto
Esempio n. 5
0
    def test_counter(self):
        """Test that we can track counters in Service303"""
        # Add a counter with a label to the regisry
        process_max_metric_name = 'process_max_fds'
        c = Counter(
            process_max_metric_name,
            'A counter',
            ['result'],
            registry=self.registry,
        )

        # Create two series for value1 and value2
        c.labels('success').inc(1.23)
        c.labels('failure').inc(2.34)

        # Build proto outputs
        counter1 = metrics_pb2.Counter(value=1.23)
        counter2 = metrics_pb2.Counter(value=2.34)
        metric1 = metrics_pb2.Metric(
            counter=counter1,
            timestamp_ms=1234000,
        )
        metric2 = metrics_pb2.Metric(
            counter=counter2,
            timestamp_ms=1234000,
        )
        family = metrics_pb2.MetricFamily(
            name=process_max_metric_name,
            type=metrics_pb2.COUNTER,
        )
        metric1.label.add(
            name='result',
            value='success',
        )
        metric2.label.add(
            name='result',
            value='failure',
        )
        family.metric.extend([metric1, metric2])

        with unittest.mock.patch('time.time') as mock_time:
            mock_time.side_effect = lambda: 1234
            self.assertCountEqual(
                list(metrics_export.get_metrics(self.registry))[0].metric,
                family.metric,
            )
Esempio n. 6
0
def _gauge_to_proto(
    metric: prometheus_client.core.Metric, ) -> metrics_pb2.MetricFamily:
    ret = metrics_pb2.MetricFamily(name=metric.name, type=metrics_pb2.GAUGE)
    for sample in metric.samples:
        (_, labels, value, *_) = sample
        met = metrics_pb2.Metric(gauge=metrics_pb2.Gauge(value=value))
        for key in labels:
            met.label.add(name=key, value=labels[key])
        ret.metric.extend([met])
    return ret
Esempio n. 7
0
def _counter_to_proto(
    metric: prometheus_client.core.Metric, ) -> metrics_pb2.MetricFamily:
    ret = metrics_pb2.MetricFamily(name=metric.name, type=metrics_pb2.COUNTER)
    for sample in metric.samples:
        counter = metrics_pb2.Counter(value=sample[2])
        met = metrics_pb2.Metric(counter=counter)
        for key in sample[1]:
            met.label.add(name=key, value=sample[1][key])
        ret.metric.extend([met])
    return ret
Esempio n. 8
0
def _untyped_to_proto(
    metric: prometheus_client.core.Metric, ) -> metrics_pb2.MetricFamily:
    ret = metrics_pb2.MetricFamily(name=metric.name, type=metrics_pb2.UNTYPED)
    for sample in metric.samples:
        (_, labels, value, *_) = sample
        new_untyped = metrics_pb2.Untyped(value=value)
        met = metrics_pb2.Metric(untyped=new_untyped)
        for key in labels:
            met.label.add(name=key, value=labels[key])
        ret.metric.extend([met])
    return ret
Esempio n. 9
0
def _get_collect_success_metric(service_name, gw_up):
    """
    Get a the service_metrics_collected metric for a service which is either 0
    if the collection was unsuccessful or 1 if it was successful
    """
    family_proto = metrics_pb2.MetricFamily(
        type=metrics_pb2.GAUGE,
        name=str(metricsd_pb2.service_metrics_collected),
    )
    metric_proto = metrics_pb2.Metric(timestamp_ms=int(time.time() * 1000))
    metric_proto.gauge.value = 1 if gw_up else 0
    metric_proto.label.add(name="service", value=service_name)
    family_proto.metric.extend([metric_proto])
    return family_proto
Esempio n. 10
0
def _get_uptime_metric(service_name, start_time):
    """
    Returns a metric for service uptime using the prometheus exposed
    process_start_time_seconds
    """
    # Metrics collection should never fail, so only log exceptions
    curr_time = calendar.timegm(time.gmtime())
    uptime = curr_time - start_time
    family_proto = metrics_pb2.MetricFamily(
        type=metrics_pb2.GAUGE,
        name=str(metricsd_pb2.process_uptime_seconds),
    )
    metric_proto = metrics_pb2.Metric(timestamp_ms=int(time.time() * 1000))
    metric_proto.gauge.value = uptime
    metric_proto.label.add(name="service", value=service_name)
    family_proto.metric.extend([metric_proto])
    return family_proto
Esempio n. 11
0
def _summary_to_proto(
        metric: prometheus_client.core.Metric,
) -> [metrics_pb2.MetricFamily]:
    """
    1. Get metrics by unique labelset ignoring quantile
    2. convert to proto separately for each one
    """

    family_by_labelset = {}

    for sample in metric.samples:
        (name, labels, value, *_) = sample
        # get real family by checking labels (ignoring quantile)
        distinct_labels = frozenset(_remove_label(labels, 'quantile').items())
        if distinct_labels not in family_by_labelset:
            fam = metrics_pb2.MetricFamily(
                name=metric.name,
                type=metrics_pb2.SUMMARY,
            )
            summ = metrics_pb2.Summary(sample_count=0, sample_sum=0)
            fam.metric.extend([metrics_pb2.Metric(summary=summ)])
            family_by_labelset[distinct_labels] = fam

        unique_family = family_by_labelset[distinct_labels]

        if str.endswith(name, "_sum"):
            unique_family.metric[0].summary.sample_sum = value
        elif str.endswith(name, "_count"):
            unique_family.metric[0].summary.sample_count = int(value)
        elif 'quantile' in labels:
            unique_family.metric[0].summary.quantile.extend([
                metrics_pb2.Quantile(
                    quantile=float(labels['quantile']),
                    value=value,
                ),
            ])

    # Add non-quantile labels to all metrics
    for labelset in family_by_labelset.keys():
        for label in labelset:
            family_by_labelset[labelset].metric[0].label.add(
                name=label[0],
                value=label[1],
            )

    return list(family_by_labelset.values())
Esempio n. 12
0
def encode_summary(family, timestamp_ms):
    """
    Takes a Summary Metric family which is a collection of timeseries
    samples that share a name (uniquely identified by labels) and yields
    equivalent protobufs.

    Each summary timeseries consists of sample tuples for the count, sum,
    and quantiles in the format (NAME,LABELS,VALUE). The NAME is suffixed
    with either _count, _sum to indicate count and sum respectively.
    Quantile samples will be of the same NAME with quantile label.

    Arguments:
        family: a prometheus summary metric family
        timestamp_ms: the timestamp to attach to the samples
    Raises:
        ValueError if metric name is not defined in MetricNames protobuf
    Returns:
        a Summary prometheus MetricFamily protobuf
    """
    family_proto = metrics_pb2.MetricFamily()
    family_proto.type = metrics_pb2.SUMMARY
    metric_protos = {}
    # Build a map of each of the summary timeseries from the samples
    for sample in family.samples:
        quantile = sample[1].pop('quantile', None)  # Remove from label set
        # Each time series identified by label set excluding the quantile
        metric_proto = \
            metric_protos.setdefault(
                frozenset(sample[1].items()),
                metrics_pb2.Metric(),
            )
        if sample[0].endswith('_count'):
            metric_proto.summary.sample_count = int(sample[2])
        elif sample[0].endswith('_sum'):
            metric_proto.summary.sample_sum = sample[2]
        elif quantile:
            quantile = metric_proto.summary.quantile.add()
            quantile.value = sample[2]
            quantile.quantile = _goStringToFloat(quantile)
    # Go back and add meta-data to the timeseries
    for labels, metric_proto in metric_protos.items():
        metric_proto.timestamp_ms = timestamp_ms
        metric_proto.label.extend(_convert_labels_to_enums(labels))
        # Add it to the family
        family_proto.metric.extend([metric_proto])
    return family_proto
Esempio n. 13
0
def _histogram_to_proto(
        metric: prometheus_client.core.Metric,
) -> [metrics_pb2.MetricFamily]:
    """
    1. Get metrics by unique labelset ignoring quantile
    2. convert to proto separately for each one
    """

    family_by_labelset = {}

    for sample in metric.samples:
        (name, labels, value, *_) = sample
        # get real family by checking labels (ignoring le)
        distinct_labels = frozenset(_remove_label(labels, 'le').items())
        if distinct_labels not in family_by_labelset:
            fam = metrics_pb2.MetricFamily(
                name=metric.name,
                type=metrics_pb2.HISTOGRAM,
            )
            hist = metrics_pb2.Histogram(sample_count=0, sample_sum=0)
            fam.metric.extend([metrics_pb2.Metric(histogram=hist)])
            family_by_labelset[distinct_labels] = fam

        unique_family = family_by_labelset[distinct_labels]

        if str.endswith(name, "_sum"):
            unique_family.metric[0].histogram.sample_sum = value
        elif str.endswith(name, "_count"):
            unique_family.metric[0].histogram.sample_count = int(value)
        elif 'le' in labels:
            unique_family.metric[0].histogram.bucket.extend([
                metrics_pb2.Bucket(
                    upper_bound=float(labels['le']),
                    cumulative_count=value,
                ),
            ])

    # Add non-quantile labels to all metrics
    for labelset in family_by_labelset.keys():
        for label in labelset:
            family_by_labelset[labelset].metric[0].label.add(
                name=str(label[0]), value=str(label[1]),
            )

    return list(family_by_labelset.values())
Esempio n. 14
0
def encode_histogram(family, timestamp_ms):
    """
    Takes a Histogram Metric family which is a collection of timeseries
    samples that share a name (uniquely identified by labels) and yields
    equivalent protobufs.

    Each summary timeseries consists of sample tuples for the count, sum,
    and quantiles in the format (NAME,LABELS,VALUE). The NAME is suffixed
    with either _count, _sum, _buckets to indicate count, sum and buckets
    respectively. Bucket samples will also contain a le to indicate its
    upper bound.

    Arguments:
        family: a prometheus histogram metric family
        timestamp_ms: the timestamp to attach to the samples
    Raises:
        ValueError if metric name is not defined in MetricNames protobuf
    Returns:
        a Histogram prometheus MetricFamily protobuf
    """
    family_proto = metrics_pb2.MetricFamily()
    family_proto.type = metrics_pb2.HISTOGRAM
    metric_protos = {}
    for sample in family.samples:
        upper_bound = sample[1].pop('le', None)  # Remove from label set
        metric_proto = \
            metric_protos.setdefault(
                frozenset(sample[1].items()),
                metrics_pb2.Metric(),
            )
        if sample[0].endswith('_count'):
            metric_proto.histogram.sample_count = int(sample[2])
        elif sample[0].endswith('_sum'):
            metric_proto.histogram.sample_sum = sample[2]
        elif sample[0].endswith('_bucket'):
            quantile = metric_proto.histogram.bucket.add()
            quantile.cumulative_count = int(sample[2])
            quantile.upper_bound = _goStringToFloat(upper_bound)
    # Go back and add meta-data to the timeseries
    for labels, metric_proto in metric_protos.items():
        metric_proto.timestamp_ms = timestamp_ms
        metric_proto.label.extend(_convert_labels_to_enums(labels))
        # Add it to the family
        family_proto.metric.extend([metric_proto])
    return family_proto