跳轉到

8.1 Workers Observability 與 Logpush#

本節目標#

  • 理解為什麼邊緣運算的可觀測性(observability)比傳統伺服器更難:沒有 SSH、沒有 log 檔案。
  • 學會開啟 Workers Observability 並在 Dashboard 閱讀 stats(請求數、錯誤率、CPU 時間、日誌流)。
  • 用 wrangler tail 在本地終端機即時收到邊緣節點的 log。
  • 建立从 Workers 到 R2 的 Logpush 管線,把日誌變成可以長期查詢的資料資產。

沒有機器,日誌該怎麼查?#

傳統部署用 ssh 進機器看 /var/log/app.log;但在 Workers 上:

  • 全球數百個 PoP 同時執行你的 isolate,log 分散在世界各地
  • isolate 隨時被回收,沒有持久的檔案系統可寫
  • 你甚至不知道請求落在哪個節點

因此 Cloudflare 把「日誌蒐集」做成平台服務,分三個層次:

層次 工具 適用情境 保留期
短期平台檢視 Observability Dashboard 上直接看 stats 與 console.log 的輸出 保留約 3 天
本地即時 wrangler tail 開發時即時看 log 串流式,不保存
長期儲存 Logpush → R2 上線後稽核、分析 自己決定(存多久都行)

分層消費:開發期看 tail、上線初期看 Observability、正式營運靠 Logpush 落地分析。

第一步:開啟 Observability#

在 wrangler.toml 加一行即可(2024 起正式 GA):

name = "my-worker"
main = "src/index.ts"
compatibility_date = "2025-01-01"

[observability]
enabled = true
head_sampling_rate = 1.0   # 取樣率 1.0 = 全收;高流量站可調 0.1 省 log 額度

開啟後每個請求的 console.* 輸出、invocation 結果(成功/錯誤/例外)、CPU 時間都會被自動蒐集,不需要你寫任何蒐集程式碼。

取樣率的精神:日誌量與流量呈線性關係,若每百億請求留 1 億份樣本就足以看見長尾,就沒必要付 100% 的錢。這是統計取樣(stratified sampling)在可觀測性的直接應用。

Dashboard 版面(三個最重要的指標)#

Analytics 分頁
├─ Requests     每分鐘請求數(看尖峰、看放量趨勢)
├─ Errors       錯誤率與類型(Exceptions vs Invocations failed)
├─ CPU Time     每請求 CPU 毫秒分布(P50/P99)
└─ Logs         即時日誌流

判讀心法:

  • Errors 突然升高:先看是 no response(程式沒回應,多是忘了 await)還是拋出例外(訊息會完整顯示)。
  • CPU Time 的 P99 逼近 30ms(Paid 上限):表示要重構熱路徑了,否則未來會被限流。
  • 曲線圖對照「有沒有快取」:8.2 節將用同張圖驗證快取命中率。

第二步:wrangler tail 即時串流#

開發期最快的手法:

npx wrangler tail --format pretty    # 人類可讀
npx wrangler tail --format json     # 給 jq 分析
# 只看指定類型(options: exception, cancellation_error 等)
npx wrangler tail --status error

輸出示例(pretty):

GET my-worker.example.workers.dev/ - Ok @ 2025/05/12 08:23:41
    id: 9a27...  GET /api/todo
    log: [info] loading todos for user=42
    log: [error] SQLITE_BUSY: database is locked (took 4ms)

注意:tail 顯示的是觀測到你本機收到的請求的 log,範圍覆蓋所有 PoP(由 Fluent Bit 管道回傳),因此外網同事打線上 worker 你也看得到。它是「看見」而非「保存」——關掉終端機就沒了。

第三步:Logpush 到 R2(長期歸檔)#

當日誌需要超過平台保留期、或要接外部分析(ClickHouse、BigQuery),就用 Logpush:Cloudflare 把 Workers 的 invocation log 批次推送到你的物件儲存。Workers 的 invocation logs 走 cloudworkers 來源,推送目標可選 R2(自家的零出口費儲存,最順)。

[PoP isolate] --(批次 1min/1GB 觸發)--> [Logpush 管道] --> R2 bucket
                                                  workers-logs/date=2025-05-12/part-xxxx.json.gz

設定流程:

# 1. 建 R2 bucket
npx wrangler r2 bucket create worker-logs

# 2. 用 API 建立 Logpush job(示意,token 需有 Logpush 編輯權限)
# POST /accounts/{account_id}/logpush/jobs
{
  "name": "worker-logs-to-r2",
  "source": "cloudworkers",        # Workers invocation logs
  "destination": "r2",
  "destination_conf": "settings={\"bucket\": \"worker-logs\", \"prefix\": \"workers/\", \"compression\": \"gzip\"}",
  "dataset_fields": ["Timestamp", "Outcome", "EventLogs", "EventRequestPath", "CPUTime"]
}

Logpush 是批次系統(快取寫滿或時間到才 flush),不保證分鐘級即時,但 高吞吐且 cheap——這正是「邊緣即時排查靠 tail,歷史線索靠 R2」的分工。

R2 收到的檔案是 newline-delimited JSON(NDJSON),每行一筆 invocation,方便之後用任何工具處理:

# 篩出所有失敗的請求並只留路徑
zcat workers/date=2025-05-12/part-000.gz \
  | jq 'select(.Outcome == "exception" or .Outcome == "exceededCpu") | .EventRequestPath'

小結與練習#

重點回顧

  1. 邊緣沒有機器可 SSH,可觀測性必須以「平台服務」補位:Observability(短期)、tail(即時)、Logpush(長期)。
  2. observability.enabled = true 一行即開啟,head_sampling_rate 控制取樣率以省錢。
  3. Logpush 是批次推送、R2 是零出口費(egress free),組合天然適合做稽核與外部分析。

練習

  1. 幫第 7 章的 Worker 加上 Observability,故意寫入一個 throw new Error("boom") 的路徑,觀察 Dashboard 的 exception 型態與 tail --status error 的呈現差異。
  2. 把 head_sampling_rate 改成 0.5,連打 10 次請求,數一數 Observability 收到幾筆,驗證取樣率語意。
  3. 建一個 Logpush 到 R2,下載一天份 NDJSON,用 jq 統計每個 path 的請求數排序前十名。