论如何通过java adapter获取prometheus remote write数据

1.如何实现prometheus remote write adapter java版本

prometheus 的remote write 与remote read 功能很强大,根据这两个功能,可以完全脱离对本地文件存储的依赖,并把数据存储变为可自定义的,现在来调研一下这个功能。

prometheus 官方提供各种remote write 的适配器,但唯独没有java语言的。
prometheus 官方remote write 版本

所以现在想解析prometheus 指标数据。

1.remote write

根据prometheus 的配置文件可以得知,remote_write 后面跟一个url路径,prometheus 会把每次刮取到的数据推到这个url上,于是我实现了一个简单的http接口:

1
2
3
4
@PostMapping("/xx")
public void getmsg(@RequestBody String msg){
xxx
}

但是发现报了一堆提示无法解析的错误,百度了一下发现是prometheus 的remote write格式比较特殊。
于是:

  • 翻到prometheus github 源码,找到remote write 的文件格式:https://github.com/prometheus/prometheus/blob/master/prompb/remote.proto,并下载下来

同时需要下载同路径文件type.proto,这两个文件互为依赖,最后把其他的依赖删掉

  • remote.proto的头部

    1
    2
    3
    4
    5
    syntax = "proto3";
    package prometheus;
    option go_package = "prompb";
    import "types.proto";
    import "gogoproto/gogo.proto"; // 删掉
  • types.proto的头部

    1
    2
    3
    4
    syntax = "proto3";
    package prometheus;
    option go_package = "prompb";
    import "gogoproto/gogo.proto"; // 删掉
  • 至于为什么删掉,因为该依赖对于java来说没什么用处: 相关issue

1.1 引入依赖

  • a.引入protobuf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<properties>
<grpc.version>1.7.0</grpc.version>
<protobuf.version>3.4.0</protobuf.version>
<snappy.version>1.1.4</snappy.version>
</properties>

<!--protobuf & java -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
<version>${snappy.version}</version>
</dependency>

1.2 引入maven插件,用于把.proto 文件转化为.java 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

1.3 重新编译项目,生成.java 文件

** 注意:**

  • 新生成的文件路径参照.proto文件内package的具体值。
  • 文件不是源码形式,而是编译后的.class文件,在target目录下

1.4 重写rest api

1
2
3
4
5
6
7
8
9
10
11
12
@PostMapping(value = "write")
public void metrics(@RequestBody byte[] data) throws Exception {
byte[] compressed;
Remote.WriteRequest writeRequest=null;
try {
compressed = Snappy.uncompress(data);
writeRequest = Remote.WriteRequest.parseFrom(compressed);
log.debug("info from Prometheus:{}", writeRequest);
} catch (IOException e) {
log.error("receive msg from Prometheus error", e);
}
}

1.5 最后

至此,得出的writerequest 就是prometheus remote write 经处理后的数据。

2. prometheus 向influxdb存储数据

prometheus 大多与时序数据库一起结合使用,比较好的时序数据库有influxdb,OpenTSDB,Druid等等。
这里使用influxdb进行调研

influxdb 关于prometheus的支持

可以看到:influxdb 1.7+ 天然支持prometheus的remote read,以及remote write功能,也就是说,上文的java adapter是没有什么卵用的。。

不过至少了解了prometheus api的通信格式,也可以在以后进行脱离influxdb 的定制自开发。

本文采用CC-BY-SA-3.0协议,转载请注明出处
Author: dadonggua