# ⏱️ Metric cơ bản: latency và error rate

By Better Wise

## Đêm đó dashboard đẹp, còn user thì bỏ đi

Bài trước bạn đã dựng được log có cấu trúc với các field như `request_id`, `route`, `duration_ms`, và biết chọn log level để không ngập log. Nhưng log chỉ trả lời "chuyện gì đã xảy ra" sau khi bạn đã biết cần tìm gì. Metric trả lời câu hỏi trước đó: hệ thống có đang khỏe không?

Chuyện thật: 3 giờ sáng, dashboard hiện latency trung bình 120ms, đẹp như mơ. Nhưng khoảng 1% user chờ 8 giây mỗi lần bấm thanh toán, và họ đã bỏ đi. Con số trung bình đã giấu hết. Bài này dạy bạn nhìn đúng chỗ.

Sau bài này, bạn sẽ:

- Đọc được p50, p95, p99 và biết vì sao trung bình hay đánh lừa
- Biết đo latency ở đâu và đo bằng cấu trúc dữ liệu nào
- Tính error rate đúng, tách 5xx khỏi 4xx
- Ghép hai con số lại để đoán loại sự cố

## Latency: đừng tin con số trung bình

### p50, p95, p99 nói gì

p95 nghĩa là 95% request nhanh hơn giá trị đó, và 5% chậm hơn. p50 là median: một nửa nhanh hơn, một nửa chậm hơn.

| Chỉ số | Nghĩa | Dùng để làm gì |
| --- | --- | --- |
| average | Tổng thời gian chia số request | Gần như vô dụng cho latency, vì vài request rất chậm kéo lệch hết |
| p50 | Trải nghiệm điển hình | Biết "user bình thường" thấy gì |
| p95 | Trải nghiệm của nhóm xui nhất | Đặt SLO latency, đây là chỉ số chính nên xem |
| p99 | Đuôi dài | Soi các luồng đắt tiền: thanh toán, tìm kiếm, xuất báo cáo |

> **Warning:** 
> Đừng đặt alert theo latency trung bình. Một request treo 30 giây giữa 10.000 request chỉ làm trung bình nhích vài ms, nhưng đủ để vài user bỏ đi. p95 mới là chỗ sự thật lộ ra.

### Đo latency ở đâu và đo thế nào

- Đo ở biên hệ thống: middleware HTTP hoặc load balancer, nơi gần user nhất mà bạn kiểm soát được. Ghi rõ trong tên metric là đo ở đâu (`http_server_duration_ms`).
- Lưu dạng histogram (các bucket), không chỉ lưu average. Percentile chỉ tính đúng khi có histogram hoặc dữ liệu thô.
- Chốt một đơn vị duy nhất, thường là ms. Lẫn ms và giây là lỗi kinh điển.
- Gắn label theo `route`, `method`, `status`. Tuyệt đối không gắn `user_id` hay `request_id` vào label, mỗi giá trị riêng tạo ra một chuỗi mới và làm nổ cardinality.
- Tách theo endpoint. `/health` mất 3ms không nói gì về `/checkout` mất 900ms.

**Bài tập nhanh.** 10 request gần nhất có latency (ms): 100, 110, 120, 130, 140, 150, 160, 170, 180, 5000. Tính average, p50, p95. Con số nào nói đúng hơn về trải nghiệm?

**Xem gợi ý đáp án**

Average = 6360 / 10 = 636ms. p50 = 135ms. p95 xấp xỉ 5000ms (với 10 mẫu, p95 rơi vào mẫu lớn nhất).

Average bị đúng một request 5 giây kéo lên gấp 5 lần p50, và không phản ánh ai cả. p50 cho biết trải nghiệm điển hình, p95 chỉ ra rằng có user thật đang chờ rất lâu. Khi lưu lượng thấp, hãy đọc p95 cùng với số lượng request để biết nó có đáng tin không.

## Error rate: đếm cho đúng tử số

Công thức: error rate = số request lỗi chia cho tổng request, trong cùng một cửa sổ thời gian.

- 5xx là lỗi phía server, tính vào error rate. 4xx thường là lỗi phía client, hãy tách riêng. Gộp vào là tự chuốc alert vì bot scan và người gõ sai URL.
- Tách theo endpoint và status code. Cả hệ 0,2% nhưng `/checkout` 12% là hai câu chuyện khác hẳn.
- Cửa sổ 5 phút đọc dễ chịu hơn 1 phút. Cửa sổ 1 phút với lưu lượng thấp sẽ nhảy loạn.
- Đếm bằng counter trong code, đừng grep log. Log có thể bị sample hoặc bị drop, còn counter thì không.

**Bài tập nhanh.** 10 phút có 20.000 request: 300 trả 5xx, 800 trả 4xx. Error rate phía server là bao nhiêu? Nếu gộp 4xx thì sao?

**Xem gợi ý đáp án**

Error rate server = 300 / 20000 = 1,5%. Nếu gộp: 1100 / 20000 = 5,5%.

Con số 5,5% bị chi phối bởi client gọi sai hoặc bot, và nếu bạn alert ở ngưỡng 5% thì đêm đó bạn thức dậy vì một con bot. Theo dõi 4xx riêng, nó vẫn hữu ích, chỉ là không phải tín hiệu hệ thống của bạn hỏng.

## Đọc hai con số cùng nhau

Một mình p95 chưa đủ, một mình error rate cũng chưa đủ. Ghép lại thì bức tranh hiện ra.

```mermaid
flowchart TD
  Start["📈 Xem metric"] --> Lat{"p95 thế nào?"}
  Lat -->|"tăng"| Err{"Error rate?"}
  Lat -->|"phẳng"| Err2{"Error rate?"}
  Err -->|"phẳng"| Slow["🐌 Chậm dần<br/>xem DB, downstream"]
  Err -->|"tăng"| Real["🔥 Sự cố thật"]
  Err2 -->|"tăng"| Fast["⚡ Fail fast<br/>xem deploy, dependency"]
  Err2 -->|"phẳng"| Traffic["🚦 Xem traffic và count"]
```

| p95 | Error rate | Đọc ra |
| --- | --- | --- |
| Tăng | Phẳng | Chậm dần nhưng chưa gãy: nghi DB chậm, downstream, queue ùn, thiếu index |
| Phẳng | Tăng | Lỗi nhanh: nghi deploy hỏng, dependency trả 5xx, config sai |
| Tăng | Tăng | Sự cố thật, ưu tiên xử lý ngay |
| Phẳng | Phẳng nhưng traffic tụt | Client không gọi được: DNS, load balancer, upstream chặn |

**Bài tập nhanh.** p95 của `/checkout` từ 300ms lên 1,2s trong 10 phút, error rate vẫn 0,2%, traffic bình thường. Bạn đọc ra gì và mở gì trước?

**Xem gợi ý đáp án**

Hệ thống chậm dần nhưng chưa gãy. Đây là lúc chưa cần đánh thức ai, nhưng nên xem ngay.

Thứ tự mở: latency tách theo từng endpoint và từng dependency, thời gian query DB và connection pool, rồi mở log của những request chậm nhất. Đây chính là lúc log có cấu trúc với `request_id` và `duration_ms` phát huy tác dụng: metric chỉ ra chỗ đau, log cho biết vì sao.

## Mấy lỗi hay gặp khi đọc latency và error rate

- Lấy average làm chỉ số chính: bỏ ngay, xem p95 trước.
- Alert trên cửa sổ 1 phút: rung liên tục, dùng 5 đến 10 phút.
- Ghi metric mà không ghi điểm đo: sáu tháng sau không ai biết số đó đo ở client hay server.
- Lẫn ms và giây trong cùng một dashboard: nhìn 0,3 cạnh 300 rồi tưởng hệ thống nhanh gấp nghìn lần.
- Quên đọc count: p95 của 4 request không phải là p95, đó là chuyện phiếm.
- Tin error rate 0%: có thể bạn đang không đếm lỗi ở tầng proxy, nơi request chết trước khi vào app.

Quy tắc ngón tay cái: **p95 là chỉ số latency mặc định, error rate phía server chỉ tính 5xx, cả hai cùng một cửa sổ thời gian**.

## Chốt lại: hai con số, một câu hỏi

- p50 cho biết trải nghiệm điển hình, p95 cho biết nhóm chậm nhất, average che giấu cả hai.
- Latency phải đo bằng histogram, ở biên hệ thống, cùng một đơn vị, tách theo endpoint.
- Error rate server chỉ tính 5xx trên tổng request, tách 4xx riêng, đọc trong cửa sổ 5 phút.
- Ghép p95 với error rate là bạn đoán được loại sự cố trước khi mở log.

Điền nhanh để tự kiểm tra:

1. p95 nghĩa là _____ request nhanh hơn giá trị đó.
2. Chỉ số nên dùng làm chỉ số latency chính thay cho average là _____.
3. Percentile chỉ tính đúng khi dữ liệu được lưu dạng _____.
4. Error rate bằng số request lỗi chia cho _____ trong cùng cửa sổ thời gian.
5. Lỗi 5xx là lỗi phía _____, còn 4xx thường là lỗi phía client nên tách riêng.

Ôn nhanh bộ thẻ dưới đây, rồi sang bài tiếp theo:

Front: p50 là gì?
Back: Median: một nửa số request nhanh hơn giá trị này.

Front: p95 là gì?
Back: 95% request nhanh hơn giá trị này, 5% còn lại chậm hơn.

Front: Vì sao không dùng latency trung bình?
Back: Vài request rất chậm kéo lệch con số và che mất trải nghiệm của nhóm chậm.

Front: Muốn tính percentile đúng thì phải lưu dữ liệu dạng gì?
Back: Histogram (các bucket), không chỉ lưu average.

Front: Nên đo latency ở đâu?
Back: Ở biên hệ thống: middleware HTTP hoặc load balancer, và ghi rõ điểm đo trong tên metric.

Front: Vì sao phải tách latency theo endpoint?
Back: Mỗi endpoint có đặc điểm riêng, gộp lại thì con số không nói lên điều gì.

Front: Công thức error rate?
Back: Số request lỗi chia cho tổng request trong cùng cửa sổ thời gian.

Front: 5xx và 4xx khác nhau thế nào khi tính error rate?
Back: 5xx là lỗi server, tính vào error rate; 4xx thường là lỗi client, theo dõi riêng.

Front: Vì sao không đếm lỗi bằng cách grep log?
Back: Log có thể bị sample hoặc drop; counter trong code chính xác và rẻ hơn.

Front: p95 tăng nhưng error rate phẳng nghĩa là gì?
Back: Hệ thống chậm dần nhưng chưa gãy: nghi DB, downstream hoặc queue.

Front: Error rate tăng nhưng latency phẳng nghĩa là gì?
Back: Lỗi nhanh (fail fast): nghi deploy hỏng, dependency trả 5xx hoặc config sai.

Front: Vì sao không gắn user_id vào label của metric?
Back: Mỗi giá trị tạo một chuỗi mới, làm nổ cardinality và khiến metric chậm, tốn tài nguyên.

Front: Cửa sổ thời gian nào hợp lý để đọc error rate?
Back: Khoảng 5 phút; cửa sổ 1 phút hay nhảy và dễ gây nhiễu.

Front: Vì sao phải đọc p95 cùng với count?
Back: Khi lưu lượng thấp, p95 được tính từ quá ít mẫu nên rất nhiễu và dễ gây hiểu sai.

Bài sau, chúng ta lấy đúng mấy chỉ số này đặt lên một dashboard nhỏ: vài ô đáng nhìn mỗi sáng, đủ để biết ứng dụng khỏe hay yếu trong vài giây.

---

## Contents

Part of [🔭 Observability cho người mới: log, metric và cảnh báo](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao.md)

- **📝 Log có cấu trúc và log level**
  - [🧱 Structured logging: log có cấu trúc và các field cần có](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/structured-logging-va-cac-field-can-co.md)
  - [🎚️ Log level: chọn đúng mức để không ngập log](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/log-level-chon-dung-muc.md) (sign-in required)
  - [🚫 Log gì và không log gì](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/log-gi-va-khong-log-gi.md)
  - [✅ Checkpoint: Log có cấu trúc và log level](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/checkpoint-log-co-cau-truc-va-log-level.md)
- **📊 Metric cơ bản và dashboard**
  - [⏱️ Metric cơ bản: latency và error rate](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/metric-co-ban-latency-va-error-rate.md) — this lesson
  - [🖥️ Dashboard: vài chỉ số đáng nhìn mỗi ngày](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/dashboard-vai-chi-so-dang-nhin.md)
  - [✅ Checkpoint: Metric cơ bản và dashboard](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/checkpoint-metric-co-ban-va-dashboard.md)
- **🔔 Alert ít nhiễu, tracing và nhờ AI thêm log**
  - [🚨 Alert không gây mệt mỏi](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/alert-khong-gay-met-moi.md)
  - [🧵 Tracing ở mức khái niệm](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/tracing-o-muc-khai-niem.md)
  - [🤖 Nhờ AI thêm log đúng chỗ](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/nho-ai-them-log-dung-cho.md) (premium content)
  - [✅ Checkpoint: Alert, tracing và AI hỗ trợ](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/checkpoint-alert-tracing-va-ai-ho-tro.md) (premium content)
- [Course cheatsheet](https://everwise.study/courses/observability-cho-nguoi-moi-log-metric-va-canh-bao/cheatsheet.md) (premium content)
