DataDog 用の jolokia AgentCheck書いてみた

記事名のとおりなんですが、AgentCheck用のインストール方法とか特に無くてファイルを置くだけっぽいので、 gist にあげておきます。コードが酷かったり、項目増やせなかったりするのは今後の課題。

gist.github.com

モチベーションとか

そもそもの話、JVMの監視をするときには極々単純に以下の項目を監視したいわけです。

  • JVM内のメモリの状態
  • GCの状態

また、メモリの状態と言ってもJVMって Heap/NonHeap みたいな単純なものではありません。EdenとかSurvivorとかOldとかがあります。 (※G1GCではちょっと違う)

GCも、 Java8 のデフォルトでは ParallelGC Java9ではG1GCだったりで、見なければいけない項目も少しずつ違います。

JVMのメモリについては、詳しくはこちらの方のブログが分かりやすかったので、是非参照してください。

blog.pepese.com

それなのに、監視サービスの某鯖とか某犬とかのJVM監視の項目を見ると、全然足りないんですよ。

mackerel-agent-plugins/mackerel-plugin-jmx-jolokia at master · mackerelio/mackerel-agent-plugins · GitHub

Datadog-Java/JMX Integration

鯖の方は、jstatで監視するなら十二分に満たしているんですが。

mackerel-agent-plugins/mackerel-plugin-jvm at master · mackerelio/mackerel-agent-plugins · GitHub

Jolokia(JMX)で監視する際には、鯖の方も項目を増やすプラグインを書いてみたりとかしています。

github.com

本題に戻って、DataDogのJmx監視のためのプロセスなんですが、JolokiaではなくてJmxFetchといって、JMX取得のためのJavaプロセスを内部で動かす方式となっています。 これが、dd-agentをDockerで動かして、AutoDiscoverを前提にすると Xmx512M 固定で起動します。公式のDockerのメモリ推奨量が256MBなのに。

https://github.com/DataDog/dd-agent/blob/5cad70dd33b58716ed102070c95edbd557bf3816/jmxfetch.py#L48

_JVM_DEFAULT_SD_MAX_MEMORY_ALLOCATION = " -Xmx512m"

コード見つつ動かしながら挙動調べた感じ、AutoDiscoverじゃなくて監視用のファイルを置いた場合にはプロセスのメモリ使用量を変更できそうでしたが、それだとAWSのECSとかでなんのタスクが動くかわからないものに対しては使えそうにありません。

そもそも、監視のプロセスだけで512MBも必要とか尋常じゃないです。AWSのECS上のTaskとして動かした場合、t2.small なんて1GBしかないんだから、残りの使えるメモリがもう半分以下しかないです。

サポートとかに聞いてもAutoDiscoverとかDocker上のdd-agentとかあんまり考慮されていなさそうだったのと、Docker起動時に外部の環境変数から変更できそうな感じじゃなかったので、Jolokiaで監視すればいいんじゃないかなと思い立った次第。

で、探したけどJolokiaようのAgentCheckスクリプトが見つからなかったので作ったのが冒頭のスクリプトになります。

使い方とか

dd-agentをDockerで動かしているので、Dockerfile置いておきます。 サーバー上で普通に動かしているのであれば、 check.d ディレクトリにファイルを置くだけでいいはずです。

FROM datadog/docker-dd-agent:latest

ADD jolokia.py /opt/datadog-agent/agent/checks.d/jolokia.py

buildして、

docker build -t dd-agent-jolokia .

dd-agentを起動(MacOSの場合。cgroupを通して監視するので、詳細は以下のリンクを参照)

docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /proc:/host/proc:ro \
-v /sys/fs/cgroup:/host/sys/fs/cgroup:ro \
-e API_KEY=<API_KEY> \
-e SD_BACKEND=docker \
-e DD_LOGS_STDOUT=yes \
dd-agent-jolokia

https://hub.docker.com/r/datadog/docker-dd-agent/

監視対象のDockerはラベルを付けて起動 JavaagentでJolokiaを指定してポートを開けるようにすること。

docker run -d \
-p 13333 \
-l com.datadoghq.ad.check_names='["jolokia"]' \
-l com.datadoghq.ad.init_configs='[{}]' \
-l com.datadoghq.ad.instances='[{"host": "%%host%%", "port": "%%port%%" }]' \
jvm_application -javaagent /paht/to/jolokia-jvm-agent.jar,port=13333,host=0.0.0.0

起動したDockerContainerの監視はLabelをつければ自動で監視対象に追加してくれる仕組み。このあたり、DataDogの仕組みは素晴らしいですね。

docs.datadoghq.com

ParallelGCの場合、監視項目はこれだけ増えます。 MemoryPoolから動的に項目取得してくるので、GCの種別を変えれば項目も変わります。

jolokia.class_load.loaded
jolokia.class_load.total
jolokia.class_load.unloaded
jolokia.gc.count
jolokia.gc.time
jolokia.memory.code_cache.committed
jolokia.memory.code_cache.init
jolokia.memory.code_cache.max
jolokia.memory.code_cache.used
jolokia.memory.compressed_class_space.committed
jolokia.memory.compressed_class_space.init
jolokia.memory.compressed_class_space.max
jolokia.memory.compressed_class_space.used
jolokia.memory.heap.committed
jolokia.memory.heap.init
jolokia.memory.heap.max
jolokia.memory.heap.used
jolokia.memory.metaspace.committed
jolokia.memory.metaspace.init
jolokia.memory.metaspace.max
jolokia.memory.metaspace.used
jolokia.memory.non_heap.committed
jolokia.memory.non_heap.init
jolokia.memory.non_heap.max
jolokia.memory.non_heap.used
jolokia.memory.ps_eden_space.committed
jolokia.memory.ps_eden_space.init
jolokia.memory.ps_eden_space.max
jolokia.memory.ps_eden_space.used
jolokia.memory.ps_old_gen.committed
jolokia.memory.ps_old_gen.init
jolokia.memory.ps_old_gen.max
jolokia.memory.ps_old_gen.used
jolokia.memory.ps_survivor_space.committed
jolokia.memory.ps_survivor_space.init
jolokia.memory.ps_survivor_space.max
jolokia.memory.ps_survivor_space.used
jolokia.thread.count

雑感

勢い余って書いてしまったけど、本当に他に困っている人いないのかどうか・・・ みんなそこまでJVM内の項目気にしていないのかなぁ。 あと、いくらなんでも雑に書きすぎたかもしれない。