Skip to content

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 series

Quan 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.

bash
# 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"}
bash
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.

bash
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 services
  • status_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 đề:

  1. 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.

  2. 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.

  3. Cardinality explosion: Nếu bạn dùng field như user_id, request_id, hay trace_id là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 type
  • logging.googleapis.com/byte_count — bytes per sink destination
  • logging.googleapis.com/error_count — sink errors
  • logging.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 create hay Cloud Console
  • Naming convention: logging.googleapis.com/user/YOUR_METRIC_NAME

Alerting từ Log-based Metrics

Log-based metric alerting: pattern phổ biến

yaml
# 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-sre

Log-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:

bash
# 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-ops

So sánh hai cách:

Log-based Metric AlertDirect Log Alert
Latency~1-2 phút (qua metric pipeline)~30 giây (gần real-time)
AggregationCó (count, rate, percentile)Không — per entry
ThresholdCó (threshold trên count/rate)Không — mỗi entry trigger một alert
CostTính phí metric storageKhông thêm phí
Use caseSustained error ratesOne-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 đa500 per project
Labels per metric10
Length của label keyMax 100 characters
Length của label valueMax 1024 characters
Histogram buckets tối đa200
Metric update interval60 giây
Alert evaluation intervalTố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

bash
# 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 overwhelmed

Giải pháp: Aggregate ở log level trước khi extract label, hoặc dùng hashed bucket:

bash
# Đú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 extraction

Anti-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.


References