Bỏ qua để đến nội dung
Knowledge Hub

Logs, metrics và traces: ba góc nhìn cho cùng một request lỗi Cơ bản

Thời gian đọc ước tính: 6 phút

Khách báo “trang đặt hàng đôi khi quay mãi”. Một log request failed cho biết có lỗi nhưng không biết nhiều hay ít. Dashboard p95 tăng nhưng không chỉ ra chặng nào chậm. Một trace cho thấy payment chiếm phần lớn thời gian nhưng không nói toàn bộ traffic có cùng triệu chứng hay không. Chỉ thu một loại dữ liệu thì phải đoán phần còn lại.

Signal Trả lời Giới hạn Ví dụ cụ thể
Metric Bao nhiêu, xu hướng, route nào? Không chỉ ra request nào hỏng Tỷ lệ lỗi 5xx của /orders/:id/pay
Trace Request đi qua những chặng nào, mỗi chặng bao lâu? Chỉ thấy phần được instrument và được lấy mẫu Span payment.charge chiếm 850 ms trong 900 ms
Log Chuyện gì đã xảy ra ở sự kiện này? Có thể bị sampling, redact hoặc thiếu payment.timeout, deadline_ms: 330

Log có cấu trúc: field có tên thay vì một chuỗi dài. Đây là output thật từ demo trong repo (hai request song song, traceId giữ nguyên qua await):

{"event":"request.start","traceId":"796e70b7-...","orderId":42}
{"event":"request.error","traceId":"1884c8d2-...","reason":"invalid order"}

Metric: câu hỏi “tỷ lệ lỗi” là một PromQL, không phải một dòng log:

sum(rate(http_requests_total{route="/orders/:id/pay", status=~"5.."}[5m]))
/
sum(rate(http_requests_total{route="/orders/:id/pay"}[5m]))

Trace: cây span có start, end và quan hệ cha-con; trace_id nối chúng với log. Trace chỉ là bản đồ của những đoạn đã đo, không phải bộ giải thích nguyên nhân: span payment 850 ms có thể gồm cả chờ connection pool hay retry.

Drill-down mặc định: alert, exemplar, trace, log

Phần tiêu đề “Drill-down mặc định: alert, exemplar, trace, log”

Đang tải diagram…

Exemplar là mắt xích nối metric với trace: một data point của histogram kèm trace_id của một request đại diện. Prometheus chỉ lưu exemplar khi bật --enable-feature=exemplar-storage; chúng nằm trong buffer vòng cố định trong RAM, cấu hình bằng khối storage.exemplars. Không có exemplar thì quay về cách thủ công: lọc trace theo route và khoảng thời gian.

Dừng ở giả thuyết, không ở kết luận: một trace chưa chứng minh nguyên nhân. Đối chiếu bằng metric của dependency, ví dụ pool utilization.

Head sampling Tail sampling
Quyết định lúc Đầu trace, chưa biết kết quả Sau khi thấy gần hết span
Tiêu chí Xác suất theo trace_id (ví dụ 5%) Có lỗi, tổng latency, attribute, tỷ lệ theo service
Ưu Đơn giản, rẻ, chạy ở bất kỳ đâu Giữ được trace lỗi và trace chậm
Nhược Không đảm bảo giữ trace lỗi Khó vận hành: component có state, tốn tài nguyên

Đặt ở OpenTelemetry Collector (Tail Sampling Processor). Hệ thống rất lớn thường kết hợp cả hai: head sampling để bảo vệ pipeline, rồi tail sampling để chọn lọc. Nếu chỉ dùng head sampling, log phải đủ thông tin để điều tra mà không cần trace.

Percentile: lấy từ histogram, không lấy trung bình

Phần tiêu đề “Percentile: lấy từ histogram, không lấy trung bình”
  • p95 của từng instance không thể cộng hay lấy trung bình; Prometheus nói thẳng rằng trung bình các quantile cho ra giá trị vô nghĩa về mặt thống kê.
  • Dùng histogram: cộng bucket của mọi instance, rồi mới tính quantile.
histogram_quantile(0.95,
sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

Bucket boundaries phải giống nhau giữa các instance. Native histogram tương thích bucket tự động và được Prometheus khuyến nghị khi dùng được.

Câu hỏi Bắt đầu bằng
Có sự cố không, lớn cỡ nào? Metric (RED: Rate, Errors, Duration, cho service request-driven)
Tài nguyên có cạn không? Metric (USE: Utilization, Saturation, Errors, cho tài nguyên)
Chậm ở chặng nào? Trace
Lỗi cụ thể là gì? Log kèm trace_id

Chạy demo (hai request song song, ID 42 thành công, -1 lỗi):

Terminal window
npx --prefix examples ts-node examples/src/observability-signals/signals-demo.ts

Dòng cuối là metrics { total: 2, errors: 1 }; requests chỉ là object trong RAM, không phải counter Prometheus, và spanId chỉ là chuỗi minh họa, chưa phải span chuẩn. Xóa context.run(...) để thấy log mất traceId trong khi counter vẫn tăng. Về AsyncLocalStorage và propagation qua network, xem correlation ID; về label metric, xem metric cardinality.

Một request tạo dữ liệu quan sát ở nhiều tầng
Một request tạo dữ liệu quan sát ở nhiều tầngBước 1/4: Request vào API; tạo hoặc nhận trace context và ghi thời điểm bắt đầu.RequestAPIDependencytrace context
Request → APItrace context
Bước 1/4

Request vào API; tạo hoặc nhận trace context và ghi thời điểm bắt đầu.

  1. Log có cấu trúc, mỗi dòng có trace_id, route, status, duration_ms.
  2. Metric đếm đúng một lần theo định nghĩa (không đếm ở cả middleware và controller).
  3. Label metric có số giá trị hữu hạn; ID cá thể ở log hoặc trace.
  4. Latency là histogram; percentile tính bằng histogram_quantile trên bucket đã cộng.
  5. Propagation chuẩn qua HTTP và message; kiểm tra bằng integration test.
  6. Chiến lược sampling nêu rõ: có giữ trace lỗi không (tail), hay log đủ để bù.
  7. Redact secret và PII ở nguồn; phân quyền và retention cho log.

Khi kết hợp ba signal

  • Metric phát hiện xu hướng, trace khoanh vùng, log giữ chi tiết.
  • trace_id trong log rút ngắn việc tìm dữ liệu của một request.
  • Quy ước route, service, status giúp đối chiếu nhiều tầng.

Chi phí phải kiểm soát

  • Log và trace tốn ingest; sampling và retention làm mất một phần.
  • Label cardinality cao làm tăng chi phí metric.
  • Instrumentation sai hoặc context đứt cho kết luận sai.

Tự kiểm tra: (1) Vì sao p95 tăng chưa đủ kết luận payment chậm? (2) Head sampling bỏ sót điều gì mà tail sampling giữ được? (3) Vì sao không lấy trung bình p95 của các Pod?