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

2023-05-16

普罗----自定义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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • 卡尔曼滤波算法详细推导(全网最详细的推导过程)

    本文是来源于B站Dr CAN的视频的学习笔记 xff0c 有需要详细了解的 xff0c 可以到B站看相关视频DR CAN的个人空间 1 递归算法 例 xff1a 假设测一段距离 xff0c 第一次测 z 1 z 1 z 1 61 50 1m
  • ADC采样滤波算法利用卡尔曼滤波算法详解

    1 ADC采样模型 xff08 本文为笔者早期所写 xff0c 当时对卡尔曼滤波器理解尚未透彻 xff0c 如今回顾 xff0c 该模型还有所缺陷 xff0c 推荐读者看卡尔曼的推导过程或者B站大佬Dr CAN的空间 xff09 假设ADC
  • 微信支付趟过的坑

    这段时间在做微信支付开发 xff0c 在公司的公众号审批下来后 xff0c 我这边的测试用例也已经开发完毕 xff0c 于是拿着具体的数据来调试了 xff0c 大段大段的代码就不贴了 xff0c demo里有 xff0c 这里就说说调试过程
  • java底层原理

    Java运行三部曲 xff1a 编写 xff0c 编译 xff0c 运行 编写 xff1a 硬件编写代码 xff0c 就是我们写代码 编译 xff1a javac将文件编译成一个或多个 class文件 编译中间的过程主要是类型和格式的检查
  • 信息化时代下的我们----弄潮儿

    读完 信息化与信息管理实践之道 的部分章节想起了 第三次浪潮 中的一段话 xff0c 摘录如下 人类到现在已经经历了两次巨大的变革浪潮 这两次浪潮都淹没了早先的文明和文化 xff0c 都是以前人所不能想象的生活方式 xff0c 替代了原来的
  • ORB-SLAM稠密点云地图构建(黑白+彩色)+ pcd文件以八叉树形式表示

    pcl1 8 1 VTK 7 1 1 版本一定要对好 xff0c 如果安装了不符的版本如我之前安的pcl1 1 3和VTK8 2 一定要卸载干净不然会一直报错 xff0c 不同版本的pcl和vtk是无法共存的 xff0c 并且光把包删除是不
  • 一步步学习多线程(一) 重要概念

    几个重要的概念 1 同步 xff08 synchronous xff09 和 异步 xff08 asynchronous xff09 2 并发 xff08 Concurrency xff09 和 并行 xff08 Parallelism x
  • MAVLink功能开发,移植教程。

    MAVLink功能开发 本文由 智御电子 提供 xff0c 同时提供视频移植教程 xff0c 以便电子爱好者交流学习 1 MAVLink简介 MAVLink是一种针对微型飞行器 xff0c 推出的轻量化 xff0c 仅由头文件信息编码而成的
  • workerman问题总结大全及解决方案

    workerman无法正常访问 问题描述 xff1a 在阿里云ECS上部署了workerman的应用 xff08 ECS是专有网络 xff09 xff0c 在ECS安全组里已经允许workerman需要的全部端口 xff0c 但是外网一直不
  • Eclipse Android开发遇到:"The type org.apache.http.HttpResponse cannot be resolved."问题的解决办法

    今天在做手机卫士的项目中 xff0c 在联网下载的功能模块中遇到The type org apache http HttpResponse cannot be resolved It is indirectly referenced fro
  • UG创建图纸明细表失败的情况

    今天进行UG二次开发的时候 xff0c 由于要在图纸中自动加入零件明细表 xff0c 但是当我在图纸中插入明细表的时候UG会弹出错误对话框 xff1a 当打开UGII UPDATE ALL ID SYMBOLS WITH PLIST变量时
  • 字符串末尾自动加上'\0'的情况

    之前一直都有一个问题困扰着我 xff0c 就是我们知道C风格的字符串在用strlen求长度时只会遇到 39 0 39 结束 xff0c 如果一个字符数组全部填满了 xff0c 而在末尾没有加上 39 0 39 就会出现结果不定的现象 xff
  • c++类成员变量的初始化顺序以及特殊成员的初始化方法规则

    说到类的成员变量的初始化顺序 xff0c 对于初学者很多容易混淆其顺序 xff0c 以为简单的按初始表来初始化 xff0c 其实不然 xff0c 现在我来详细讲解下类的初始化顺序 xff1a 首先由简单开始 xff1a class peop
  • deque 迭代器失效的问题详解

    今天在看STL源码的时候 xff0c 无意写了如下的代码 xff0c 发现程序崩溃了 xff1a lt span style 61 34 font size 14px 34 gt deque lt int gt iterator iter
  • Python中__init__.py文件的作用

    在创建python包的过程中 xff0c IDE都会在包根目录下创建一个 init py文件 xff0c 该Python文件默认是空的 目录结构如下 xff1a Pycharm下的package树结构 xff1a 在Finder中的目录结构
  • 使用Ajax以及CSS+DIV高仿谷歌搜索(附源码下载)

    在使用 Google 搜索或者是 Baidu 搜索的时候 xff0c 在输入搜索关键字的同时 xff0c 会自动弹出匹配的其他关键字的提示 xff0c 全心全意为人民服务的精神在这里崭露无遗 这种利用 Ajax 技术实现输入提示和自动完成的
  • 导致索引失效的可能情况

    如下是可能导致索引失效的情况 xff1a 1 xff0e 隐式转换导致索引失效 这一点应当引起重视 也是开发中经常会犯的错误 由于表的字段tu mdn定义为varchar2 20 但在查询时把该字段作为number类型以where条件传给O
  • 二叉搜索树的增删查

    今天把搜索二叉树的思路又理了一遍 xff0c 把代码又从头到尾敲了一遍 xff0c 各位看客就不要在意代码粗糙和内存溢出了 xff0c 主要把插入和删除的过程理了一遍 xff0c 其中比较复杂的地方就是搜索二叉树的删除 xff0c 涉及了很
  • 中缀表达式转前缀和后缀表达式

    之前笔试中国电信IT研发中心的时候 xff0c 遇到了几个前 中 后缀表达式的相互转换 xff0c 当时忘得差不多了 xff0c 今天好好把该方面的知识好好复习 xff0c 并把相关代码和思路自己缕了一遍 xff1a 将中缀表达式转换为前缀
  • java prometheus 自定义exporter开发,以及实现多个接口返回metrics

    普罗 自定义exporter开发 exporter的作用是采集需要监控的数据 xff0c 并将采集到的数据转换成prometheus所需要的数据格式 xff0c 将这些转换后的数据返回 xff0c 供给prometheus 使用 java