Trong bài viết trước, mình đã giới thiệu với các bạn về class MeterRegistry của Micrometer, một class giúp chúng ta có thể collect và quản lý các thông tin về metrics của ứng dụng. Trong Micrometer còn có một class Registry khác tên là ObservationRegistry đó các bạn! Class ObservationRegistry này dùng để quản lý lifecyle của một observation từ lúc start observer cho đến lúc stop, có lỗi gì xảy ra trong quá trình observation đó không. Nó cũng sẽ tự động record các thông tin không chỉ về metrics như timer, counter mà còn về traces và handle cả context propagation (nắm giữ các thông tin về context của request như user ID, trace ID qua nhiều layer khác nhau của ứng dụng). ObservationRegistry handle về observation ở mức high-level hơn, còn MeterRegistry thì sẽ low-level hơn. Cụ thể như thế nào? Chúng ta hãy cùng nhau tìm hiểu trong bài viết này các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Maven project để làm ví dụ:

Class ObservationRegistry nằm trong một artifact khác của Micrometer là Micrometer Observation, nhưng các bạn cũng chỉ cần khai báo sử dụng micrometer-core dependency là được các bạn nhé:
|
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> |
Với ObservationRegistry thì chúng ta sẽ sử dụng class Observation để làm việc với observation cho ứng dụng. Các bạn có thể khởi tạo đối tượng của class Observation, đăng ký nó với ObservationRegistry, cơ bản như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.micrometer; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; public class Application { static void main() throws InterruptedException { ObservationRegistry observationRegistry = ObservationRegistry.create(); Observation observation = Observation.start("job.execute", observationRegistry); try { // business logic Thread.sleep(2000); } catch (Exception e) { observation.error(e); } finally { observation.stop(); } } } |
Để có thể collect các thông tin metrics hay traces thì chúng ta phải cấu hình các handler cho đối tượng Observation các bạn nhé! Với ví dụ trên thì sẽ không có output gì cả.
Các bạn có thể cấu hình các handler sử dụng các implementation của class ObservationHandler 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 22 23 24 25 26 27 28 29 30 31 |
package com.huongdanjava.micrometer; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; import java.util.concurrent.TimeUnit; public class Application { static void main() throws InterruptedException { MeterRegistry meterRegistry = new SimpleMeterRegistry(); ObservationRegistry observationRegistry = ObservationRegistry.create(); observationRegistry.observationConfig() .observationHandler( new DefaultMeterObservationHandler(meterRegistry) ); Observation observation = Observation.start("job.execute", observationRegistry); Thread.sleep(150); observation.stop(); Timer timer = meterRegistry.get("job.execute").timer(); System.out.println("Count = " + timer.count()); System.out.println("Total time (ms) = " + timer.totalTime(TimeUnit.MILLISECONDS)); } } |
Class DefaultMeterObservationHandler sẽ tự động record các thông tin về timer và counter từ lúc observation start cho đến lúc stop các bạn nhé! Nó cũng sử dụng class MeterRegistry để làm điều này.
Kết quả khi mình chạy ví dụ trên như sau:

Các bạn cũng có thể record error, tags được đánh dấu cho Observation sử dụng một customer ObservationHandler, 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 22 23 24 25 26 27 |
package com.huongdanjava.micrometer; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; public class Application { static void main() { ObservationRegistry observationRegistry = ObservationRegistry.create(); observationRegistry.observationConfig() .observationHandler( new HDJHandler() ); Observation observation = Observation.createNotStarted("job.execute", observationRegistry) .lowCardinalityKeyValue("website", "Huong Dan Java"); observation.start(); try { throw new RuntimeException("Job failed"); } catch (Exception e) { observation.error(e); } finally { observation.stop(); } } } |
Với class HDJHandler có nội dung 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 |
package com.huongdanjava.micrometer; import io.micrometer.observation.Observation; import io.micrometer.observation.Observation.Context; import io.micrometer.observation.ObservationHandler; public class HDJHandler implements ObservationHandler<Context> { @Override public void onStop(Observation.Context context) { Throwable error = context.getError(); if (error != null) { System.out.println("Observation error: " + error.getMessage()); } System.out.println("Observation Tags: " + context.getAllKeyValues()); } @Override public boolean supportsContext(Observation.Context context) { return true; } } |
Kết quả:
Các bạn nên sử dụng ObservationRegistry để record các thông tin cho:
- HTTP requests
- Database calls
- Kafka consumers
- gRPC calls
- Business operations
các bạn nhé!
