prometheus jmx_exporter 源码分析

prometheus jmx_exporter 用于将jmx bean的信息转为prometheus exports 模式。

一共有4个子项目

  • collector ,核心代码,负责收集和scrap 数据并输出
  • example_configs 各类应用配置示意
  • jmx_prometheus_httpserver http server模式,这种模式需要应用启动jmx
  • jmx_prometheus_javaagent 使用java agent模式启动

java agent 源码

使用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);
  • 注册JmxCollector
  • 启动默认的Hostspot jvm exporter注意httpserver 没有这个
  • 启动prometheus java 提供的io.prometheus.client.exporter 里httpServer。

jmx_prometheus_httpserver 源码

jmx_prometheus_httpserver 代码和java agent 基本一致,主要差异只有2点

  • 由于不是同一jvm,所有没有DefaultExports.initialize(); 但其实也可以通过mbean 加yml配置获取到相关信息并export
  • 连接 jmx信息配置在yml里面,这些信息读取在collector 项目中

以下是一个非SSL连接的配置示意

hostPort: 192.168.157.130:9099
username: admin 
password: "123456"
ssl: false

Collector 源码

Collector 一共4个类,关键的是

  • public class JmxCollector
  • class JmxScraper

先看JmxScraper,JmxScraper负责读取所有mbean的信息并转换为JmxCollector需要的格式,主要方法

  • public void doScrape() 负责创建jmx conn并取得mbean 列表
  • private void scrapeBean(MBeanServerConnection
    beanConn, ObjectName mbeanName) :处理单个mbean数据
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 的主要函数如下

  • private Config loadConfig(Map yamlConfig) 装载yaml文件,对yaml配置项不清楚可以看此函数
  • private void reloadConfig() 重新加载config,在prometheus 进行scrap,list前被调用
  • static String safeName(String name) ,将不符合prometheus的字符转为为"_"
  • public void recordBean, 负责分析JmxScraper的scrapeBean,和yaml配置的rule进行匹配,转为prometheus sample输出

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+的内容,按次序来,即

  • replicaId: “$2” 将被替换为replica.(\d+) 对应信息
  • zookeeper_$4_$5 间使用name3=(\w+)><>(\w+)"的两个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"

你可能感兴趣的:(java,架构)