datadog 监控 JVM 或者基于 JVM 的应用的方式

  • datadog 监控 java 应用主要通过采集 JMX 指标:https://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#local
  • 原理:datadog 调用一个名为 JMXFetch 的轻量级 java 插件连接 MBean server,从而获取到这些指标。这个插件通过运行在 agent 上的 Dogstatsd Server 将采集到的指标数据发送到 datadog agent。
  • 这种方式同样在以下监控中得以应用,ActiveMQ, Cassandra, Solr, and Tomcat,可以看得出,这些应用都基于 jmx 来注册自定义的应用状态数据。

jmx 监控的典型配置

如下是一个完整的配置文件内容

  1. bean 的一个 attribute 对应到 datadog 的监控体系里,就是一个 metric
  2. 如果这个 attribute 的类型不是 simple 的,而是 Composite(本质上是一个 hashmap),那么这个 attribute 的每一个 key 对应的才是 metric,在下面的配置中,”java.lang:type=MemoryPool,name=PS Old Gen” 这个 bean 的 Usage 就是一个 Composite 类型的数据
instances:
  - host: localhost
    port: 9999
    tools_jar_path: /usr/java/jdk1.7.0_65/lib/tools.jar
init_config:
  conf:
  - include:
      domain: "java.lang"
      bean: "java.lang:type=MemoryPool,name=PS Old Gen"
      attribute:
        Usage.max:
          alias: "jvm.memory.pools.ps_old_gen.max"
          metric_type: "gauge"
        Usage.used:
          alias: "jvm.memory.pools.ps_old_gen.used"
          metric_type: "gauge"
        Usage.committed:
          alias: "jvm.memory.pools.ps_old_gen.committed"
          metric_type: "gauge"
        Usage.init:
          alias: "jvm.memory.pools.ps_old_gen.init"
          metric_type: "gauge"

这里要特别注意的是对于 ActiveMQ, Cassandra, Solr, and Tomcat 这几种集成监控的配置文件也可以通过JMX的配置语法来扩展。

如何查询注册到 JMX 的 bean

1. 查询当前 jmx 有哪些 bean

/etc/init.d/datadog-agent jmx list_everything

2. 查询某个 bean 的复合类型 attribute 的 key

这里只能通过 jmxterm-1.0-DATADOG-uber.jar来查询:https://docs.datadoghq.com/integrations/faq/collecting-composite-type-jmx-attributes/

下面列出了 jmxterm 的命令行调用及结果,通常的过程是

  1. 先通过 beans 命令查询到有哪些 bean
  2. 再通过 info 命令查询该 bean 有哪些 attribute
  3. 最后通过 get 命令查询某个复合类型的 attribute 有哪些 key
java -jar /opt/datadog-agent/agent/checks/libs/jmxterm-1.0-DATADOG-uber.jar -l localhost:9999

$>beans -b java.lang:name=PS Old Gen,type=MemoryPool
#domain = java.lang:
java.lang:name=Code Cache,type=MemoryPool
java.lang:name=CodeCacheManager,type=MemoryManager
java.lang:name=PS Eden Space,type=MemoryPool
java.lang:name=PS MarkSweep,type=GarbageCollector
java.lang:name=PS Old Gen,type=MemoryPool
java.lang:name=PS Perm Gen,type=MemoryPool
java.lang:name=PS Scavenge,type=GarbageCollector
java.lang:name=PS Survivor Space,type=MemoryPool
java.lang:type=ClassLoading
java.lang:type=Compilation
java.lang:type=Memory
java.lang:type=OperatingSystem
java.lang:type=Runtime
java.lang:type=Threading

$>info -b java.lang:name=PS\ Old\ Gen,type=MemoryPool
#mbean = java.lang:name=PS Old Gen,type=MemoryPool
#class name = sun.management.MemoryPoolImpl
# attributes
  %0   - CollectionUsage (javax.management.openmbean.CompositeData, r)
  %1   - CollectionUsageThreshold (long, rw)
  %2   - CollectionUsageThresholdCount (long, r)
  %3   - CollectionUsageThresholdExceeded (boolean, r)
  %4   - CollectionUsageThresholdSupported (boolean, r)
  %5   - MemoryManagerNames ([Ljava.lang.String;, r)
  %6   - Name (java.lang.String, r)
  %7   - ObjectName (javax.management.ObjectName, r)
  %8   - PeakUsage (javax.management.openmbean.CompositeData, r)
  %9   - Type (java.lang.String, r)
  %10  - Usage (javax.management.openmbean.CompositeData, r)
  %11  - UsageThreshold (long, rw)
  %12  - UsageThresholdCount (long, r)
  %13  - UsageThresholdExceeded (boolean, r)
  %14  - UsageThresholdSupported (boolean, r)
  %15  - Valid (boolean, r)
# operations
  %0   - void resetPeakUsage()
#there's no notifications

get -b java.lang:name=PS\ Old\ Gen,type=MemoryPool Usage
#mbean = java.lang:name=PS Old Gen,type=MemoryPool:
Usage = {
  committed = 716177408;
  init = 716177408;
  max = 716177408;
  used = 410159232;
 };

参考