prometheus jmx_exporter 用于将jmx bean的信息转为prometheus exports 模式。
一共有4个子项目
使用pattern 解析输出参数,pattern后续还有大量使用。
Pattern pattern = Pattern.compile(
"^(?:((?:[\\w.]+)|(?:\\[.+])):)?" + // host name, or ipv4, or ipv6 address in brackets
"(\\d{1,5}):" + // port
"(.+)"); // config file
Matcher matcher = pattern.matcher(args);
if (!matcher.matches()) {
throw new IllegalArgumentException("Malformed arguments - " + args);
}
String givenHost = matcher.group(1);
String givenPort = matcher.group(2);
String givenConfigFile = matcher.group(3);
可以参数就是以:分割的
核心代码其实就以下三行:
new JmxCollector(new File(config.file)).register();
DefaultExports.initialize();
server = new HTTPServer(config.socket, CollectorRegistry.defaultRegistry, true);
jmx_prometheus_httpserver 代码和java agent 基本一致,主要差异只有2点
以下是一个非SSL连接的配置示意
hostPort: 192.168.157.130:9099
username: admin
password: "123456"
ssl: false
Collector 一共4个类,关键的是
先看JmxScraper,JmxScraper负责读取所有mbean的信息并转换为JmxCollector需要的格式,主要方法
if (jmxUrl.isEmpty()) {
beanConn = ManagementFactory.getPlatformMBeanServer();
} else {
Map<String, Object> environment = new HashMap<String, Object>();
if (username != null && username.length() != 0 && password != null && password.length() != 0) {
String[] credent = new String[] {username, password};
environment.put(javax.management.remote.JMXConnector.CREDENTIALS, credent);
}
if (ssl) {
environment.put(Context.SECURITY_PROTOCOL, "ssl");
SslRMIClientSocketFactory clientSocketFactory = new SslRMIClientSocketFactory();
environment.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, clientSocketFactory);
environment.put("com.sun.jndi.rmi.factory.socket", clientSocketFactory);
}
jmxc = JMXConnectorFactory.connect(new JMXServiceURL(jmxUrl), environment);
beanConn = jmxc.getMBeanServerConnection();
}
jmxUrl.isEmpty() 即为Agent 模式。
public class JmxCollector 的主要函数如下
recordBean的匹配是逐个rule进行尝试
Matcher matcher = null;
String matchName = beanName + (rule.attrNameSnakeCase ? attrNameSnakeCase : attrName);
if (rule.pattern != null) {
matcher = rule.pattern.matcher(matchName + ": " + beanValue);
if (!matcher.matches()) {
continue;
}
}
注意下rule的pattern加了固定前后缀
if (yamlRule.containsKey("pattern")) {
rule.pattern = Pattern.compile("^.*(?:" + (String)yamlRule.get("pattern") + ").*$");
}
可以看到使用matcher的replaceAll,比如:
String name = safeName(matcher.replaceAll(rule.name));
查看配置yaml,很多如下信息:
- pattern: "org.apache.ZooKeeperService<>(\\w+)"
name: "zookeeper_$4_$5"
labels:
replicaId: "$2"
memberType: "$3"
这里的$2-$5其实是对应 \d+ 及\w+的内容,按次序来,即
最后注意pattern后面统一加了").*$",这个就是value。
最后补充一个jvm thread 转换示意
---
hostPort: 192.168.157.130:9099
username: admin
password: "123456"
ssl: false
rules:
# standalone Zookeeper
- pattern: "org.apache.ZooKeeperService<>(\\w+)"
name: "zookeeper_$2"
# jvm thread
- pattern: "java.lang<>(\\w+)"
name: "java.Threading_$1"