DatadogのAutoDiscovery機能を使ってPrometheusのエンドポイントを叩いてメトリクスをDatadogに送る
DatadogのAutoDiscovery機能があるのを知ったので試してみたよ、という記事です。 今回は簡単に設定を試すために docker-composeを使って試してみました。
2022/09/29追記: 本記事の内容は少し古くなっています。 本記事では、Prometheusのインテグレーションを使っていますが、OpenMetricsというインテグレーションが別で存在していて この場合、本記事に記載した、extra_headersの設定なしで動くはずです。
はじめに
Spring BootのActuatorエンドポイントには Prometheus向けのフォーマットでメトリクスを公開してくれるエンドポイントがあります。 今回の記事では、Datadog AgentのAutoDiscovery機能を使って MicrometerのPrometheus向けのエンドポイントからメトリクスを取ってDatadogに連携してみる話です。
これは、micrometer-registry-prometheusを依存関係に加えた上で所定のactuatorの設定を追加すると有効になります。 細かい公開される仕様はリファレンスを読んでください。
Spring Boot Reference Documentation
フォーマットとしては以下のような形で公開してくれます。
$ curl localhost:8080/actuator/prometheus # HELP tomcat_servlet_error_total # TYPE tomcat_servlet_error_total counter tomcat_servlet_error_total{name="default",} 0.0 tomcat_servlet_error_total{name="dispatcherServlet",} 0.0 # HELP tomcat_threads_config_max_threads # TYPE tomcat_threads_config_max_threads gauge tomcat_threads_config_max_threads{name="http-nio-8080",} 200.0 # HELP jvm_threads_states_threads The current number of threads having NEW state # TYPE jvm_threads_states_threads gauge jvm_threads_states_threads{state="runnable",} 7.0 jvm_threads_states_threads{state="blocked",} 0.0 jvm_threads_states_threads{state="waiting",} 12.0 jvm_threads_states_threads{state="timed-waiting",} 4.0 jvm_threads_states_threads{state="new",} 0.0 jvm_threads_states_threads{state="terminated",} 0.0 # HELP tomcat_sessions_rejected_sessions_total # TYPE tomcat_sessions_rejected_sessions_total counter tomcat_sessions_rejected_sessions_total 0.0 # HELP system_cpu_count The number of processors available to the Java virtual machine # TYPE system_cpu_count gauge system_cpu_count 8.0 # HELP jvm_gc_memory_promoted_bytes_total Count of positive increases in the size of the old generation memory pool before GC to after GC # TYPE jvm_gc_memory_promoted_bytes_total counter
このようなテキストを本来はPrometheusがメトリクスにしてくれるのですが これをDatadog AgentのPrometheus Checkを使って、Datadogにメトリクスとして連携してみます。
Datadog AgentのAutoDiscovery機能とは
Datadog AgentのAutoDiscovery機能とは特定のコンテナにAgentからチェックをする際に コンテナの情報からチェックする内容を判断してくれます。
https://docs.datadoghq.com/ja/containers/kubernetes/integrations/
リファレンスによると、DockerのラベルやKubernetesのアノテーションなどからAutoDiscoveryが可能です。
というわけで、今回はローカルで試したいので、docker-composeを使って試します。 また、Discovery方法としてはDockerのラベルという機能を使います。 ドキュメントを見ながら書いてみたのが以下のようなdocker-compose.ymlです。 myappはSpring Bootのアプリケーションです。
version: '3.7' services: myapp: image: myapp ports: - "3001:3001" labels: com.datadoghq.ad.check_names: '["prometheus"]' com.datadoghq.ad.init_configs: '[{}]' com.datadoghq.ad.instances: '[{"prometheus_url": "http://%%host%%:3001/actuator/prometheus", "namespace": "local.test","metrics": ["jvm*"]}]' datadog: links: - myapp image: datadog/agent:latest environment: - DD_API_KEY=<REDACTED> - DD_TAGS="app:foo-bar-app env:foo-bar-environment" - DD_AC_EXCLUDE=".*" - DD_AC_INCLUDE="myapp:.*myapp" volumes: - /var/run/docker.sock:/var/run/docker.sock - /proc/:/host/proc/:ro - /sys/fs/cgroup:/host/sys/fs/cgroup:ro
ちなみに、これは動きません。(2019/12/09現在)
何がダメだったんでしょうか?
ダメだったところは?
以下のリンク先をみてもらうと分かるんですが、Datadog AgentはデフォルトのフォーマットとしてはProtocol Bufferです。 integrations-core/mixins.py at 3653923265d75d13c87b70d2010c06edcf89a8bb · DataDog/integrations-core · GitHub
そのため、Acceptヘッダに Protocol Bufferの類の設定をしていますが
Spring BootのActuatorのエンドポイントは text/plain
を期待しており、Spring Boot側でマッチするエンドポイントが見つからない、と言ってエラーになります。
Spring Boot側はこんな感じになっていて
text/plain; version=0.0.4; charset=utf-8
となっています。
- spring-boot/PrometheusScrapeEndpoint.java at v2.1.6.RELEASE · spring-projects/spring-boot · GitHub
- client_java/TextFormat.java at ef16c43f63128c14627eeff301a32c12e7751a4e · prometheus/client_java · GitHub
ちなみにProtocol Buffer形式でのメトリクスはPrometheusの2系からサポートしなくなっているようですね。
Exposition formats | Prometheus
じゃあどうすればいいか
Prometheus Checkの設定には extra_headers
の設定があります。
extra_headers
は datadog agentが prometheusのエンドポイントに対してアクセスする際に付与するヘッダです。
そこで、以下のように Accept
ヘッダに text/plain
を設定しましょう。
これで動きました。
version: '3.7' services: myapp: image: myapp ports: - "3001:3001" labels: com.datadoghq.ad.check_names: '["prometheus"]' com.datadoghq.ad.init_configs: '[{}]' com.datadoghq.ad.instances: '[{"prometheus_url": "http://%%host%%:3001/actuator/prometheus", "extra_headers": {"Accept": "text/plain"}, "namespace": "local.test","metrics": ["jvm*"]}]' datadog: links: - myapp image: datadog/agent:latest environment: - DD_API_KEY=<REDACTED> - DD_TAGS="app:foo-bar-app env:foo-bar-environment" - DD_AC_EXCLUDE=".*" - DD_AC_INCLUDE="myapp:.*myapp" volumes: - /var/run/docker.sock:/var/run/docker.sock - /proc/:/host/proc/:ro - /sys/fs/cgroup:/host/sys/fs/cgroup:ro
実際にDatadogに送られたメトリクスの様子です。
まとめ
今回は、DatadogのAutoDiscovery機能を使って、Datadog AgentからPrometheus向けにメトリクスを提供するエンドポイントから メトリクスを収集して、Datadogにメトリクスを送る方法を試しました。 一部ハマるところもありましたが、比較的簡単に試すことができました。
Datadog AgentのAutoDiscovery機能は設定をコンテナ側に持たすことができるため、非常に使いやすいです。 ECSのDAEMONでDatadogのAgentを立てた時とかに便利に使えるんじゃないかなと思っています。
今度はECSで試します。
終わり。