java prometheus 自定义exporter开发,以及实现多个接口返回metrics

普罗----自定义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的四类指标说明

数据类型解释
CounterCounter类型代表一种样本数据单调递增的指标,即只增不减,除非监控系统发生了重置
GuageGuage类型代表一种样本数据可以任意变化的指标,即可增可减
HistogramHistogram 由bucket{le=””},bucket{le=”+Inf”},sum,count 组成,主要用于表示一段时间范围内对数据进行采样(通常是请求持续时间或响应大小),并能够对其指定区间以及总数进行统计,通常它采集的数据展示为直方图
SummarySummary 和 Histogram 类似,由{quantile=”<φ>”},sum,count 组成,主要用于表示一段时间内数据采样结果(通常是请求持续时间或响应大小),它直接存储了 quantile 数据,而不是根据统计区间计算出来的。

目前在开发hadoop集群指标监控中只用到了前两种数据类型。
demo:
创建启动类Exporter

public class Exporter {

    public static void main(String[] args) throws IOException {
        //注册collector
        new Example1Collector().register();
        new Example2Collector().register();
        //开启http服务供prometheus调用,该http服务默认只提供一个接口 http://ip:port/metrics 所有指标一起返回
        HTTPServer server=new HTTPServer("localhost",8080);
    }
}

创建我们自定义的收集器,继承Collector

public class Example1Collector extends Collector {
    //每个指标收集器继承collector类,在收到http请求时,会自动返回collect()方法返回的list
    @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 {
  /**
   * Content-type for text version 0.0.4.
   */
  public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8";

  /**
   * Write out the text version 0.0.4 of the given MetricFamilySamples.
   */
  public static void write004(Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
    /* See http://prometheus.io/docs/instrumenting/exposition_formats/
     * for the output format specification. */
    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>
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值