Cloud Logging 簡介 (Introduction to Cloud Logging)
在任何分散式系統中,日誌 (Logs) 都是「發生了什麼事」的基本記錄。Cloud Logging 是一項全託管服務,可讓你儲存、搜尋、分析、監控來自 Google Cloud 及其他來源的日誌數據與事件,並針對其設定警報。配合能自動歸類當機與異常狀況的 Error Reporting,它為即時疑難排解與長期稽核提供了強大的工具集。
白話文解釋 Logging and Error Reporting
類比 1 — 飛機黑盒子 (The Black Box Flight Recorder)
Cloud Logging 就像飛機上的黑盒子。它記錄了每一次按鈕的按下、每一次引擎溫度的變化以及每一次通訊。如果飛機平安降落,你可能永遠不會去看它;但如果出了問題,它就是調查人員了解事件順序的首要來源。
類比 2 — 醫療紀錄 (The Medical Record)
日誌記錄就像病人的醫療紀錄,記錄了每一次就診、每一種症狀和每一種藥物。Error Reporting 則像是急診室 (ER) 的檢傷分類系統。它發現有 50 個人帶著相同的症狀(歸類的異常 Grouped Exception)來到醫院,並提醒工作人員這可能是食物中毒爆發(應用程式 Bug),而不是 50 起無關的意外。
類比 3 — 圖書館檔案館 (The Library Archive)
日誌記錄是圖書館檔案館。每天都有成千上萬份報紙(日誌)送達。日誌路由器 (Log Router) 就像是管理員,負責決定哪些報紙留在主閱覽室(日誌值筒 Log Bucket),哪些送到地下室進行長期儲存(Coldline GCS),哪些送到研究室進行分析 (BigQuery)。
日誌接收器 (Log Sink):一種配置,指示 Cloud Logging 將特定日誌匯出到 BigQuery、Cloud Storage 或 Pub/Sub 等目的地。
日誌路由與儲存 (Log Routing and Storage)
Cloud Logging 使用「路由器 (Router)」來處理傳入的日誌:
- 擷取 (Ingestion): 日誌來自 GCE、GKE 或透過 API 傳入。
- 排除過濾器 (Exclusion Filters): 捨棄「雜訊」日誌(如成功的健康檢查)以節省成本。
- 接收器 (Sinks): 將日誌匯出至:
- Cloud Storage: 用於長期、低成本的合規性儲存(保留期 Retention)。
- BigQuery: 用於複雜的 SQL 分析和安全性數位鑑識。
- Pub/Sub: 即時串流至外部 SIEM 或自動化補救腳本。
- 日誌值筒 (Log Buckets): Logs Explorer 內搜尋功能的預設儲存空間。
Log Router Sinks 深入解析 — BigQuery、GCS、Pub/Sub、Splunk
Log Router 是每一筆日誌的分岔路口:每一行都會被所有啟用的 sink 規則比對一次,零個、一個或多個 sink 都可能命中。理解每種 sink 目的地,是 PCA 合規、分析、SIEM 整合題目的關鍵。
BigQuery Sink
適合需要對日誌做 SQL 分析、JOIN 或 BI 儀表板的場景。
- 分區資料表 (Partitioned tables)(建議):每個日誌流一張分區表,依
timestamp分區。建立 sink 時加上--use-partitioned-tables。 - Schema 演進: 當
jsonPayload出現新欄位,Cloud Logging 會自動加欄;舊資料列保留原始 schema。 - 延遲: 端到端通常 60-120 秒。
Cloud Storage Sink
適合封存、WORM 合規、或 7 年稽核保留等最低成本場景。
- 日誌以每小時 JSON 檔案落在
gs://<bucket>/<log-id>/YYYY/MM/DD/HH/。 - 搭配 Bucket Lock + Retention Policy 來滿足 SEC/HIPAA 不可變寫入要求。
- 用 lifecycle 規則自動轉換到 Nearline → Coldline → Archive。
Pub/Sub Sink
適合即時 fan-out 到 Dataflow、Splunk、Chronicle 或第三方 SIEM。
- 每一筆日誌變成一個 Pub/Sub 訊息;下游消費者必須處理 at-least-once 投遞。
- 常見模式:
Logs Router → Pub/Sub → Dataflow → BigQuery + Chronicle。
Splunk via Pub/Sub + Dataflow Template
GCP 提供 Google 維護的 Pub/Sub-to-Splunk Dataflow 範本 (HEC),把日誌串流進 Splunk HTTP Event Collector。它處理批次、重試、與 dead-letter queue;這是把 GCP 日誌集中到既有地端 Splunk SIEM 的官方零程式碼路徑。
Sink IAM 陷阱: 每個 Log Router sink 都用一個由 Cloud Logging 自動建立的寫入者服務帳戶 (writer service account) 執行。建立 sink 之後,你必須在目的地授予該服務帳戶 roles/bigquery.dataEditor、roles/storage.objectCreator 或 roles/pubsub.publisher;否則日誌會靜默丟失且沒有任何可見錯誤。用 gcloud logging sinks describe SINK_NAME 查出寫入者身分。
Cloud Error Reporting
Error Reporting 會自動分析日誌中的常見異常模式(例如 Java、Python 或 Go 中的堆疊追蹤 Stack Traces)。
- 自動歸類 (Auto-Grouping): 相似的錯誤會被歸類在一起,因此你會看到「發生 50 次」,而不是 50 條獨立的日誌。
- 警報 (Alerting): 當生產環境中出現「新類型」的錯誤時,立即獲得通知。
- 連結至程式碼: 如果你的原始碼位於 Cloud Source Repositories 中,Error Reporting 可以將堆疊追蹤直接連結到對應的程式碼行。
日誌記錄的最佳實踐
- 結構化日誌 (Structured Logging): 始終使用 JSON 格式記錄。這讓你可以根據特定欄位(如
jsonPayload.user_id)進行過濾,而不是進行緩慢的字串搜尋。 - 保留策略 (Retention Policies): 為不同的日誌設定不同的保留期。稽核日誌可能需要保留 7 年,而除錯日誌可能只需要 30 天。
- 數據遮罩 (Data Masking): 在儲存之前,使用日誌路由器脫敏或遮蓋 PII(個人身份資訊)。
架構師洞察: 對於 PCA 考試,如果你需要對日誌數據進行「針對安全威脅的即時分析」,正確的架構是 Logs Router -> Pub/Sub -> Dataflow -> BigQuery。 ::
基於日誌的指標 (Log-Based Metrics) — Counter vs Distribution
Log-based metrics 把日誌內容轉成 Cloud Monitoring 可以畫圖、可以警報的 time-series 指標。兩種型態,成本與用途差距很大。
Counter 指標
- 計算符合條件的日誌筆數。
- 範例 filter:
severity=ERROR AND resource.type="cloud_run_revision"→ 產生 1-D 整數指標。 - 適合 SLO error budget、「5xx 暴衝」警報、或「失敗登入次數」。
Distribution 指標
- 從每筆日誌擷取一個數值(例如
jsonPayload.latency_ms)並產生 histogram,含 p50/p95/p99 百分位數。 - 適合從日誌追蹤延遲 (latency) 的場景,特別是當你的應用程式無法直接吐 OpenTelemetry 指標時。
系統 vs 使用者自訂
- 系統 log-based metrics(例如
logging.googleapis.com/byte_count)免費且預先存在。 - 使用者自訂 log-based metrics 依照指標擷取量計費;維持 cardinality 低 — 每個 label 組合(特別像
user_id這類高 cardinality 的 label)都會倍增成本。
Labels 與欄位擷取
你可以用正規表達式或欄位擷取器把 jsonPayload 的欄位升級成指標 label。要小心:像 request_id 這種 label 會讓每個請求都產生一條 time series,把你的帳單炸開。
Distribution 指標陷阱: PCA 題目常問「我的舊系統只會寫純文字 log,怎麼追蹤 p99 延遲?」答案是搭配 regex 擷取器的 distribution log-based metric,不是 counter metric。Counter 只能告訴你發生幾次;Distribution 才能給出數值分佈與百分位數。
保留值筒 (Retention Buckets) — 自訂 vs 預設
Cloud Logging 把日誌存在 log buckets 裡,每個專案或資料夾層級都有。每個專案會自動建立兩個 bucket:
| Bucket | 預設保留期 | 用途 |
|---|---|---|
_Default |
30 天 | 所有非稽核日誌 |
_Required |
400 天(不可變) | Admin Activity + System Event 稽核日誌 |
自訂 Buckets
當你需要以下任一條件時,建立自己的 log bucket:
- 自訂保留期 從 1 天到 3650 天(10 年)。
- CMEK(客戶管理加密金鑰)— 只有使用者自建的 bucket 才能設定。
- 區域釘選 (Regional pinning) — 為了 GDPR,把歐盟日誌存在
europe-west1。
鎖定保留期 (Locked Retention)
對 bucket 套用 retention lock,設定的保留期就會變成不可變 — 任何人(包括 project owner)都不能縮短。這是 GCP 上日誌資料的 WORM 合規對應方案,SOX/PCI 場景必備。
Sink-to-Bucket 模式
用 Log Router sink 路由特定日誌流到自訂 bucket,例如:security 日誌 → 7 年鎖定 bucket;應用 debug 日誌 → 7 天便宜 bucket。這是同時滿足混合保留要求又不必匯出到 GCS 的最省錢方法。
排除過濾器與成本最佳化 (Exclusion Filters and Cost Optimization)
Cloud Logging ingestion 計費是每月每專案前 50 GiB 免費,之後 $0.50 / GiB。對於話多的 workload(GKE、load balancer、Cloud SQL 慢查詢),這項往往主宰了 observability 帳單。Exclusion filter 是主要的成本控制槓桿。
套用位置
排除過濾器掛在 sink 層級(包含隱含的 _Default sink)。被排除的日誌在計費前就被丟棄;它們不會進入任何 bucket,無法復原。
典型 Pattern
- 丟掉成功的健康檢查:
resource.type="http_load_balancer" AND httpRequest.status<400 AND httpRequest.requestUrl=~"/healthz" - 丟掉冗長的 GKE 控制平面日誌:
resource.type="k8s_container" AND severity<WARNING AND resource.labels.container_name="istio-proxy" - 取樣 10% 的 INFO 日誌:
severity=INFO AND sample(insertId, 0.10)(用sample()函式保持統計可信度)。
取樣 vs 排除
- 排除 (Exclusion) 丟掉 100% 符合條件的日誌。
- 取樣 (Sampling)(透過 filter 內的
sample())保留一定百分比 — 適合你還想留樣本作抽查。
成本 vs 可見性的權衡
過於激進的排除會藏住事件。永遠搭配在排除之前計算的 log-based metrics(指標會對所有 ingestion 的日誌計算,與 bucket 路由無關),這樣即使你丟掉原始日誌,仍然看得到計數。
省錢撇步: 打開 Console 的 Logs Storage 頁,依量級排序看誰是大戶。多數 GCP 專案裡,60-80% 的 ingestion 都來自 2-3 條吵雜的日誌流(LB access log、GKE system、VPC Flow)。光排除這三個通常就能砍掉一半帳單。
Error Reporting 歸類與去重 (Grouping and Deduplication)
Error Reporting 的價值在歸類 — 把 50,000 條 stack trace 變成 12 個可行動的錯誤群組。理解歸類演算法可以幫你寫出能正確歸類的可記錄錯誤。
歸類特徵 (Signature)
對每個錯誤,Error Reporting 從以下計算一組特徵:
- 例外型別 (例如
NullPointerException、ValueError)。 - Stack trace 的頂端 frames(通常是離 throw 最近的 3-5 個 frame)。
- Service + version(
checkout-svc的v1.2.3錯誤與v1.2.4的會被分開歸類)。
原生支援的語言
Error Reporting 原生解析 Java、Python、Go、Node.js、Ruby、PHP、.NET、C# 的 stack trace。其他語言則寫一筆結構化日誌帶上 @type: "type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent",Error Reporting 就會吃。
透過 API 手動回報
沒有原生支援的語言可以直接呼叫 Error Reporting API,或單純寫一條 log entry,把 ReportedErrorEvent proto 放在 jsonPayload 裡。後者是建議模式,因為它不挑 agent。
解決流程 (Resolution Workflow)
每個群組有狀態:Open → Acknowledged → Resolved → Muted。把錯誤標 Resolved 等於告訴 Error Reporting:若它再次出現,請重新警報(regression detection),所以 Resolved 有意義 — 不要批次清掉。
為什麼有時群組會意外分裂
若重新部署改動了 stack trace 的行號(例如 refactor),同一個邏輯 bug 可能產生新的群組。用 error_message filter 與 resolution timeline 視圖在心理上合併;目前沒有手動 merge 的 UI。
Cloud Logging API 與結構化日誌 jsonPayload
Cloud Logging API 透過 entries.write 接收日誌。生產等級日誌記錄最重要的單一欄位是 jsonPayload vs textPayload。
textPayload vs jsonPayload
textPayload:單一字串。搜尋是全文掃描 — 又慢又貴。jsonPayload:結構化物件。每個 key 都變成可查詢欄位:jsonPayload.user_id="u123"已索引、查詢快速。
保留的頂層欄位
在 jsonPayload 裡,特定 key 會被晉升到 LogEntry 的頂層欄位:
severity→LogEntry.severity(控制顏色 + 警報)。message→ 在 Logs Explorer 中顯示為摘要行。trace→LogEntry.trace(把日誌連結到 Cloud Trace 的 span)。spanId→ 啟用每個 span 的日誌篩選。httpRequest→ 填滿 HTTP request 面板。
Trace 關聯範例
{
"severity": "ERROR",
"message": "Payment timeout",
"logging.googleapis.com/trace": "projects/my-proj/traces/abc123",
"logging.googleapis.com/spanId": "span-456",
"jsonPayload": {"order_id": "o-789", "vendor": "stripe", "timeout_ms": 30000}
}
這筆 entry 會在 trace abc123 的 Cloud Trace waterfall 內聯出現 — 對 debug 分散式系統非常寶貴。
Ops Agent 自動解析
GCE 上的 Ops Agent 會自動偵測 stdout/stderr 中的 JSON 並解析到 jsonPayload。在 GKE 上,Logging operator 對 container stdout 做同樣的事。在最常見的情境下,只要把 JSON 寫到 stdout,不需要任何 SDK。
Client Libraries
複雜場景(自訂 monitored resource、大型 payload)使用官方 Logging client libraries(Python 的 google-cloud-logging、Node.js 的 @google-cloud/logging)。它們會批次寫入、自動處理重試。
稽核日誌 — Admin Activity vs Data Access vs System Event
Cloud Audit Logs 是 GCP 環境中不可妥協的鑑識紀錄:誰做了什麼。稽核日誌有四種不同型別,預設與成本影響各異。
1. Admin Activity(管理活動)
- 內容: 修改 metadata 或設定的 API 呼叫(建立 VM、改 IAM、刪除 bucket)。
- 預設: 永遠開啟、無法停用、免費。
- 保留期: 在
_Requiredbucket 保留 400 天。
2. Data Access(資料存取)
- 內容: 讀取或寫入使用者資料的 API 呼叫(
storage.objects.get、bigquery.jobs.create讀取資料表)。 - 預設: 多數服務停用(BigQuery 例外,預設開啟讀取記錄)。
- 成本: 按一般 Logging ingestion 計費;可能讓成本爆增 10-100 倍。
- 粒度: 三種子類型 —
ADMIN_READ、DATA_READ、DATA_WRITE。可逐服務選擇性啟用。
3. System Event(系統事件)
- 內容: GCP 主動發起的動作(live migration、host 維護、自動 key rotation)。
- 預設: 永遠開啟、免費。
- 用途: 把 workload 中斷與平台事件關聯起來。
4. Policy Denied(政策拒絕)
- 內容: 紀錄請求被 VPC Service Controls、Org Policy 或 IAM Conditions 拒絕的情況。
- 預設: 永遠開啟、免費。
- 用途: Debug「為什麼這個請求被擋?」— VPC-SC perimeter 推行期間特別寶貴。
啟用 Data Access Logs
透過 gcloud organizations set-iam-policy 或 Console 在 IAM Audit Config 中逐服務啟用。PCA 題目常暗示這點:「稽核誰讀取了敏感 BigQuery 資料表」→ 為 BigQuery 啟用 DATA_READ,路由到鎖定的 bucket。
PCA 場景判斷法則: 若題目問為了合規 (SOX/HIPAA/PCI) 提供不可變、防竄改、7 年保留的「誰做了什麼」紀錄,答案是 Admin Activity + Data Access 稽核日誌 → sink 到鎖定的 log bucket(或啟用 Bucket Lock 的 GCS bucket)並設定對應保留期。永遠不要只把稽核日誌存在預設 bucket — 它 400 天的上限低於多數合規要求。
Log Analytics on BigQuery
Log Analytics 讓你直接對 Cloud Logging bucket 跑 BigQuery SQL,不需要先匯出。2023 年 GA,許多分析場景因此不必再開一個 BigQuery sink。
運作方式
- 把一個 log bucket 升級為 Log Analytics-enabled(單向操作)。
- 該 bucket 的日誌可透過合成的 BigQuery dataset (
{project}.global._Default._AllLogs) 查詢。 - 也可以把 bucket 連結 為 BigQuery dataset,與你自己的 BigQuery 資料表 JOIN。
能力
- 標準 SQL,可用完整 BigQuery 函式(window function、regex、geo)。
- Schema:每筆日誌是一列,含
timestamp、severity、resource、json_payload、proto_payload。 - 查詢直接打 bucket 的底層儲存 — 沒有儲存重複,也沒有額外 ingestion 費。
成本模型
- 分析功能本身免費;只有當你把 bucket 連結為 BigQuery dataset 時,按 BigQuery 查詢掃描量計費。
- 在 Log Analytics UI 內的查詢,掃描 bucket 是包含的。
何時用 Log Analytics vs BigQuery Sink
| 需求 | 選擇 |
|---|---|
| 一次性的日誌 SQL 探索 | Log Analytics |
| 日誌與帳單 / 資產 / 外部資料表 JOIN | BigQuery Sink(或 Log Analytics 加連結 dataset) |
| 長期封存 + 儀表板 | 含分區的 BigQuery Sink |
| 事故當下不必設定就能寫 SQL | Log Analytics |
範例查詢
SELECT
TIMESTAMP_TRUNC(timestamp, MINUTE) AS minute,
COUNT(*) AS errors
FROM `my-proj.global._Default._AllLogs`
WHERE severity = 'ERROR'
AND resource.type = 'cloud_run_revision'
AND timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
GROUP BY minute
ORDER BY minute DESC;
日誌中的敏感資料遮罩 (Sensitive Data Redaction in Logs)
應用程式日誌是 GCP 環境裡 PII 洩漏的第一來源 — 開發者不假思索就把 request body、header、DB row 記下來。三層防禦,由內而外。
1. 擷取前清洗(最佳)
在應用程式碼裡於來源端清洗。用一個 logging interceptor 在呼叫 Logging API 之前剝除 password、ssn、credit_card 等欄位。這是唯一能保證敏感資料完全沒進 GCP 的方法。
2. Log Router 搭配 Cloud DLP
對於已經流經 Logs Router 的資料,走 Pub/Sub → 用 DLP Inspect 範本的 Dataflow → BigQuery/GCS。Dataflow 用 Cloud DLP 的 infoType detector(EMAIL_ADDRESS、US_SOCIAL_SECURITY_NUMBER、CREDIT_CARD_NUMBER)處理,可以遮蔽 (redact)(換成 [REDACTED])、遮罩 (mask)(***-**-1234)、或代幣化 (tokenize)(格式保留加密)。
3. 對 Log Bucket 做欄位層級存取控制
即便原始 PII 不小心落入 bucket,也可以用 Logging field-level IAM + bucket views 對多數使用者只開放遮罩過的視圖,把完整 bucket 鎖在一個小型安全群組(持有 roles/logging.privateLogViewer)後面。
Data Access Logs 本身也是敏感的
諷刺的是,Data Access logs 包含被存取的資源名稱 — 有時資源名稱本身就敏感(例如 storage.objects.get 於 gs://my-bucket/patient-12345/scan.dcm)。對稽核日誌 bucket 的保留期與存取控制,要用跟它所稽核的資料同等的嚴謹度來規劃。
應該避免的反模式
- 記錄整個 HTTP request body(生產環境只記 header)。
- 在
Authorization日誌行裡帶 JWT 或 session token。 - 把 SQL query 參數
WHERE ssn='123-45-6789'整段 dump — 在 log 之前先參數化。
記下四種稽核日誌: Admin Activity(永遠開啟、免費、修改設定)、Data Access(預設停用,BigQuery 例外、計費、讀寫資料)、System Event(永遠開啟、免費、GCP 發起)、Policy Denied(永遠開啟、免費、被政策擋下)。只有 Data Access 會花錢且需要明確啟用。
常見問題 — Cloud Logging (FAQ — Cloud Logging)
Q1. 「管理活動日誌 (Admin Activity)」與「數據存取日誌 (Data Access)」有什麼區別?
管理活動日誌記錄修改資源的 API 呼叫(如建立 VM),且始終免費。數據存取日誌記錄讀取或寫入數據的 API 呼叫(如讀取 GCS 物件),數據量可能非常大且昂貴;它們預設是停用的。
Q2. 我該如何降低日誌記錄成本?
使用排除過濾器捨棄不需要的日誌,並僅針對關鍵資源啟用數據存取日誌。此外,如果日誌僅用於合規性而非主動搜尋,請考慮將其路由至 Cloud Storage。
Q3. Cloud Logging 可以處理來自地端伺服器的日誌嗎?
可以,透過 Ops Agent 或 Logging API。你可以將所有日誌集中在 GCP 中,實現「單一介面 (Single Pane of Glass)」視圖。
Q4. 什麼是「基於日誌的警報 (Log-based Alert)」?
這是在日誌中出現特定模式(例如單字 "CRITICAL" 或特定錯誤碼)時觸發的警報。適用於沒有數值指標的事件。
Q5. Error Reporting 如何知道一個新錯誤是「新」的?
它維護著堆疊追蹤 (Stack Trace) 的特徵碼 (Signature)。如果傳入的堆疊追蹤與任何現有特徵碼都不匹配,它就會被標記為新錯誤。