# 🔎 CloudWatch và X-Ray: log, metric, trace để chẩn đoán

## Mục tiêu học tập

Sau bài này, bạn cần làm được:

- Phân biệt ba tín hiệu **metric**, **log**, **trace** và biết khi nào chọn CloudWatch, khi nào chọn X-Ray.
- Đọc thành thạo một alarm: state, period, evaluation periods, cách xử lý missing data.
- Tạo metric filter từ log và nhớ giới hạn quan trọng của nó.
- Đọc service map và segment của X-Ray để chỉ ra service nào là nguyên nhân gốc.
- Nhận diện các bẫy giám sát hay gặp trong đề DVA-C02.

## Ôn nhanh

Bài trước bạn đã chốt: **SQS** để decouple và buffer, **SNS** để fan-out, **EventBridge** để định tuyến sự kiện, **Step Functions** để điều phối workflow. Giờ hệ thống đó chạy thật: message có bị kẹt trong queue không, Lambda có timeout không, event có tới đúng target không. Trả lời những câu đó chính là việc của CloudWatch và X-Ray.

> [!NOTE]
> Câu hỏi troubleshooting trong đề thường bắt đầu bằng "ứng dụng chạy chậm, developer cần biết service nào gây ra độ trễ". Từ khoá đó gần như luôn trỏ về **X-Ray**, không phải CloudWatch.

## Lý thuyết

### Ba tín hiệu, hai dịch vụ

| Tín hiệu | Trả lời câu hỏi | Dịch vụ | Chi phí |
| --- | --- | --- | --- |
| Metric | "Hệ thống có bất thường không?" | CloudWatch Metrics | Rẻ, cảnh báo tự động |
| Log | "Chuyện gì đã xảy ra chính xác?" | CloudWatch Logs | Theo dung lượng nạp/lưu |
| Trace | "Request đi qua đâu và chậm ở đâu?" | X-Ray | Theo trace ghi được |

Bạn cài đặt một bộ đếm công tơ điện, đọc hoá đơn và xem camera từng phòng. Metric là công tơ, log là hoá đơn chi tiết, trace là camera ghi lại đường đi của khách trong nhà.

### CloudWatch Metrics

Mỗi metric thuộc một **namespace**, được nhận diện bằng tên và tối đa 30 **dimension**. Statistic hay dùng: Average, Sum, Maximum, p99.

- EC2 **basic monitoring**: period {{c1::5 phút}}. **Detailed monitoring**: {{c2::1 phút}}, bật thêm và tính phí.
- Custom metric độ phân giải cao (high-resolution) xuống tới **1 giây**, gửi qua `PutMetricData` hoặc CloudWatch Agent.
- Metric do hypervisor cung cấp **không có RAM và disk usage**. Muốn có phải cài CloudWatch Agent trên instance.

> [!WARNING]
> Bẫy kinh điển: đề hỏi "làm sao alarm khi EC2 dùng quá 80% RAM". Đáp án không bao giờ là "bật detailed monitoring". Đáp án đúng là cài **CloudWatch Agent** để đẩy custom metric `mem_used_percent`.

### CloudWatch Logs

Cấu trúc: **log group** chứa nhiều **log stream**. Hai điểm thi hay hỏi:

- **Retention mặc định là Never expire**, phải set thủ công, và có thể mã hoá bằng KMS.
- **Metric filter** biến một pattern trong log thành metric (ví dụ đếm số lần `ERROR`), rồi gắn alarm lên metric đó. Metric filter **chỉ áp dụng cho log event mới**, không tính hồi tố các log đã ghi trước đó.
- **Subscription filter** đẩy log theo thời gian thực sang Lambda, Kinesis Data Streams hoặc Firehose.

### CloudWatch Alarms

Một alarm có ba state: OK, ALARM và {{c4::INSUFFICIENT_DATA}}. Cấu hình gồm **period**, **evaluation periods** và số datapoint cần vi phạm (M of N). Action có thể là gửi SNS, thực hiện EC2 action (stop, terminate, reboot) hoặc trigger Auto Scaling. **Composite alarm** gộp nhiều alarm con để giảm nhiễu on-call.

