
org.apache.bookkeeper.stats.prometheus.PrometheusTextFormat Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.bookkeeper.stats.prometheus;
import io.prometheus.client.Collector;
import io.prometheus.client.Collector.MetricFamilySamples;
import io.prometheus.client.Collector.MetricFamilySamples.Sample;
import io.prometheus.client.CollectorRegistry;
import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Logic to write metrics in Prometheus text format.
*/
public class PrometheusTextFormat {
Set metricNameSet = new HashSet<>();
void writeGauge(Writer w, String name, SimpleGauge extends Number> gauge) {
// Example:
// # TYPE bookie_storage_entries_count gauge
// bookie_storage_entries_count 519
try {
writeType(w, name, "gauge");
w.append(name);
writeLabels(w, gauge.getLabels());
w.append(' ').append(gauge.getSample().toString()).append('\n');
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void writeCounter(Writer w, String name, LongAdderCounter counter) {
// Example:
// # TYPE jvm_threads_started_total counter
// jvm_threads_started_total 59
try {
writeType(w, name, "counter");
w.append(name);
writeLabels(w, counter.getLabels());
w.append(' ').append(counter.get().toString()).append('\n');
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void writeOpStat(Writer w, String name, DataSketchesOpStatsLogger opStat) {
// Example:
// # TYPE bookie_journal_JOURNAL_ADD_ENTRY summary
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="0.5",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="0.75",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="0.95",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="0.99",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="0.999",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="0.9999",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY{success="false",quantile="1.0",} NaN
// bookie_journal_JOURNAL_ADD_ENTRY_count{success="false",} 0.0
// bookie_journal_JOURNAL_ADD_ENTRY_sum{success="false",} 0.0
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="0.5",} 1.706
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="0.75",} 1.89
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="0.95",} 2.121
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="0.99",} 10.708
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="0.999",} 10.902
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="0.9999",} 10.902
// bookie_journal_JOURNAL_ADD_ENTRY{success="true",quantile="1.0",} 10.902
// bookie_journal_JOURNAL_ADD_ENTRY_count{success="true",} 658.0
// bookie_journal_JOURNAL_ADD_ENTRY_sum{success="true",} 1265.0800000000002
try {
writeType(w, name, "summary");
writeQuantile(w, opStat, name, false, 0.5);
writeQuantile(w, opStat, name, false, 0.75);
writeQuantile(w, opStat, name, false, 0.95);
writeQuantile(w, opStat, name, false, 0.99);
writeQuantile(w, opStat, name, false, 0.999);
writeQuantile(w, opStat, name, false, 0.9999);
writeQuantile(w, opStat, name, false, 1.0);
writeCount(w, opStat, name, false);
writeSum(w, opStat, name, false);
writeQuantile(w, opStat, name, true, 0.5);
writeQuantile(w, opStat, name, true, 0.75);
writeQuantile(w, opStat, name, true, 0.95);
writeQuantile(w, opStat, name, true, 0.99);
writeQuantile(w, opStat, name, true, 0.999);
writeQuantile(w, opStat, name, true, 0.9999);
writeQuantile(w, opStat, name, true, 1.0);
writeCount(w, opStat, name, true);
writeSum(w, opStat, name, true);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void writeLabels(Writer w, Map labels) throws IOException {
if (labels.isEmpty()) {
return;
}
w.append('{');
writeLabelsNoBraces(w, labels);
w.append('}');
}
private void writeLabelsNoBraces(Writer w, Map labels) throws IOException {
if (labels.isEmpty()) {
return;
}
boolean isFirst = true;
for (Map.Entry e : labels.entrySet()) {
if (!isFirst) {
w.append(',');
}
isFirst = false;
w.append(e.getKey())
.append("=\"")
.append(e.getValue())
.append('"');
}
}
private void writeQuantile(Writer w, DataSketchesOpStatsLogger opStat, String name, Boolean success,
double quantile) throws IOException {
w.append(name)
.append("{success=\"").append(success.toString())
.append("\",quantile=\"").append(Double.toString(quantile))
.append("\"");
if (!opStat.getLabels().isEmpty()) {
w.append(", ");
writeLabelsNoBraces(w, opStat.getLabels());
}
w.append("} ")
.append(Double.toString(opStat.getQuantileValue(success, quantile))).append('\n');
}
private void writeCount(Writer w, DataSketchesOpStatsLogger opStat, String name, Boolean success)
throws IOException {
w.append(name).append("_count{success=\"").append(success.toString()).append("\"");
if (!opStat.getLabels().isEmpty()) {
w.append(", ");
writeLabelsNoBraces(w, opStat.getLabels());
}
w.append("} ")
.append(Long.toString(opStat.getCount(success))).append('\n');
}
private void writeSum(Writer w, DataSketchesOpStatsLogger opStat, String name, Boolean success)
throws IOException {
w.append(name).append("_sum{success=\"").append(success.toString()).append("\"");
if (!opStat.getLabels().isEmpty()) {
w.append(", ");
writeLabelsNoBraces(w, opStat.getLabels());
}
w.append("} ")
.append(Double.toString(opStat.getSum(success))).append('\n');
}
static void writeMetricsCollectedByPrometheusClient(Writer w, CollectorRegistry registry) throws IOException {
Enumeration metricFamilySamples = registry.metricFamilySamples();
while (metricFamilySamples.hasMoreElements()) {
MetricFamilySamples metricFamily = metricFamilySamples.nextElement();
// Write type of metric
w.append("# TYPE ").append(metricFamily.name).append(getTypeNameSuffix(metricFamily.type)).append(' ')
.append(getTypeStr(metricFamily.type)).write('\n');
for (int i = 0; i < metricFamily.samples.size(); i++) {
Sample sample = metricFamily.samples.get(i);
w.write(sample.name);
w.write('{');
for (int j = 0; j < sample.labelNames.size(); j++) {
if (j != 0) {
w.write(", ");
}
w.write(sample.labelNames.get(j));
w.write("=\"");
w.write(sample.labelValues.get(j));
w.write('"');
}
w.write("} ");
w.write(Collector.doubleToGoString(sample.value));
w.write('\n');
}
}
}
static String getTypeNameSuffix(Collector.Type type) {
if (type.equals(Collector.Type.INFO)) {
return "_info";
}
return "";
}
static String getTypeStr(Collector.Type type) {
switch (type) {
case COUNTER:
return "counter";
case GAUGE:
case INFO:
return "gauge";
case SUMMARY:
return "summary";
case HISTOGRAM:
return "histogram";
case UNKNOWN:
default:
return "unknown";
}
}
void writeType(Writer w, String name, String type) throws IOException {
if (metricNameSet.contains(name)) {
return;
}
metricNameSet.add(name);
w.append("# TYPE ").append(name).append(" ").append(type).append("\n");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy