Preview Bản nháp chờ review — title, nội dung, link có thể sửa trước khi bỏ nhãn.

Timeout budget trong code: một deadline cho cả chuỗi. Khi p99 đỏ, log “timeout” không nói hop nào ăn hết ms.

Distributed trace (OpenTelemetry, Jaeger, Zipkin…) là kính hiển vi: mỗi hop một span. Bài này: đọc trace bằng mắt budget — không phải tutorial cài agent.

Budget trên giấy vs trên trace

Code:  deadline = now + 2000ms, truyền xuống
Trace: thấy thực tế
  API        0───1950ms─────────────────────x timeout
  ├ pool.wait     0──800ms──┐
  ├ db.query           800──1400
  └ http.B                 1400──1900 (retry ×2?)

Cùng “timeout 2s”, root cause có thể là acquire pool, query, hay retry amplification — ba hướng chữa khác nhau.

Năm pattern đọc nhanh

  1. Parent ≫ sum(children): thời gian “mất tích” — queue nội bộ, GC, sync trên event loop, serialization.
  2. Span pool.acquire / getConnection dài: pool exhaustion — CPU có thể rảnh.
  3. Nhiều span con giống nhau liên tiếp: retry / hedge — đếm attempt attribute.
  4. Span status error + message canceled/aborted: cancel đúng hay timeout không abort? cancellation.
  5. Deadline còn 0 mà vẫn start child: budget không xuyên tầng — bug policy.

Attribute nên có

deadline_ms / deadline_remaining_ms
attempt / retry_reason
outcome = ok | timeout | aborted | error
http.route / rpc.method
pool.wait_ms (nếu instrument được)

Không có remaining_ms vẫn suy từ start time vs deadline header — instrument sẵn thì on-call đỡ đoán.

Checklist 1 trace chậm

  1. Root duration vs SLA/budget?
  2. Critical path span nào dài nhất?
  3. Chờ (queue/pool) hay làm (query/CPU)?
  4. Có retry/hedge không — tổng work vs 1 attempt?
  5. Client đã abort chưa — server còn chạy orphan?

Giới hạn

Trace không thay budget trong code; sampling có thể bỏ đúng request xấu; span thiếu = mù. Vẫn cần metric in-flight / pool.

Một câu

Trace là kính hiển vi của budget — chỉ ra hop nào ăn deadline, không thay việc truyền deadline xuống.