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 """) # 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))
def collect(self): response = requests.get(args.uri) json = response.json() metrics = json['metrics'] # iterate over all metrics for k in metrics: underscores = re.sub('\.|-|\s', '_', k).lower() if metrics[k]['type'] == 'timer': # we have a timer, expose as a Prometheus Summary underscores = underscores + '_' + metrics[k]['duration_unit'] summary = SummaryMetricFamily(underscores, 'libmedida metric type: ' + metrics[k]['type'], count_value=metrics[k]['count'], sum_value=(metrics[k]['mean'] * metrics[k]['count'])) # add stellar-core calculated quantiles to our summary summary.add_sample(underscores, labels={'quantile':'0.75'}, value=metrics[k]['75%']) summary.add_sample(underscores, labels={'quantile':'0.99'}, value=metrics[k]['99%']) yield summary elif metrics[k]['type'] == 'counter': # we have a counter, this is a Prometheus Gauge yield GaugeMetricFamily(underscores, 'libmedida metric type: ' + metrics[k]['type'], value=metrics[k]['count']) elif metrics[k]['type'] == 'meter': # we have a meter, this is a Prometheus Counter yield CounterMetricFamily(underscores, 'libmedida metric type: ' + metrics[k]['type'], value=metrics[k]['count'])
def collect(self): # TODO handle missing labels, probably return 500? labels = self.get_labels() labels_p75 = labels.copy() # Work on copy of labels variable to avoid other metrics getting quantile label labels_p75.update({'quantile': '0.75'}) labels_p99 = labels.copy() # Work on copy of labels variable to avoid other metrics getting quantile label labels_p99.update({'quantile': '0.99'}) response = requests.get(args.uri) metrics = response.json()['metrics'] # iterate over all metrics for k in metrics: metric_name = re.sub('\.|-|\s', '_', k).lower() metric_name = 'stellar_core_' + metric_name if metrics[k]['type'] == 'timer': # we have a timer, expose as a Prometheus Summary # we convert stellar-core time units to seconds, as per Prometheus best practices metric_name = metric_name + '_seconds' if 'sum' in metrics[k]: # use libmedida sum value total_duration = metrics[k]['sum'] else: # compute sum value total_duration = (metrics[k]['mean'] * metrics[k]['count']) summary = SummaryMetricFamily(metric_name, 'libmedida metric type: ' + metrics[k]['type'], labels=labels.keys()) summary.add_metric(labels.values(), count_value=metrics[k]['count'], sum_value=(duration_to_seconds(total_duration, metrics[k]['duration_unit']))) # add stellar-core calculated quantiles to our summary summary.add_sample(metric_name, labels=labels_p75, value=(duration_to_seconds(metrics[k]['75%'], metrics[k]['duration_unit']))) summary.add_sample(metric_name, labels=labels_p99, value=(duration_to_seconds(metrics[k]['99%'], metrics[k]['duration_unit']))) yield summary elif metrics[k]['type'] == 'counter': # we have a counter, this is a Prometheus Gauge g = GaugeMetricFamily(metric_name, 'libmedida metric type: ' + metrics[k]['type'], labels=labels.keys()) g.add_metric(labels.values(), metrics[k]['count']) yield g elif metrics[k]['type'] == 'meter': # we have a meter, this is a Prometheus Counter c = CounterMetricFamily(metric_name, 'libmedida metric type: ' + metrics[k]['type'], labels=labels.keys()) c.add_metric(labels.values(), metrics[k]['count']) yield c # Export metrics from the info endpoint response = requests.get(args.info_uri) info = response.json()['info'] if not all([i in info for i in self.info_keys]): print('WARNING: info endpoint did not return all required fields') return # Ledger metrics for core_name, prom_name in self.ledger_metrics.items(): g = GaugeMetricFamily('stellar_core_ledger_{}'.format(prom_name), 'Stellar core ledger metric name: {}'.format(core_name), labels=labels.keys()) g.add_metric(labels.values(), info['ledger'][core_name]) yield g # Quorum metrics are reported under dynamic name for example: # "quorum" : { # "758110" : { # "agree" : 3, tmp = info['quorum'].values()[0] for metric in self.quorum_metrics: g = GaugeMetricFamily('stellar_core_quorum_{}'.format(metric), 'Stellar core quorum metric: {}'.format(metric), labels=labels.keys()) g.add_metric(labels.values(), tmp[metric]) yield g # Peers metrics g = GaugeMetricFamily('stellar_core_peers_authenticated_count', 'Stellar core authenticated_count count', labels=labels.keys()) g.add_metric(labels.values(), info['peers']['authenticated_count']) yield g g = GaugeMetricFamily('stellar_core_peers_pending_count', 'Stellar core pending_count count', labels=labels.keys()) g.add_metric(labels.values(), info['peers']['pending_count']) yield g g = GaugeMetricFamily('stellar_core_protocol_version', 'Stellar core protocol_version', labels=labels.keys()) g.add_metric(labels.values(), info['protocol_version']) yield g g = GaugeMetricFamily('stellar_core_synced', 'Stellar core sync status', labels=labels.keys()) if info['state'] == 'Synced!': g.add_metric(labels.values(), 1) else: g.add_metric(labels.values(), 0) yield g g = GaugeMetricFamily('stellar_core_started_on', 'Stellar core start time in epoch', labels=labels.keys()) date = datetime.strptime(info['startedOn'], "%Y-%m-%dT%H:%M:%SZ") g.add_metric(labels.values(), int(date.strftime('%s'))) yield g