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'
小結與練習#
重點回顧
- 邊緣沒有機器可 SSH,可觀測性必須以「平台服務」補位:Observability(短期)、tail(即時)、Logpush(長期)。
observability.enabled = true一行即開啟,head_sampling_rate控制取樣率以省錢。- Logpush 是批次推送、R2 是零出口費(egress free),組合天然適合做稽核與外部分析。
練習
- 幫第 7 章的 Worker 加上 Observability,故意寫入一個
throw new Error("boom")的路徑,觀察 Dashboard 的 exception 型態與tail --status error的呈現差異。 - 把
head_sampling_rate改成 0.5,連打 10 次請求,數一數 Observability 收到幾筆,驗證取樣率語意。 - 建一個 Logpush 到 R2,下載一天份 NDJSON,用
jq統計每個 path 的請求數排序前十名。