普罗----自定义exporter开发
exporter的作用是采集需要监控的数据,并将采集到的数据转换成prometheus所需要的数据格式,将这些转换后的数据返回,供给prometheus 使用。
java 编写自定义exporter所需要的pom.xml:
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_httpserver</artifactId>
<version>0.3.0</version>
</dependency>
exporter的四类指标说明
数据类型 | 解释 |
---|
Counter | Counter类型代表一种样本数据单调递增的指标,即只增不减,除非监控系统发生了重置 |
Guage | Guage类型代表一种样本数据可以任意变化的指标,即可增可减 |
Histogram | Histogram 由bucket{le=””},bucket{le=”+Inf”},sum,count 组成,主要用于表示一段时间范围内对数据进行采样(通常是请求持续时间或响应大小),并能够对其指定区间以及总数进行统计,通常它采集的数据展示为直方图 |
Summary | Summary 和 Histogram 类似,由{quantile=”<φ>”},sum,count 组成,主要用于表示一段时间内数据采样结果(通常是请求持续时间或响应大小),它直接存储了 quantile 数据,而不是根据统计区间计算出来的。 |
目前在开发hadoop集群指标监控中只用到了前两种数据类型。
demo:
创建启动类Exporter
public class Exporter {
public static void main(String[] args) throws IOException {
new Example1Collector().register();
new Example2Collector().register();
HTTPServer server=new HTTPServer("localhost",8080);
}
}
创建我们自定义的收集器,继承Collector
public class Example1Collector extends Collector {
@Override
public List<MetricFamilySamples> collect() {
List<MetricFamilySamples> list = new ArrayList<>();
GaugeMetricFamily exampleGaugeMetricFamily = new GaugeMetricFamily("example_1_collector",
"example1_gauge", Arrays.asList("name"));
exampleGaugeMetricFamily.addMetric(Arrays.asList("Example1Collector"), 1);
list.add(exampleGaugeMetricFamily);
return list;
}
}
public class Example2Collector extends Collector {
@Override
public List<MetricFamilySamples> collect() {
List<MetricFamilySamples> list = new ArrayList<>();
CounterMetricFamily exampleCounterMetricFamily= new CounterMetricFamily("example_2_collector",
"example2_counter", Arrays.asList("name"));
exampleCounterMetricFamily.addMetric(Arrays.asList("Example2Collector"), 1);
list.add(exampleCounterMetricFamily);
return list;
}
}
这样一个小demo即完成,启动Exporter即可。
访问http://localhost:8080,返回结果如下:
# HELP example_1_collector example1_gauge
# TYPE example_1_collector gauge
example_1_collector{name="Example1Collector",} 1.0
# HELP example_2_collector example2_counter
# TYPE example_2_collector counter
example_2_collector{name="Example2Collector",} 1.0
这样开发有一个问题就是整个http服务只有这一个接口返回所有指标。假如有需求需要提供多个接口返回指定的指标时,这样就不能满足需求了。
思考:可以使用grizzly2实现http服务提供多个接口,返回固定的指标,那么最重要的就是返回prometheus需要的数据格式,在TextFormat这个类中找到了具体的实现,具体代码如下:
public class TextFormat {
public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8";
public static void write004(Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
while(mfs.hasMoreElements()) {
Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement();
writer.write("# HELP ");
writer.write(metricFamilySamples.name);
writer.write(' ');
writeEscapedHelp(writer, metricFamilySamples.help);
writer.write('\n');
writer.write("# TYPE ");
writer.write(metricFamilySamples.name);
writer.write(' ');
writer.write(typeString(metricFamilySamples.type));
writer.write('\n');
for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) {
writer.write(sample.name);
if (sample.labelNames.size() > 0) {
writer.write('{');
for (int i = 0; i < sample.labelNames.size(); ++i) {
writer.write(sample.labelNames.get(i));
writer.write("=\"");
writeEscapedLabelValue(writer, sample.labelValues.get(i));
writer.write("\",");
}
writer.write('}');
}
writer.write(' ');
writer.write(Collector.doubleToGoString(sample.value));
if (sample.timestampMs != null){
writer.write(' ');
writer.write(sample.timestampMs.toString());
}
writer.write('\n');
}
}
}
private static void writeEscapedHelp(Writer writer, String s) throws IOException {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\\':
writer.append("\\\\");
break;
case '\n':
writer.append("\\n");
break;
default:
writer.append(c);
}
}
}
private static void writeEscapedLabelValue(Writer writer, String s) throws IOException {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\\':
writer.append("\\\\");
break;
case '\"':
writer.append("\\\"");
break;
case '\n':
writer.append("\\n");
break;
default:
writer.append(c);
}
}
}
private static String typeString(Collector.Type t) {
switch (t) {
case GAUGE:
return "gauge";
case COUNTER:
return "counter";
case SUMMARY:
return "summary";
case HISTOGRAM:
return "histogram";
default:
return "untyped";
}
}
}
可以通过在获取collector返回的list后调用该方法返回普罗的数据格式。
这种方式可实现多个自定义接口返回多个指定的metrics
pom.xml
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.25.1</version>
</dependency>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)