Tuỳ chọn `treat missing data` quyết định alarm phản ứng thế nào khi không có datapoint: `breaching`, `notBreaching`, `ignore`, `missing`.

### X-Ray

Kiến trúc: SDK trong app gửi segment tới **X-Ray daemon**, daemon gửi lên dịch vụ X-Ray.

- **Segment** = một request. **Subsegment** = một lời gọi downstream (DynamoDB, S3, HTTP, hàm khác).
- **Service map** trực quan hoá luồng đi và tỉ lệ lỗi, độ trễ từng node.
- **Annotation** được index nên tìm kiếm/lọc được; **metadata** thì không index, chỉ để xem chi tiết.
- **Sampling mặc định**: {{c6::1 request/giây}} cộng thêm 5% lưu lượng vượt ngưỡng đó. Có thể tạo custom sampling rule.
- Với Lambda chỉ cần bật **Active Tracing**. Với EC2, ECS, on-premise bạn phải tự chạy daemon và cấp quyền `xray:PutTraceSegments`, `xray:PutTelemetryRecords` trong IAM.

### Chọn công cụ nào?

```mermaid
flowchart TD
    A["🔴 Sự cố production"] --> B["📊 Metric có bất thường?"]
    B -->|Có| C["Xem dimension, period, alarm state"]
    B -->|Không rõ| D["📝 Logs Insights tìm lỗi"]
    D --> E["🔍 Service map X-Ray"]
    C --> E
    E --> F["Tìm subsegment chậm nhất"]
```

Rule of thumb: **CloudWatch nói "có chuyện", X-Ray nói "chuyện ở đâu"**.

## Ví dụ minh hoạ

**Ví dụ 1: tính thời gian alarm kêu.** Alarm có period 60 giây, evaluation periods = 3, datapoints to alarm = 2 of 3. Cần ít nhất 2 trong 3 điểm dữ liệu vi phạm, mỗi điểm cách nhau 60 giây, nên thời gian tối thiểu để chuyển sang ALARM là 2 phút, tối đa 3 phút nếu điểm vi phạm rơi vào các cửa sổ xa nhau.

**Ví dụ 2: ước lượng sampling của X-Ray.** API nhận 200 request/giây. Sampling mặc định = 1 + 5% × (200 − 20) ≈ 10 request/giây được trace. Muốn trace nhiều hơn cho một endpoint quan trọng, tạo custom sampling rule theo URL.

**Ví dụ 3: chẩn đoán từ đầu đến cuối.** API Gateway trả 504. Bước 1, metric `Latency` của API Gateway vượt ngưỡng, alarm vào ALARM. Bước 2, Logs Insights trên log group của Lambda thấy nhiều dòng `Task timed out after 3.00 seconds`. Bước 3, mở trace trên X-Ray: segment của Lambda có subsegment gọi DynamoDB chiếm 2.9 giây trong tổng 3 giây. Kết luận: nguyên nhân gốc là truy vấn DynamoDB (thiếu index hoặc bị throttle), không phải API Gateway.

## Thảo luận và phản tư

1. Với hệ thống SQS + Lambda bạn vừa học ở bài trước, bạn sẽ đặt alarm trên metric nào để phát hiện consumer bị tắc? (`ApproximateAgeOfOldestMessage` là một gợi ý.)
2. Vì sao metric filter không tính lại log cũ lại quan trọng khi bạn vừa triển khai filter cho một sự cố đã xảy ra?
3. Nếu chi phí X-Ray tăng gấp ba, bạn sẽ đổi sampling rule hay đổi cách dùng annotation? Vì sao?

## Góc chuyên gia

