Log-based Metrics & Alerting
Tại sao Log-based Metrics quan trọng
Không phải mọi sự kiện quan trọng đều có sẵn metric. GCP cung cấp hàng nghìn predefined metrics cho infrastructure, nhưng business-level events — số lượng payment failures, số lần retry một operation cụ thể, tỷ lệ lỗi của một API endpoint nội bộ — chỉ xuất hiện trong logs.
Log-based metrics là cầu nối: chúng cho phép bạn biến patterns trong logs thành Cloud Monitoring time series, và từ đó tạo alert, dashboard, và SLO dựa trên những patterns đó.
Nhưng log-based metrics có timing model khác với infrastructure metrics, cardinality constraints cần tính đến, và cost implications khi số lượng label combinations tăng lên. Hiểu internal model giúp tránh những pitfall phổ biến.
Internal Model: Cách Log-based Metrics Được Tính Toán
Từ log entry đến time series
Khi bạn tạo một log-based metric với một filter, Cloud Logging không re-process historical logs. Metric chỉ bắt đầu track từ thời điểm tạo. Điều này có hệ quả: bạn không thể backfill metric từ logs cũ.
Quá trình tính toán:
Log Entry arrives → Log Router evaluates
│
▼ (nếu entry match metric filter)
Metric processing pipeline
│
├── Counter: increment in-memory counter
│ per label combination
│
└── Distribution: extract numeric value,
update histogram buckets
│
▼ (mỗi 60 giây)
Write to Cloud Monitoring time seriesQuan trọng: Metric được update mỗi phút, không real-time. Khi một error xảy ra lúc 14:00:30, nó xuất hiện trong metric lúc 14:01:00 (hoặc 14:02:00 tùy timing của write cycle). Đây là lý do log-based metric alerting có inherent latency khoảng 1-2 phút.
Behavior khi không có entries:
- Nếu interval T có entries → giá trị non-zero được ghi
- Nếu interval T không có entries nhưng T-1 có → giá trị zero được ghi (đảm bảo trend thấy được)
- Nếu cả T và T-1 đều không có entries → data gap (không ghi gì), không phải zero
Data gap quan trọng với alerting: một alert policy configured với no data behavior cần biết data gap không có nghĩa là metric = 0.
Counter Metrics
Counter metrics đếm số log entries matching một filter trong mỗi 1-phút interval.
# Tạo counter metric: đếm số lần HTTP 5xx
gcloud logging metrics create http_5xx_errors \
--description="Count of HTTP 5xx responses" \
--log-filter='resource.type="http_load_balancer"
httpRequest.status>=500'Metric name trong Cloud Monitoring: logging.googleapis.com/user/http_5xx_errors
Labels: Labels extract values từ matching log entries, tạo separate time series per unique label combination. Ví dụ, nếu bạn add label status_code extract từ httpRequest.status:
- Entry với status=500 → time series
{status_code="500"} - Entry với status=503 → time series
{status_code="503"}
gcloud logging metrics create http_errors_by_status \
--description="HTTP errors by status code" \
--log-filter='httpRequest.status>=500' \
--label-extractors='status_code=EXTRACT(httpRequest.status)'Distribution Metrics
Distribution metrics không chỉ đếm — chúng extract một numeric value từ mỗi matching entry và tính toán thống kê (mean, stddev, histogram buckets) trên những values đó.
Use case điển hình: response latency từ log entries.
gcloud logging metrics create request_latency \
--description="Request latency distribution" \
--log-filter='resource.type="cloud_run_revision"
httpRequest.latency!=""' \
--value-extractor='EXTRACT(httpRequest.latency)' \
--histogram-buckets='[0,1,5,10,50,100,500,1000,5000,10000]'Histogram buckets xác định boundaries (tính bằng milliseconds trong ví dụ này). Cloud Monitoring sau đó tính percentiles (p50, p95, p99) từ histogram data.
Lưu ý về value extraction: Value extractor dùng EXTRACT(field_path) để lấy giá trị từ một field cụ thể. Field phải là numeric (integer hoặc float). Nếu field là string (ví dụ "1.23s"), cần dùng REGEXP_EXTRACT và convert.
Label Design và Cardinality Constraints
Cardinality là gì và tại sao quan trọng
Cardinality = số lượng unique time series được tạo ra bởi metric. Mỗi unique combination của label values tạo một time series.
Ví dụ với 3 labels:
service_name: 50 servicesstatus_code: 50 possible codes (4xx, 5xx)region: 20 regions
Worst case: 50 × 50 × 20 = 50,000 time series từ một metric duy nhất.
Tại sao đây là vấn đề:
Cost: Mỗi active time series được tính là một custom metric. User-defined log-based metrics tính phí theo số time series active. Giá khoảng $0.10/active time series/tháng sau free tier.
Alerts performance: Alert policies với nhiều time series chạy chậm hơn. Tổng hợp cần nhiều compute hơn.
Cardinality explosion: Nếu bạn dùng field như
user_id,request_id, haytrace_idlàm label, mỗi user/request/trace tạo một time series riêng → cardinality nhanh chóng đến hàng triệu.
Rule of thumb: Không dùng field với unbounded cardinality làm label. Labels nên là:
- Categorical values với known finite set (region, environment, status_code_range)
- Low cardinality fields (service_name với tổng < 100 services)
System-defined vs User-defined Metrics
System-defined log-based metrics (cung cấp bởi Google, không tính phí như custom metrics):
logging.googleapis.com/billing/bytes_ingested— volume ingested per resource typelogging.googleapis.com/byte_count— bytes per sink destinationlogging.googleapis.com/error_count— sink errorslogging.googleapis.com/log_entry_count— entries per resource type
User-defined log-based metrics (bạn tạo, tính phí như custom metrics):
- Mọi metric tạo qua
gcloud logging metrics createhay Cloud Console - Naming convention:
logging.googleapis.com/user/YOUR_METRIC_NAME
Alerting từ Log-based Metrics
Log-based metric alerting: pattern phổ biến
# Alert policy cho HTTP 5xx spike
# Trigger khi 5xx > 100 trong 1 phút, sustained 5 phút
alertPolicy:
displayName: "HTTP 5xx Error Spike"
conditions:
- displayName: "5xx errors > threshold"
conditionThreshold:
filter: 'metric.type="logging.googleapis.com/user/http_5xx_errors"'
aggregations:
- alignmentPeriod: 60s
perSeriesAligner: ALIGN_RATE # Rate per second
crossSeriesReducer: REDUCE_SUM
groupByFields: ["resource.type"]
comparison: COMPARISON_GT
thresholdValue: 1.67 # 100 errors/minute = 1.67/second
duration: 300s # Sustained 5 phút
notificationChannels:
- projects/my-project/notificationChannels/pagerduty-sreLog-based alerting vs Direct log alerting
Cloud Logging cũng hỗ trợ direct log alerting — alert được trigger trực tiếp khi log entry match filter, không cần qua metric:
# Tạo log-based alert trực tiếp
gcloud alpha logging alerts create \
--display-name="Critical Error Alert" \
--condition-filter='severity=CRITICAL AND resource.type="k8s_container"' \
--notification-channels=projects/my-project/notificationChannels/slack-opsSo sánh hai cách:
| Log-based Metric Alert | Direct Log Alert | |
|---|---|---|
| Latency | ~1-2 phút (qua metric pipeline) | ~30 giây (gần real-time) |
| Aggregation | Có (count, rate, percentile) | Không — per entry |
| Threshold | Có (threshold trên count/rate) | Không — mỗi entry trigger một alert |
| Cost | Tính phí metric storage | Không thêm phí |
| Use case | Sustained error rates | One-time critical events |
Direct log alerting tốt cho: database connection failure, security breach events, OOM kills — những event mà một occurrence duy nhất cũng đủ nghiêm trọng để page.
Log-based metric alerting tốt cho: error rate thresholds, latency percentile alerts, volume-based alerts — nơi cần aggregation trước khi trigger.
Tích Hợp với Cloud Monitoring
Log-based metrics xuất hiện trong Cloud Monitoring như các custom metrics khác:
Cloud Monitoring
├── Custom Metrics
│ └── logging.googleapis.com/user/* ← Log-based metrics của bạn
├── System Metrics
│ └── logging.googleapis.com/* ← System-defined log metrics
└── External Metrics
└── (GKE, Prometheus, etc.)Có thể dùng log-based metrics trong:
- Dashboards: Chart theo thời gian, so sánh environments
- Alert Policies: Threshold, rate of change, SLO violation
- SLO/Error Budget: Dùng SLI metric từ log data (ví dụ: good requests = 2xx responses)
Ví dụ SLO từ log-based metric:
SLI: count(HTTP 2xx) / count(HTTP total)
SLO: 99.9% trong 30 ngày rolling window
Metrics cần:
- good_requests: filter httpRequest.status>=200 AND httpRequest.status<300
- total_requests: filter resource.type="http_load_balancer"Constraints và Limitations
| Tham số | Giá trị |
|---|---|
| Số user-defined log-based metrics tối đa | 500 per project |
| Labels per metric | 10 |
| Length của label key | Max 100 characters |
| Length của label value | Max 1024 characters |
| Histogram buckets tối đa | 200 |
| Metric update interval | 60 giây |
| Alert evaluation interval | Tối thiểu 60 giây |
Không thể tạo log-based metric counting error groups từ Error Reporting, và không thể extract Error Reporting ID vào label — đây là documented limitation.
Anti-patterns
Anti-pattern: Label có unbounded cardinality
# SAI: user_id là unbounded cardinality
gcloud logging metrics create user_api_calls \
--label-extractors='user_id=EXTRACT(httpRequest.userId)'
# Nếu có 1 triệu users, tạo ra 1 triệu time series
# → Exploding cost, monitoring system overwhelmedGiải pháp: Aggregate ở log level trước khi extract label, hoặc dùng hashed bucket:
# Đúng hơn: extract chỉ categorical dimension
gcloud logging metrics create user_api_calls \
--label-extractors='api_endpoint=EXTRACT(httpRequest.requestUrl)'
# api_endpoint có bounded set nếu route-level extractionAnti-pattern: Tạo metric với filter quá broad
Log-based metric với filter match mọi entries sẽ tính phí custom metric tương ứng với số time series, có thể rất lớn. Luôn filter càng specific càng tốt.