Micrometer là một thư viện định nghĩa standard các API về observation với metrics, giúp chúng ta có thể dễ dàng collect các metrics để monitor các ứng dụng của mình. Nó là vendor-neutral facade, tương tự như thư viện Slf4j, đóng vai trò tương tự như một interface, nghĩa là chúng ta có thể dễ dàng collect metrics và expose các thông tin metrics này cho nhiều vendor khác nhau mà không cần phải thay đổi code nhiều. Trong bài viết này, mình sẽ giới thiệu với các bạn những khái niệm cơ bản của Micrometer và cách chúng ta có thể sử dụng thư viện này để monitor cho ứng dụng của mình các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Maven project để làm ví dụ:

Để làm việc với Micrometer, thông thường chúng ta sẽ khai báo dependency của nó sử dụng dependency management như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<dependencies> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-core</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-bom</artifactId> <version>1.16.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> |
Micrometer sử dụng interface Meter để định nghĩa base abstraction cho các thông tin metrics. Có nhiều interface khác nhau extends interface Meter này giúp chúng ta có thể định nghĩa cụ thể hơn các thông tin metrics mà chúng ta muốn collect. Mình có thể liệt kê một số interface chính như sau:
- Counter: dùng để đếm số lượng, ví dụ như số lần nhận HTTP request, số lần thực hiện một tác vụ nào đó, …
- Timer: dùng để đo đạc thời gian thực hiện một tác vụ nào đó
- Gauge: dùng để đo đạc trạng thái hiện tại của hệ thống. Giá trị này có thể tăng hoặc giảm tuỳ theo trạng thái của hệ thống: ví dụ như memory usage, nhiệt độ, …
- LongTaskTimer dùng để đo đạc thời gian cho các tác vụ vẫn còn đang chạy.
- DistributionSummary dùng để đo lường các thông tin liên quan đến kích thước của dữ liệu, ví dụ như request payload size, response payload size, message size trong Apache Kafka, …
Chúng ta sẽ sử dụng abstract class MeterRegistry để quản lý các thông tin metrics trên. Có một vài implementation cho abstract class MeterRegistry này, các bạn có thể khởi tạo đối tượng của class MeterRegistry sử dụng implementation SimpleMeterRegistry dành cho testing, như sau:
|
1 |
MeterRegistry registry = new SimpleMeterRegistry(); |
Bây giờ thì các bạn có thể khởi tạo các đối tượng của class Timer, Counter sử dụng các class builder của chúng, ví dụ như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Counter jobCounter = Counter.builder("jobs.processed") .description("Number of jobs processed") .register(registry); Timer jobTimer = Timer.builder("jobs.execution.time") .description("Job execution time") .register(registry); for (int i = 0; i < 5; i++) { jobTimer.record(() -> { try { Thread.sleep(100 + (long) (Math.random() * 200)); } catch (InterruptedException ignored) { } }); jobCounter.increment(); } System.out.println("Jobs processed = " + jobCounter.count()); System.out.println("Total time (ms) = " + jobTimer.totalTime(TimeUnit.MILLISECONDS)); System.out.println("Max time (ms) = " + jobTimer.max(TimeUnit.MILLISECONDS)); |
Như các bạn thấy, sau khi khởi tạo các đối tượng Counter, Timer, chúng ta sẽ gọi phương thức register() để đăng ký chúng vào đối tượng MeterRegistry. Ở đây mình có 5 job chạy và thời gian để hoàn thành của mỗi job sẽ random, nên khi các bạn chạy ví dụ này, các bạn sẽ thấy kết quả như sau:
Các bạn cũng có thể sử dụng class Gauge như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.huongdanjava.micrometer; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import java.util.concurrent.atomic.AtomicInteger; public class Application { static void main() { MeterRegistry registry = new SimpleMeterRegistry(); AtomicInteger activeConnections = new AtomicInteger(0); Gauge.builder("connections.active", activeConnections, AtomicInteger::get) .description("Active connections") .register(registry); activeConnections.incrementAndGet(); activeConnections.incrementAndGet(); System.out.println( "Active connections = " + registry.get("connections.active").gauge().value()); activeConnections.decrementAndGet(); System.out.println( "Active connections = " + registry.get("connections.active").gauge().value()); } } |
Kết quả:
