最近、prometheusを使い始めましたので、java(spring boot)でメトリクス収集のスタンダードとなりつつあるmicrometer.ioを調べてみました。
はじめに
micrometer.ioは、javaアプリの性能監視用メトリクスを収集して任意のモニタリングサービスと連携してくれるライブラリです。
prometheusやinfluxDBと連携してとっても簡単に性能モニタリングや性能監視ができます。
連携できるサービスは
Spring Boot Reference Guide
に記載されています。
micrometer.ioでは、
サーブレット周りのメトリクス(リクエスト数やレスポンスタイム、ステータスコードごとのレスポンス数)、WebFlux、datasource、schedulerなどなどのメトリクスが取得可能です。
spring bootでmicrometerを使う場合は、dependencyにmicrometerを追加するだけで、AutoConfigurationによって諸々Bean生成&AOPされ、コードを一切書かずにメトリクス収集できてしまいます。
使ってみた範囲では、サーブレット周りのメトリクスは、dependency追加だけで収集してくれました。
任意のメソッドの処理速度を測りたい場合は、アノテーション(たぶん@Timed)を付与するだけで取れちゃうそうです。
また、spring boot 2からは、micrometerがbootに統合され、bootでのメトリクス収集のデファクトになっています。
試してみた
各種ソフトウェアのバージョンなど
次のソフトウェアバージョンで試してみました。
- Java ... java1.8
- spring boot ... 1.5.10
- micrometer ... 1.0
- prometheus ... 2.2.0 rc1
また、お試し用に、簡単なRestサービスを作りサーブレットのメトリクスを取ってみました。
gradleやmaven のdependencyに以下を追加します。
- micrometer-spring-legacy
- spring boot 1.5ではmicrometerを引っ張る必要があります。2.0からは不要かな?
- micrometer-registry-prometheus
- prometheusと連携するために追加します。これと次のactuatorを組み合わせてprometheus用のエンドポイントが自動作成されます。
- spring-boot-starter-actuator
- prometheus用のエンドポイントはactuatorを利用します。
gradleだと以下のような設定になります。
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
compile('io.micrometer:micrometer-spring-legacy:latest.release')
compile('io.micrometer:micrometer-registry-prometheus:1.0.0')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
prometheusエンドポイントの認証設定 (actuatorの認証設定)
application.propertiesやymlで、prometheusエンドポイントの認証設定を行います。
デフォルトでは認証がかかっていますが、お試しなので、認証を解除しておきます。
actuatorを利用してprometheus用のエンドポイントが作られていますので、以下で認証を解除できます。
endpoints.prometheus.sensitive=false
以上の設定だけで、メトリクスが収集され、prometheus向けのエンドポイントができあがります。
エンドポイントは/prometheusです。
メトリクスを見てみる
ローカルでアプリを動かした場合は、localhost:8080/prometheusに接続するとprometheus向けのメトリクスが参照できます。
次のようなメトリクスが取れます。
サンプルとして、/demo/sleep(ランダムスリープするAPI)と/greeting(hello worldを返却するだけ)を作成しており、何回かアクセスした後に、メトリクスを参照しています。
http_server_requests_seconds_{count,max,sum}がHTTPリクエストのメトリクスです。
その他にもCPUやメモリ、Javaヒープのメトリクスなどなどがデフォルトで取得できます。
# HELP system_cpu_count The number of processors available to the Java virtual machine
# TYPE system_cpu_count gauge
system_cpu_count 4.0
# HELP tomcat_cache_access_total
# TYPE tomcat_cache_access_total counter
tomcat_cache_access_total 0.0
# HELP jvm_memory_max_bytes The maximum amount of memory in bytes that can be used for memory management
# TYPE jvm_memory_max_bytes gauge
jvm_memory_max_bytes{area="nonheap",id="Code Cache",} 2.5165824E8
jvm_memory_max_bytes{area="nonheap",id="Metaspace",} -1.0
jvm_memory_max_bytes{area="nonheap",id="Compressed Class Space",} 1.073741824E9
jvm_memory_max_bytes{area="heap",id="PS Eden Space",} 3.38690048E8
jvm_memory_max_bytes{area="heap",id="PS Survivor Space",} 9437184.0
jvm_memory_max_bytes{area="heap",id="PS Old Gen",} 7.16177408E8
# HELP jvm_threads_peak The peak live thread count since the Java virtual machine started or peak was reset
# TYPE jvm_threads_peak gauge
jvm_threads_peak 26.0
# HELP jvm_buffer_total_capacity_bytes An estimate of the total capacity of the buffers in this pool
# TYPE jvm_buffer_total_capacity_bytes gauge
jvm_buffer_total_capacity_bytes{id="direct",} 81920.0
jvm_buffer_total_capacity_bytes{id="mapped",} 0.0
# HELP tomcat_cache_hit_total
# TYPE tomcat_cache_hit_total counter
tomcat_cache_hit_total 0.0
# HELP jvm_gc_memory_allocated_bytes_total Incremented for an increase in the size of the young generation memory pool after one GC to before the next
# TYPE jvm_gc_memory_allocated_bytes_total counter
jvm_gc_memory_allocated_bytes_total 2.96805056E8
# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="nonheap",id="Code Cache",} 1.3597504E7
jvm_memory_used_bytes{area="nonheap",id="Metaspace",} 3.5858104E7
jvm_memory_used_bytes{area="nonheap",id="Compressed Class Space",} 4497880.0
jvm_memory_used_bytes{area="heap",id="PS Eden Space",} 1.2576784E7
jvm_memory_used_bytes{area="heap",id="PS Survivor Space",} 0.0
jvm_memory_used_bytes{area="heap",id="PS Old Gen",} 2.0745336E7
# HELP jvm_classes_loaded The number of classes that are currently loaded in the Java virtual machine
# TYPE jvm_classes_loaded gauge
jvm_classes_loaded 6636.0
# HELP jvm_buffer_count An estimate of the number of buffers in the pool
# TYPE jvm_buffer_count gauge
jvm_buffer_count{id="direct",} 10.0
jvm_buffer_count{id="mapped",} 0.0
# HELP tomcat_global_sent_bytes_total
# TYPE tomcat_global_sent_bytes_total counter
tomcat_global_sent_bytes_total{name="http-nio-8080",} 21404.0
# HELP tomcat_threads_current
# TYPE tomcat_threads_current gauge
tomcat_threads_current{name="http-nio-8080",} 10.0
# HELP jvm_threads_live The current number of live threads including both daemon and non-daemon threads
# TYPE jvm_threads_live gauge
jvm_threads_live 24.0
# HELP tomcat_global_request_seconds
# TYPE tomcat_global_request_seconds summary
tomcat_global_request_seconds_count{name="http-nio-8080",} 15.0
tomcat_global_request_seconds_sum{name="http-nio-8080",} 3.532
# HELP tomcat_threads_busy
# TYPE tomcat_threads_busy gauge
tomcat_threads_busy{name="http-nio-8080",} 1.0
# HELP process_files_open The open file descriptor count
# TYPE process_files_open gauge
process_files_open 98.0
# HELP tomcat_global_received_bytes_total
# TYPE tomcat_global_received_bytes_total counter
tomcat_global_received_bytes_total{name="http-nio-8080",} 0.0
# HELP jvm_gc_max_data_size_bytes Max size of old generation memory pool
# TYPE jvm_gc_max_data_size_bytes gauge
jvm_gc_max_data_size_bytes 7.16177408E8
# 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
jvm_gc_memory_promoted_bytes_total 1.4576224E7
# HELP tomcat_servlet_request_max_seconds
# TYPE tomcat_servlet_request_max_seconds gauge
tomcat_servlet_request_max_seconds{name="default",} 0.0
# HELP system_load_average_1m The sum of the number of runnable entities queued to available processors and the number of runnable entities running on the available processors averaged over a period of time
# TYPE system_load_average_1m gauge
system_load_average_1m 3.58740234375
# HELP process_files_max The maximum file descriptor count
# TYPE process_files_max gauge
process_files_max 10240.0
# HELP logback_events_total Number of error level events that made it to the logs
# TYPE logback_events_total counter
logback_events_total{level="error",} 0.0
logback_events_total{level="warn",} 0.0
logback_events_total{level="info",} 56.0
logback_events_total{level="debug",} 0.0
logback_events_total{level="trace",} 0.0
# HELP process_uptime_seconds The uptime of the Java virtual machine
# TYPE process_uptime_seconds gauge
process_uptime_seconds 354.935
# HELP tomcat_servlet_request_seconds
# TYPE tomcat_servlet_request_seconds summary
tomcat_servlet_request_seconds_count{name="default",} 0.0
tomcat_servlet_request_seconds_sum{name="default",} 0.0
# HELP system_cpu_usage The "recent cpu usage" for the whole system
# TYPE system_cpu_usage gauge
system_cpu_usage 0.15862260998700575
# HELP jvm_gc_pause_seconds Time spent in GC pause
# TYPE jvm_gc_pause_seconds summary
jvm_gc_pause_seconds_count{action="end of minor GC",cause="Allocation Failure",} 2.0
jvm_gc_pause_seconds_sum{action="end of minor GC",cause="Allocation Failure",} 0.057
jvm_gc_pause_seconds_max{action="end of minor GC",cause="Allocation Failure",} 0.0
jvm_gc_pause_seconds_count{action="end of minor GC",cause="Metadata GC Threshold",} 1.0
jvm_gc_pause_seconds_sum{action="end of minor GC",cause="Metadata GC Threshold",} 0.056
jvm_gc_pause_seconds_max{action="end of minor GC",cause="Metadata GC Threshold",} 0.056
jvm_gc_pause_seconds_count{action="end of major GC",cause="Metadata GC Threshold",} 1.0
jvm_gc_pause_seconds_sum{action="end of major GC",cause="Metadata GC Threshold",} 0.186
jvm_gc_pause_seconds_max{action="end of major GC",cause="Metadata GC Threshold",} 0.186
# HELP jvm_buffer_memory_used_bytes An estimate of the memory that the Java virtual machine is using for this buffer pool
# TYPE jvm_buffer_memory_used_bytes gauge
jvm_buffer_memory_used_bytes{id="direct",} 81920.0
jvm_buffer_memory_used_bytes{id="mapped",} 0.0
# HELP tomcat_servlet_error_total
# TYPE tomcat_servlet_error_total counter
tomcat_servlet_error_total{name="default",} 0.0
# HELP http_server_requests_seconds
# TYPE http_server_requests_seconds summary
http_server_requests_seconds_count{exception="None",method="GET",status="200",uri="/prometheus",} 2.0
http_server_requests_seconds_sum{exception="None",method="GET",status="200",uri="/prometheus",} 0.253484348
http_server_requests_seconds_max{exception="None",method="GET",status="200",uri="/prometheus",} 0.237163955
http_server_requests_seconds_count{exception="None",method="GET",status="200",uri="/**/favicon.ico",} 6.0
http_server_requests_seconds_sum{exception="None",method="GET",status="200",uri="/**/favicon.ico",} 0.310324459
http_server_requests_seconds_max{exception="None",method="GET",status="200",uri="/**/favicon.ico",} 0.284490161
http_server_requests_seconds_count{exception="None",method="GET",status="200",uri="/demo/sleep",} 4.0
http_server_requests_seconds_sum{exception="None",method="GET",status="200",uri="/demo/sleep",} 2.649034912
http_server_requests_seconds_max{exception="None",method="GET",status="200",uri="/demo/sleep",} 0.819051821
http_server_requests_seconds_count{exception="None",method="GET",status="200",uri="/demo/greeting",} 3.0
http_server_requests_seconds_sum{exception="None",method="GET",status="200",uri="/demo/greeting",} 0.029463802
http_server_requests_seconds_max{exception="None",method="GET",status="200",uri="/demo/greeting",} 0.016638298
# HELP process_start_time_seconds The start time of the Java virtual machine
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.519658903528E9
# HELP jvm_threads_daemon The current number of live daemon threads
# TYPE jvm_threads_daemon gauge
jvm_threads_daemon 22.0
# HELP tomcat_global_request_max_seconds
# TYPE tomcat_global_request_max_seconds gauge
tomcat_global_request_max_seconds{name="http-nio-8080",} 0.826
# HELP jvm_memory_committed_bytes The amount of memory in bytes that is committed for the Java virtual machine to use
# TYPE jvm_memory_committed_bytes gauge
jvm_memory_committed_bytes{area="nonheap",id="Code Cache",} 1.3697024E7
jvm_memory_committed_bytes{area="nonheap",id="Metaspace",} 3.6872192E7
jvm_memory_committed_bytes{area="nonheap",id="Compressed Class Space",} 4718592.0
jvm_memory_committed_bytes{area="heap",id="PS Eden Space",} 1.16391936E8
jvm_memory_committed_bytes{area="heap",id="PS Survivor Space",} 9437184.0
jvm_memory_committed_bytes{area="heap",id="PS Old Gen",} 5.8720256E7
# HELP process_cpu_usage The "recent cpu usage" for the Java Virtual Machine process
# TYPE process_cpu_usage gauge
process_cpu_usage 0.04120401140398954
# HELP tomcat_global_error_total
# TYPE tomcat_global_error_total counter
tomcat_global_error_total{name="http-nio-8080",} 0.0
# HELP tomcat_threads_config_max
# TYPE tomcat_threads_config_max gauge
tomcat_threads_config_max{name="http-nio-8080",} 200.0
# HELP jvm_gc_live_data_size_bytes Size of old generation memory pool after a full GC
# TYPE jvm_gc_live_data_size_bytes gauge
jvm_gc_live_data_size_bytes 2.0745336E7
# HELP jvm_classes_unloaded_total The total number of classes unloaded since the Java virtual machine has started execution
# TYPE jvm_classes_unloaded_total counter
jvm_classes_unloaded_total 1.0
prometheusの設定
prometheusで、監視対象として作成したエンドポイント(/prometheus)を追加します。
設定ファイル(prometheus.yml)で以下のような設定を追加すれば完了です。
scrape_configs:
- job_name: 'spring'
metrics_path: '/prometheus'
scrape_interval: 30s
static_configs:
- targets: ['localhost:8080']
まとめ
spring boot とmicrometerを組み合わせることで、dependencyの追加と、application.properties/yml の設定だけでコードは一切書かずにメトリクスを取れてしまいます。
めちゃめちゃ簡単です。
micrometer以外では、prometheusオフィシャルのsimpleclientでもうちょっと違うメトリクスが取得できます。用途に合わせてsimpleclientと組み合わせたりして使うとよいとおもいます。
prometheusにはzipkinプラグインがありますので、これも調べたいと思います。
また、WebFluxのメトリクス取得や、scheduler, datasourceのメトリクスがどんなものが取得できるのかも試したいですね。
今回試したサンプルアプリはgithubに登録してあります。
GitHub - ikeda-mk/prometheus-micrometer-demo