- **Đọc kỹ chủ thể trong câu hỏi.** "Developer cần biết service nào chậm" → X-Ray. "Cần cảnh báo khi tỉ lệ lỗi tăng" → CloudWatch alarm trên metric filter. Đừng chọn theo cảm giác.
- **INSUFFICIENT_DATA** xuất hiện khi metric chưa từng được publish hoặc vừa tạo alarm. Đề hay hỏi "alarm ở trạng thái này dù app vẫn chạy", đáp án thường là sai namespace, sai dimension hoặc instance không có agent.
- **Metric filter đếm trên log event**, không phải trên request đã xử lý thành công. Nếu app log 2 dòng cho mỗi lỗi, metric sẽ gấp đôi thực tế.
- **Annotation để lọc, metadata để debug.** Đặt `userId`, `orderId` vào annotation; đặt payload lớn vào metadata.
- **Đừng bật detailed monitoring cho mọi thứ.** Nó chỉ đổi 5 phút thành 1 phút; nếu đề cần độ phân giải giây thì phải là high-resolution custom metric.
- **X-Ray không thay thế log.** Trace cho biết chỗ chậm, log cho biết lý do. Đề DVA-C02 rất thích ghép hai công cụ trong một đáp án.

## Tóm tắt và bước tiếp theo

Bốn câu chốt: **CloudWatch Metrics** để cảnh báo, **CloudWatch Logs** để điều tra chi tiết, **metric filter** để biến log thành alarm (chỉ áp dụng cho dữ liệu mới), **X-Ray** để tìm service gây lỗi với annotation được index và sampling mặc định 1 request/giây cộng 5%. Nhớ hai bẫy lớn: RAM/disk của EC2 cần CloudWatch Agent, và alarm có thể nằm ở INSUFFICIENT_DATA.

```flashcard
[
  { "front": "Ba tín hiệu giám sát chính là gì?", "back": "Metric (CloudWatch), log (CloudWatch Logs), trace (X-Ray)." },
  { "front": "EC2 basic monitoring có period bao nhiêu?", "back": "5 phút." },
  { "front": "EC2 detailed monitoring có period bao nhiêu?", "back": "1 phút, bật thêm và tính phí." },
  { "front": "High-resolution custom metric đạt độ phân giải nào?", "back": "1 giây." },
  { "front": "Vì sao metric mặc định của EC2 không có RAM và disk usage?", "back": "Vì chỉ lấy từ hypervisor; cần CloudWatch Agent để đẩy custom metric." },
  { "front": "Ba state của CloudWatch alarm?", "back": "OK, ALARM, INSUFFICIENT_DATA." },
  { "front": "Metric filter áp dụng cho log cũ hay log mới?", "back": "Chỉ cho log event mới, không hồi tố." },
  { "front": "CloudWatch Logs giữ log bao lâu nếu không cấu hình?", "back": "Never expire, phải set retention thủ công." },
  { "front": "Composite alarm dùng để làm gì?", "back": "Gộp nhiều alarm con để giảm nhiễu và tạo cảnh báo theo điều kiện phức hợp." },
  { "front": "Sampling mặc định của X-Ray?", "back": "1 request/giây cộng 5% lưu lượng vượt ngưỡng." },
  { "front": "Annotation khác metadata ở điểm nào?", "back": "Annotation được index nên lọc/tìm kiếm được; metadata chỉ để xem chi tiết." },
  { "front": "Lambda cần làm gì để gửi trace lên X-Ray?", "back": "Bật Active Tracing trên function, không cần tự chạy daemon." },
  { "front": "Segment và subsegment khác nhau thế nào?", "back": "Segment là một request; subsegment là một lời gọi downstream trong request đó." },
  { "front": "Công cụ nào trả lời 'service nào gây độ trễ'?", "back": "X-Ray service map và trace." }
]
```

Bài tiếp theo sẽ chuyển sang phần chiến thuật: các bẫy thường gặp trong đề DVA-C02 và cách phân bổ thời gian cho 65 câu trong 130 phút, trong đó có những bẫy giám sát bạn vừa học.
