Observability: Logs vs. Metrics vs. Tracing — Mô hình tư duy 'Bộ dụng cụ Bác sĩ'
App chậm. Tại DB? Queue? Mạng? Hướng dẫn chuyên sâu về ba trụ cột observability và cách chúng phối hợp với nhau.
App production của bạn đang chậm. User phàn nàn. Sếp nhắn Slack.
Bạn SSH vào server và… nhìn chằm chằm vào màn hình.
Không có observability, debug production giống như bác sĩ chẩn đoán bệnh nhân mà không được nhìn, sờ, hay nói chuyện với họ. Bài viết này trao cho bạn bộ dụng cụ của Bác sĩ.
Phần 1: Nền tảng (Mô hình tư duy)
Bộ dụng cụ Bác sĩ
Bác sĩ có ba loại dụng cụ cho các câu hỏi khác nhau:
- Ống nghe (Logs): “Để tôi NGHE bệnh nhân đang nói gì từng giây một.” Sự kiện thô. Có timestamp. Chi tiết. Ồn ào.
- Bảng theo dõi sinh hiệu (Metrics): “Để tôi KIỂM TRA các con số quan trọng: nhịp tim, huyết áp, nhiệt độ.” Đã tổng hợp. Là số. Tốt cho dashboard.
- X-Quang (Tracing): “Để tôi NHÌN THẤY bên trong và theo dõi đúng vấn đề này qua từng cơ quan.” Luồng request đầu cuối xuyên suốt các service.
| Trụ cột | Câu hỏi trả lời | Đơn vị | Công cụ |
|---|---|---|---|
| Logs | ”Chính xác chuyện gì đã xảy ra?” | Text events | Datadog, Loki, ELK Stack |
| Metrics | ”Hệ thống đang như thế nào nói chung?” | Số liệu theo thời gian | Prometheus, Grafana, Datadog |
| Tracing | ”Request này bị chậm ở đâu?” | Spans + Traces | Jaeger, Zipkin, OpenTelemetry |
Phần 2: Điều tra (Đi sâu từng Trụ cột)
1. Logs — “Nhật ký của Bệnh nhân”
Log là bản ghi có timestamp về những gì đã xảy ra. Kỷ luật quan trọng nhất: structured logging (log có cấu trúc).
# ❌ TỆ: Không có cấu trúc (khó query)
print(f"Lỗi xử lý đơn hàng cho user {user_id}")
# ✅ TỐT: JSON có cấu trúc (có thể tìm kiếm, lọc)
import structlog
log = structlog.get_logger()
log.error(
"order_processing_failed",
user_id=user_id,
order_id=order_id,
reason=str(e),
duration_ms=123
)
# Output: {"event": "order_processing_failed", "user_id": 42, "order_id": 999, ...}
Log Levels (Dùng đúng!):
DEBUG: Chi tiết tỉ mỉ cho dev. Tắt ở production.INFO: Hoạt động bình thường. “User 42 đăng nhập.”WARNING: Có thể sắp có chuyện. “Ổ đĩa đầy 80%.”ERROR: Thứ gì đó thất bại. “Thanh toán thất bại cho đơn 999.”CRITICAL: App đang hấp hối. Người trực on-call thức dậy.
2. Metrics — “Bảng Sinh hiệu”
Metrics cho bạn biết xu hướng thay đổi theo thời gian. Bốn Tín hiệu Vàng (Google SRE):
- Latency: Request mất bao lâu? (p50, p95, p99)
- Traffic: Bao nhiêu request mỗi giây?
- Errors: Bao nhiêu % request thất bại?
- Saturation: Hệ thống đầy bao nhiêu? (CPU %, RAM %, độ sâu Queue)
# Dùng Prometheus với Python
from prometheus_client import Counter, Histogram
REQUEST_LATENCY = Histogram("api_request_duration_seconds", "Độ trễ API")
ERROR_COUNT = Counter("api_errors_total", "Tổng lỗi API", ["endpoint"])
@REQUEST_LATENCY.time() # Tự động đo thời gian hàm
def process_order(order_id):
try:
...
except Exception:
ERROR_COUNT.labels(endpoint="/orders").inc()
3. Tracing — “Phim X-Quang”
Trong hệ thống microservices, một request user có thể đi qua 7 service. Nếu mất 2 giây, 2 giây đó ở đâu?
Tracing trả lời bằng Biểu đồ Thác nước (Waterfall):
Request: GET /checkout (2.0s tổng)
├── Auth Service (0.05s) ✅
├── Cart Service (0.08s) ✅
├── Inventory Service (1.6s) ← 🔴 NÚT CỔ CHAI
│ └── DB Query: SELECT ... (1.55s) ← THỨ THỰC SỰ CHẬM
└── Payment Service (0.27s) ✅
OpenTelemetry là chuẩn mở. Viết một lần, gửi đến backend nào cũng được (Jaeger, Datadog,…):
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def checkout(user_id):
with tracer.start_as_current_span("checkout") as span:
span.set_attribute("user.id", user_id)
with tracer.start_as_current_span("fetch_cart"):
cart = get_cart(user_id) # Span này sẽ là con của span cha
with tracer.start_as_current_span("process_payment"):
charge(cart.total)
Phần 3: Chẩn đoán (Dùng Công cụ Nào?)
| Vấn đề | Nhìn vào đâu trước? | Tại sao |
|---|---|---|
| ”Lỗi 500 cho user 42” | Logs | Tìm thông báo lỗi và stack trace chính xác. |
| ”API chậm từ 3 giờ chiều” | Metrics | Tìm đỉnh P95 latency trên dashboard. |
| ”Request này mất 2s” | Tracing | Xem Waterfall và tìm service nào chậm. |
| ”Server bị sập” | Metrics | Alert CPU/Memory kích hoạt trước khi crash. |
Phần 4: Giải pháp (Bộ Alerting)
Bạn không thể ngồi nhìn dashboard 24/7. Bạn cần alerts.
Alert tốt: “P99 latency vượt 2 giây trong 5 phút.” (Cụ thể, có thể hành động). Alert tệ: “CPU trên 50%.” (Mơ hồ, báo liên tục, gây alert fatigue).
# Prometheus alerting rule
groups:
- name: api_alerts
rules:
- alert: HighLatencyP99
# Báo alert nếu P99 latency > 2s trong 5 phút
expr: histogram_quantile(0.99, api_request_duration_seconds_bucket) > 2
for: 5m
annotations:
summary: "P99 latency của API đang ở mức nghiêm trọng"
Mô hình tư duy chốt hạ
Logs -> Nhật ký Bệnh nhân. "Chuyện gì xảy ra? Khi nào? Chi tiết thế nào?"
Metrics -> Bảng Sinh hiệu. "Hệ thống đang biến đổi theo hướng nào?"
Tracing -> Phim X-Quang. "Request CỤ THỂ NÀY bị lỗi ở đâu?"
Dùng Logs để hiểu sự kiện.
Dùng Metrics để build dashboard và alert.
Dùng Tracing để debug giao dịch phân tán chậm.
Bạn cần cả ba. Log không có Metrics là bay mù. Metrics không có Tracing là biết mình bệnh nhưng không biết tại sao.
Bài viết liên quan
-
MoneyPrinterV2: 18.000 Sao GitHub Và Cái Máy In Nội Dung Tự Động
Ollama viết kịch bản, KittenTTS đọc, Gemini vẽ hình, MoviePy ghép video. Bạn ngồi uống cà phê. YouTube Short tự lên kênh.
-
Giải Mã Super Agent Harness: Đi Sâu Vào DeerFlow Của Bytedance
Khám phá cách DeerFlow 2.0 chuyển mình từ một công cụ nghiên cứu chuyên sâu thành một hệ sinh thái agent toàn diện với sandbox, sub-agent và bộ nhớ dài hạn.
-
Giải thích về OpenBB: Nền tảng Dữ liệu Mở cho Nghiên cứu Đầu tư
Phân tích sâu về OpenBB, nền tảng mã nguồn mở giúp thống nhất các API dữ liệu tài chính thành một giao diện duy nhất cho lập trình viên Python, nhà phân tích và các AI agents.
-
AI Agents & Hệ thống Đa tác nhân: Mô hình tư duy 'Công ty Robot'
Sự khác biệt giữa ChatGPT và AI Agent là gì? Hướng dẫn chuyên sâu về tool calling, LangGraph và tại sao multi-agent là kiến trúc của 2026.