Bài 10: Giám sát hiệu năng và đo đạc thời gian với AOP

Mục tiêu bài học
Tạo một Performance Aspect dùng
@Around
Advice để đo thời gian thực thi method.Tích hợp metric thu thập được vào các công cụ giám sát (Prometheus, Grafana, Datadog, New Relic, v.v.).
Biết tối ưu hoá tránh overhead quá cao, phân tích log/metrics một cách có chủ đích.
Thực hành một ví dụ case study đo thời gian method quan trọng, đưa ra cảnh báo khi vượt ngưỡng.
Nội dung chính
1. Performance Aspect
Khái niệm:
Trong một ứng dụng lớn, các method quan trọng (đặc biệt là “truy cập DB”, “gọi service ngoài”, “tính toán nặng”) cần đo thời gian để biết performance thực tế.
Thay vì thủ công chèn
System.currentTimeMillis()
đầu-cuối mọi nơi, ta viết 1 aspect chung quét tất cả method / method được “đánh dấu”.
Dùng
@Around
Advice:Advice “bao” toàn bộ lời gọi method, cho phép đo
start = System.currentTimeMillis()
→pjp.proceed()
→end = …
.Ghi log hoặc gửi metric (vd:
methodX_time = 50ms
) vào Hệ thống giám sát.
Annotation
@PerformanceMonitor
(gợi ý):Tương tự
@Loggable
, ta tạo annotation để đánh dấu method nào cần theo dõi:@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PerformanceMonitor { // Có thể thêm tham số threshold, v.v. }
Aspect bắt
@PerformanceMonitor
=> Tự động đo thời gian.
2. Tích hợp Prometheus, Grafana
Micrometer:
Là thư viện “thu thập metric” chuẩn trong Spring Boot.
Tạo
Timer
,Counter
,Gauge
… và publish sang nhiều backend (Prometheus, New Relic, Datadog...).
Prometheus:
- Thường khởi chạy 1 “endpoint”
/actuator/prometheus
để Prometheus “scrape” metric.
- Thường khởi chạy 1 “endpoint”
Grafana:
- Dùng dashboard theo dõi metric, vẽ biểu đồ.
Cách áp dụng:
Mỗi khi method gắn
@PerformanceMonitor
chạy, aspect:Tạo/ghi
Timer
(Micrometer) →timer.record(end - start, TimeUnit.MILLISECONDS)
.Kết quả hiển thị trong Grafana: “Trung bình method X = 40ms”.
Ví dụ:
@Aspect @Component public class PerformanceAspect { private final MeterRegistry meterRegistry; @Autowired public PerformanceAspect(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; } @Pointcut("@annotation(com.example.monitor.PerformanceMonitor)") private void monitorMethods() {} @Around("monitorMethods()") public Object recordExecutionTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); long end = System.currentTimeMillis(); long duration = end - start; // Tên method: pjp.getSignature().toShortString() String methodName = pjp.getSignature().getName(); // Ghi metric Timer timer = Timer.builder("method.performance") .tag("method", methodName) .register(meterRegistry); timer.record(duration, TimeUnit.MILLISECONDS); return result; } }
3. Ví dụ code
Annotation
@PerformanceMonitor
:@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PerformanceMonitor { // Optional: threshold, description... }
Service:
@Service public class PaymentService { @PerformanceMonitor public void processPayment(Order order) { // Giả lập xử lý payment, tốn thời gian // ... } }
Aspect (đã trình bày ở trên).
Kết quả:
- Gọi
paymentService.processPayment(...)
→ AOP aspect đo thời gian → Ghi metric “method.performance{method=processPayment} = 52ms”.
- Gọi
4. Tối ưu hoá
Không “monitor” toàn bộ method:
Chỉ method cốt lõi (ví dụ Payment, Checkout, Calculation...).
Lạm dụng => overhead log/metrics, “rác” data.
Sampling:
Ở scale lớn, đôi khi ta chỉ theo dõi X% request.
Hoặc “monitor theo batch” thay vì method-level.
Kiểm soát log level:
- Print debug info => overhead, disk usage.
5. Performance Monitoring Troubleshooting
Overhead:
Mỗi method log/metrics => tốn CPU + network.
Cần giám sát overhead vs. lợi ích.
Sai pointcut:
- Monitor “quá rộng” => dính cả method trivial => spam metric.
Phân tích:
- Dữ liệu metric “method X tốn 60ms” => Tìm code optimize? Kiểm tra DB query?
Kiểm soát threshold:
- Setting alarm? “Nếu
processPayment
> 100ms → Gửi alert Slack.”
- Setting alarm? “Nếu
6. Case study
Dự án Ecommerce:
Method
checkoutService.checkout()
→ Tính tổng, trừ stock, gọi payment.@PerformanceMonitor →
PerformanceAspect
ghi time = 120ms.Prometheus + Grafana → Chart hiển thị “Trung bình 5 phút = 110ms, p95 = 200ms.”
Cảnh báo: Mức threshold 300ms => Quá => Thông báo dev.
Nhờ AOP, ta cắm logic “đo thời gian” 1 lần, apply khắp service. Code business gọn.
Tóm tắt
Dùng @Around advice để đo thời gian method, log/ghi metric.
Kết hợp Micrometer + Prometheus/Grafana (hoặc New Relic, Datadog) để theo dõi biểu đồ.
Cần chọn lọc method quan trọng để monitor, tránh overhead.
Bài 11: Tìm hiểu cách AOP hỗ trợ logging/tracing/security tại kiến trúc microservices.
Câu hỏi thảo luận
Những method nào không nên bị “tracking” quá nhiều? Có tiêu chí lựa chọn method cốt lõi nào?
Bạn từng dùng New Relic/Datadog thay vì Prometheus? So sánh ưu/nhược?
Subscribe to my newsletter
Read articles from hoangkim directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
