これは、なにをしたくて書いたもの?
Spring Bootには、Spring Boot ActuatorおよびMicrometerを使うことでメトリクスをモニタリングシステムで収集することが
できます。
ここで、収集先のモニタリングシステムがない場合にログ出力でもできないかな?と思って調べてみたら、Micrometerの
LoggingMeterRegistry
を使えばできそうだったので、試してみました。
Spring Boot ActuatorとMicromter
先に、Spring Boot ActuatとMicrometerについて少し書いておきましょう。
Spring Boot Actuatorは、プロダクション環境でアプリケーションをモニタリング、管理するための機能を提供するものです。
Spring Boot Actuator: Production-ready Features
Spring Boot Actuatorは、spring-boot-starter-actuator
を依存関係に含めることで有効になります。
このうちメトリクスに関する機能は、Micrometerを統合することで実現しています。
Micrometer Application Monitoring
Datadog、New Relic、Elasticsearchなど、いろいろなモニタリングシステムにメトリクスを送信できたりします。
利用するには、対象のモニタリングシステムに関するmicrometer-registry-xxxxx
を依存関係に加え、設定を行えばOKです。
LoggingMeterRegistry
モニタリングシステムがない場合に、簡単に動作確認する方法はないかな?と思ったのですが。
Micrometerのメトリクス登録先であるMeterRegistry
の実装として
MeterRegistry (micrometer-core 1.6.6 API)
メトリクスをログ出力するLoggingMeterRegistry
というものがあったので、こちらを使ってみましょうというのが
今回のお題です。
LoggingMeterRegistry (micrometer-core 1.6.6 API)
Spring Bootの場合、Spring Boot Actuatorを有効(spring-boot-starter-actuator
を依存関係に含める)うえで、
LoggingMeterRegistry
をBean登録すればそれだけで使えます。
@Bean public MeterRegistry meterRegistry() { return new LoggingMeterRegistry(); }
ログの出力先ですが、デフォルトではSLF4Jが利用できる場合はSLF4Jへ、そうでない場合はJava標準のロガー(j.u.l.Logger)に
渡されます。
メトリクスは定期的に出力されますが、デフォルトだと1分間隔です。
このあたりは、設定することもできます。
LoggingRegistryConfig (micrometer-core 1.6.6 API)
お題
Spring Boot Actuatorを有効にした、簡単なCommandLineRunner
で一定時間動き続けるアプリケーションを作成します。
この時、メトリクスをログ出力します。
あと、追加のメトリクスがなにもないのもなんなので、キャッシュを有効にしてそちらも加えましょう。
環境
今回の環境は、こちらです。
今回は
$ java --version openjdk 11.0.11 2021-04-20 OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04) OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing) $ mvn --version Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 11.0.11, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-72-generic", arch: "amd64", family: "unix"
Spring Bootは2.4.5、Spring Frameworkは5.3.6、Micrometerは1.6.6を使用します。
プロジェクトの作成
依存関係にactuator
とcache
を加えて、Spring Bootプロジェクトを作成。
$ curl -s https://start.spring.io/starter.tgz \ -d bootVersion=2.4.5 \ -d javaVersion=11 \ -d name=metrics-logging \ -d groupId=org.littlewings \ -d artifactId=metrics-logging \ -d version=0.0.1-SNAPSHOT \ -d packageName=org.littlewings.spring.metrics \ -d dependencies=actuator,cache \ -d baseDir=metrics-logging | tar zxvf - $ cd metrics-logging
キャッシュはCaffeineを使うことにしましょう。依存関係に追加しておきます。
<properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
あと、生成されたクラスは使わないので削除しておきます…。
アプリケーションを作成する
それでは、アプリケーションを作成します。
キャッシュも使うので、まずは設定ファイルから。
src/main/resources/application.properties
spring.cache.cache-names=caffeineCache spring.cache.caffeine.spec=maximumSize=100,recordStats
Caffeineを使ってメトリクスを収集しようと思った場合、recordStats
を有効にしておく必要があります。
キャッシュヒットしなかった場合は、スリープするクラスを作成。
src/main/java/org/littlewings/spring/metrics/MessageService.java
package org.littlewings.spring.metrics; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class MessageService { Logger logger = LoggerFactory.getLogger(MessageService.class); @Cacheable("caffeineCache") public String message(int num) { try { logger.info("sleeping..."); TimeUnit.SECONDS.sleep(5L); } catch (InterruptedException e) { // ignore } return String.format("Hello %d", num); } }
利用+起動クラス側。
src/main/java/org/littlewings/spring/metrics/App.java
package org.littlewings.spring.metrics; import java.sql.Time; import java.time.Duration; import java.util.Random; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class App implements CommandLineRunner { Logger logger = LoggerFactory.getLogger(App.class); MessageService messageService; public static void main(String[] args) { SpringApplication.run(App.class, args); } public App(MessageService messageService) { this.messageService = messageService; } @Override public void run(String... args) throws Exception { Duration limit = Duration.ofMinutes(2L); long startTime = System.currentTimeMillis(); long elapsedTime = System.currentTimeMillis() - startTime; int randomLimit = 50; Random random = new Random(); random.nextInt(randomLimit); logger.info("start"); while (Duration.ofMillis(elapsedTime).minus(limit).isNegative()) { logger.info("get message = {}", messageService.message(random.nextInt(randomLimit))); TimeUnit.SECONDS.sleep(1L); elapsedTime = System.currentTimeMillis() - startTime; } logger.info("end"); } }
先ほど作成したクラスを、Random
を使って2分間適当に呼び出します。
ランダムでキャッシュにヒットするだろう、と。
あとは、LoggingMeterRegistry
をBeanとして登録して完了です。
src/main/java/org/littlewings/spring/metrics/MetricsConfig.java
package org.littlewings.spring.metrics; import java.time.Duration; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.logging.LoggingMeterRegistry; import io.micrometer.core.instrument.logging.LoggingRegistryConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MetricsConfig { @Bean public MeterRegistry meterRegistry() { return new LoggingMeterRegistry(); } }
パッケージングして
$ mvn package
実行。
$ java -jar target/metrics-logging-0.0.1-SNAPSHOT.jar
起動後、こんな感じで動いていきますが
2021-05-03 22:30:16.479 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : start 2021-05-03 22:30:16.509 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:21.515 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 13 2021-05-03 22:30:22.519 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:27.520 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 32 2021-05-03 22:30:28.521 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:33.522 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 4 2021-05-03 22:30:34.523 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:39.524 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 9 2021-05-03 22:30:40.525 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:45.526 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 42 2021-05-03 22:30:46.529 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 9 2021-05-03 22:30:47.530 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:52.531 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 29 2021-05-03 22:30:53.531 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping... 2021-05-03 22:30:58.533 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 34 2021-05-03 22:30:59.534 INFO 43396 --- [ main] o.l.spring.metrics.MessageService : sleeping...
1分経過すると、メトリクスがログ出力されます。
2021-05-03 22:31:16.207 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=hit} throughput=0.016667/s 2021-05-03 22:31:16.207 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=miss} throughput=0.166667/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.memory.allocated{} throughput=2.45 MiB/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.memory.promoted{} throughput=9.022396 KiB/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : logback.events{level=info} throughput=0.433333 events/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : cache.size{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache} value=9 2021-05-03 22:31:16.209 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.count{id=mapped} value=0 buffers 2021-05-03 22:31:16.209 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.count{id=direct} value=1 buffers 2021-05-03 22:31:16.209 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.memory.used{id=direct} value=8 KiB 2021-05-03 22:31:16.209 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.memory.used{id=mapped} value=0 B 2021-05-03 22:31:16.209 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.total.capacity{id=direct} value=8 KiB 2021-05-03 22:31:16.209 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.total.capacity{id=mapped} value=0 B 2021-05-03 22:31:16.210 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.classes.loaded{} value=4808 classes 2021-05-03 22:31:16.210 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.live.data.size{} value=0 B 2021-05-03 22:31:16.210 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.max.data.size{} value=3.888672 GiB 2021-05-03 22:31:16.210 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=heap,id=G1 Old Gen} value=94 MiB 2021-05-03 22:31:16.210 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=heap,id=G1 Eden Space} value=151 MiB 2021-05-03 22:31:16.211 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=Compressed Class Space} value=2.75 MiB 2021-05-03 22:31:16.211 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=CodeHeap 'profiled nmethods'} value=6.875 MiB 2021-05-03 22:31:16.211 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=CodeHeap 'non-nmethods'} value=2.4375 MiB 2021-05-03 22:31:16.211 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=heap,id=G1 Survivor Space} value=7 MiB 2021-05-03 22:31:16.211 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=Metaspace} value=19.5 MiB 2021-05-03 22:31:16.211 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=CodeHeap 'non-profiled nmethods'} value=2.4375 MiB 2021-05-03 22:31:16.212 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=heap,id=G1 Eden Space} value=-1 B 2021-05-03 22:31:16.212 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=CodeHeap 'profiled nmethods'} value=117.214844 MiB 2021-05-03 22:31:16.212 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=Compressed Class Space} value=1 GiB 2021-05-03 22:31:16.212 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=CodeHeap 'non-profiled nmethods'} value=117.21875 MiB 2021-05-03 22:31:16.212 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=heap,id=G1 Old Gen} value=3.888672 GiB 2021-05-03 22:31:16.213 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=CodeHeap 'non-nmethods'} value=5.566406 MiB 2021-05-03 22:31:16.213 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=Metaspace} value=-1 B 2021-05-03 22:31:16.213 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=heap,id=G1 Survivor Space} value=-1 B 2021-05-03 22:31:16.213 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=Compressed Class Space} value=2.376991 MiB 2021-05-03 22:31:16.213 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=Metaspace} value=18.34124 MiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=CodeHeap 'non-profiled nmethods'} value=1.75354 MiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=heap,id=G1 Eden Space} value=5 MiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=heap,id=G1 Survivor Space} value=7 MiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=CodeHeap 'non-nmethods'} value=1.118042 MiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=CodeHeap 'profiled nmethods'} value=6.87854 MiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=heap,id=G1 Old Gen} value=541.34375 KiB 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.daemon{} value=6 threads 2021-05-03 22:31:16.214 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.live{} value=7 threads 2021-05-03 22:31:16.215 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.peak{} value=7 threads 2021-05-03 22:31:16.216 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=blocked} value=0 threads 2021-05-03 22:31:16.216 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=runnable} value=3 threads 2021-05-03 22:31:16.216 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=waiting} value=2 threads 2021-05-03 22:31:16.217 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=new} value=0 threads 2021-05-03 22:31:16.217 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=timed-waiting} value=2 threads 2021-05-03 22:31:16.217 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=terminated} value=0 threads 2021-05-03 22:31:16.217 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : process.cpu.usage{} value=0 2021-05-03 22:31:16.218 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : process.files.max{} value=1048576 files 2021-05-03 22:31:16.218 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : process.files.open{} value=9 files 2021-05-03 22:31:16.218 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : process.start.time{} value=450013h 30m 14.272999936s 2021-05-03 22:31:16.218 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : process.uptime{} value=1m 1.985s 2021-05-03 22:31:16.218 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : system.cpu.count{} value=8 2021-05-03 22:31:16.219 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : system.cpu.usage{} value=0 2021-05-03 22:31:16.219 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : system.load.average.1m{} value=0.7 2021-05-03 22:31:16.221 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.pause{action=end of minor GC,cause=G1 Evacuation Pause} throughput=0.016667/s mean=0.013s max=0.013s
キャッシュの情報も含まれています。
2021-05-03 22:31:16.207 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=hit} throughput=0.016667/s 2021-05-03 22:31:16.207 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=miss} throughput=0.166667/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.memory.allocated{} throughput=2.45 MiB/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.memory.promoted{} throughput=9.022396 KiB/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : logback.events{level=info} throughput=0.433333 events/s 2021-05-03 22:31:16.208 INFO 43396 --- [trics-publisher] i.m.c.i.logging.LoggingMeterRegistry : cache.size{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache} value=9
スレッド名が、不思議なものになっていますね。これは、デフォルトでlogging-metrics-publisher
となっています。
あと、アプリケーションの停止時にもShutdown Hookでメトリクスのログ出力が行われます。
2021-05-03 22:32:20.557 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : get message = Hello 15 2021-05-03 22:32:21.558 INFO 43396 --- [ main] org.littlewings.spring.metrics.App : end 2021-05-03 22:32:21.564 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=hit} throughput=0.066667/s 2021-05-03 22:32:21.564 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=miss} throughput=0.166667/s 2021-05-03 22:32:21.564 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : logback.events{level=info} throughput=1.316667 events/s 2021-05-03 22:32:21.564 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : cache.size{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache} value=20 2021-05-03 22:32:21.564 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.count{id=mapped} value=0 buffers 2021-05-03 22:32:21.564 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.count{id=direct} value=1 buffers 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.memory.used{id=direct} value=8 KiB 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.memory.used{id=mapped} value=0 B 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.total.capacity{id=direct} value=8 KiB 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.buffer.total.capacity{id=mapped} value=0 B 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.classes.loaded{} value=4825 classes 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.live.data.size{} value=0 B 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.gc.max.data.size{} value=3.888672 GiB 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=heap,id=G1 Old Gen} value=94 MiB 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=heap,id=G1 Eden Space} value=151 MiB 2021-05-03 22:32:21.565 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=Compressed Class Space} value=2.75 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=CodeHeap 'profiled nmethods'} value=7.0625 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=CodeHeap 'non-nmethods'} value=2.4375 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=heap,id=G1 Survivor Space} value=7 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=Metaspace} value=19.5 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.committed{area=nonheap,id=CodeHeap 'non-profiled nmethods'} value=2.4375 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=heap,id=G1 Eden Space} value=-1 B 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=CodeHeap 'profiled nmethods'} value=117.214844 MiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=Compressed Class Space} value=1 GiB 2021-05-03 22:32:21.566 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=CodeHeap 'non-profiled nmethods'} value=117.21875 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=heap,id=G1 Old Gen} value=3.888672 GiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=CodeHeap 'non-nmethods'} value=5.566406 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=nonheap,id=Metaspace} value=-1 B 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.max{area=heap,id=G1 Survivor Space} value=-1 B 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=Compressed Class Space} value=2.387825 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=Metaspace} value=18.455597 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=CodeHeap 'non-profiled nmethods'} value=1.785645 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=heap,id=G1 Eden Space} value=6 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=heap,id=G1 Survivor Space} value=7 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=CodeHeap 'non-nmethods'} value=1.121338 MiB 2021-05-03 22:32:21.567 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=nonheap,id=CodeHeap 'profiled nmethods'} value=7.046753 MiB 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.memory.used{area=heap,id=G1 Old Gen} value=541.34375 KiB 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.daemon{} value=6 threads 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.live{} value=8 threads 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.peak{} value=9 threads 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=blocked} value=0 threads 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=runnable} value=3 threads 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=waiting} value=3 threads 2021-05-03 22:32:21.568 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=new} value=0 threads 2021-05-03 22:32:21.569 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=timed-waiting} value=2 threads 2021-05-03 22:32:21.569 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : jvm.threads.states{state=terminated} value=0 threads 2021-05-03 22:32:21.569 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : process.cpu.usage{} value=0.000702 2021-05-03 22:32:21.569 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : process.files.max{} value=1048576 files 2021-05-03 22:32:21.569 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : process.files.open{} value=9 files 2021-05-03 22:32:21.570 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : process.start.time{} value=450013h 30m 14.272999936s 2021-05-03 22:32:21.570 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : process.uptime{} value=2m 7.336s 2021-05-03 22:32:21.570 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : system.cpu.count{} value=8 2021-05-03 22:32:21.570 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : system.cpu.usage{} value=0.079138 2021-05-03 22:32:21.571 INFO 43396 --- [extShutdownHook] i.m.c.i.logging.LoggingMeterRegistry : system.load.average.1m{} value=1.13
これは、LoggingMeterRegistry
の親クラスであるMeterRegistry
にclose
メソッドが定義されているからですね。
MeterRegistry (micrometer-core 1.6.6 API)
LoggingMeterRegistryが使われるのは?
ところで、LoggingMeterRegistry
をBean登録しただけで使われたのは?というと、このあたりの仕組みですね。
Bean登録した際に、MicrometerのMetrics
に登録されるからです。
LoggingMeterRegistryの設定をしてみる
これで終わってもなんなので、LoggingMeterRegistry
の設定をしてみましょう。
LoggingMeterRegistry.Builder
を使うことで、ある程度設定可能です。
LoggingMeterRegistry.Builder (micrometer-core 1.6.6 API)
@Configuration public class MetricsConfig { @Bean public MeterRegistry meterRegistry() { return LoggingMeterRegistry .builder(LoggingRegistryConfig.DEFAULT) .loggingSink(m -> System.out.println(m)) .build(); } }
今回は、メトリクスの出力先を標準出力にしてみました。
結果はこちら。
cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=hit} throughput=0.016667/s cache.gets{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache,result=miss} throughput=0.166667/s logback.events{level=info} throughput=0.366667 events/s cache.size{cache=caffeineCache,cacheManager=cacheManager,name=caffeineCache} value=9 jvm.buffer.count{id=mapped} value=0 buffers jvm.buffer.count{id=direct} value=1 buffers jvm.buffer.memory.used{id=direct} value=8 KiB jvm.buffer.memory.used{id=mapped} value=0 B jvm.buffer.total.capacity{id=direct} value=8 KiB jvm.buffer.total.capacity{id=mapped} value=0 B 〜省略〜
標準出力に書き出すだけだと意味がありませんが、メトリクスの出力先をコントロールしたい場合に使うとよいでしょう。
ちなみに、SLF4Jを使う場合のデフォルトのロガー名は、io.micrometer.core.instrument.logging.LoggingMeterRegistry
となります(クラス名)。
もう1パターンやってみましょう。
LoggingMeterRegistry.Builder
で設定できない項目を変えたい場合は、LoggingMeterRegistry
の実装クラスを作成することに
なります。
@Configuration public class MetricsConfig { @Bean public MeterRegistry meterRegistry() { return LoggingMeterRegistry .builder(new LoggingRegistryConfig() { @Override public Duration step() { return Duration.ofSeconds(10L); } @Override public String get(String key) { return null; } }) .loggingSink(m -> System.out.println(m)) .build(); } }
今回は、メトリクスを10秒おき(step
)に出力するようにしてみました。
LoggingMeterRegistry#get
がnull
を返していますが、これはデフォルト実装と同じです。特に変えなくていいと思います…。
結果については、割愛。
まとめ
Spring Boot Actuatorで、Micrometerによるメトリクスをログ出力するようにしてみました。
ちょっとした確認などの際に、知っておくと便利なのではないでしょうか。