# 來自 Grafana 與 OpenTelemetry 的 Logging 最佳實踐

## 現代可觀測性中的 Log 思維革命：來自 Grafana 與 OpenTelemetry 的最佳實踐

<iframe width="560" height="315" src="https://www.youtube.com/embed/D-bWeY-gBWU?si=M-uqAa1TInSKgVc3"></iframe>

以下是影片內容的完整解釋與重點摘要：

### 1\. 2025 年 Log 的角色與重要性

* **Log 是否仍有一席之地？** [\[05:30\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=330)
    
    * 來賓們討論在現代[可觀測性](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=330)Observability）中 Log 的地位。[Ed認為 Log 是「唯一真實的可觀測性訊號」，因為它是最容易獲取的](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=330)（從 Hello World 就開始用），且無法被完全取代（如 process 的 stdout/stderr）。
        
    * **Zero Duration Spans (零持續時間的 Span**) [\[08:33\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=513)：Jack 提到一種反模式，即人們將 Log 記錄為「持續時間為零」的 Span。他認為如果不具備層級結構且沒有持續時間，那它本質上就是 Log，不應硬套用 Span 的概念。
        

### 2\. OpenTelemetry 為何需要 Logng API？ [\[17:23\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=1043)

* 儘管已有很多成熟的 Log \[框架（如 Log4j,Python logging），OpenTelemetry 仍推出了自己的 Logging API。
    
* **互操作性（Interoperability）**：最初目的是為了橋接現有的 Log 系統（Log Bridge API）。
    
* **統一性**：讓使用者能用同一套 API 處理 Metrics、Traces 和 Logs。
    
* **強型別與結構化**：OpenTelemetry 希望推動 Log 往「結構化（Structured）」方向發展，包含明確的事件名稱（Event Name）與屬性（Attributes），而非僅是純文字字串。
    

### 3\. 結構化 Log vs. 人類可讀性

* **兩難**：純文字 Log 對人類閱讀除錯很友善，但對機器分析不便；結構化 Log（如 JSON）對機器友善，但人類難以直接閱讀。
    
* **建議**：Log 應該是結構化的，但保留一個人類可讀的訊息欄位（或將其轉化為 Event Name）。[\[34:51\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=1043)
    

### \[4. Log 的最佳實踐建議

來賓們分享了具體的實戰建議：

* **撰寫有意義的錯誤訊息**\[[36:52\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=2212)
    
    * Ed強調：當你寫 error log 時，請**告訴讀者（通常是未來的你）該怎麼做**。不要只寫「資料庫連線失敗」，要寫「資料庫連線失敗，正在重試」或「請檢查某設定」。
        
* **直接傳送 vs**檔案抓取\*\*[\[42:50\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=513)
    
    * Jack 建議應用程式應**直接透過網路（OTLP協定）發送Log**後端，而不是寫入檔案再由 Agent 去抓取（Tail）。這樣能更無縫地保留 Context（如 Trace ID）。
        
    * Ed 補充建議：在應用程式與後端之間最好有一個**本地的Colle**ctor\*\*。這樣當需要過濾大量垃圾 Log 時，可以在 Coller 端調整設定，而無需重新部署應用程式。
        
* **不要濫用 Log**
    
    * **Metrics vs. Logs**[\[47:28\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=2848)：不要用 Lo 來做高基數（High Cardinality）的計數統計，那應該用 Metrics。
        
    * **Traces vs. Logs** [\[48:29\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=3816)：如果你想知道「請求花費了多少時間」或「請求的路徑」，請使用 Traces，不要用 Log 印出「開始\]請求」、「結束請求」。
        
* \[**Log 等級（Severity**[\[01:03:36\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=3816)：絕對不要記錄沒有等級的 Log。至少要區分 INFO、ERROR、DEBUG，這對過濾和警報至關重要。
    
* **安全性** [\[01:01:53\]](http://www.youtube.com/watch?v=D-bWeY-gBWU&t=3432)：小心不要在 Log 中記錄 PII（個人識別資訊）或 Secrets，也不要記錄完整的 HTTP Headers。
    

### 5\. 快速問答環節（Good or Bad?）

影片末尾\[\[57:12\]\] 進行了一個快問快答遊戲：

* **格式化 L**og 字串？\*\* 不建議（應使用參數化/結構化）。
    
* **將所有 Excetion 都記為 Error？** 同意。
    
* **記錄 Request/Response Body？** 通常不建議（成本太高且易洩漏個資，除非有極強烈的除錯需求。
    
* **記錄所有細節？** 不建議，每一個 bytes都要錢，請有意識地選擇要記錄的內容（Be intention）。
    

---

在 Cloud Native 與微服務架構盛行的 2025 年，Log（日誌）這個最古老的除錯工具，是否已經過時？或者它只是需要一點「現代化」的改造？

最近觀看了 Grafana Labs 與 OpenTelemetry (OTel) 技術委員會成員的一場深度對談（Community Call），主題聚焦於 **Logging Best Practices**。這場討論並非單純的操作教學，而是對於 Log 在現代可觀測性（Observability）中角色的重新定義。

以下整理了影片中的核心觀點，希望能幫助開發者與維運人員打破舊有的 Log 思維，建立更具「意圖性」的可觀測性策略。

### 1\. 觀念翻轉：Log 的定位與「反模式」

在 Tracing（追蹤）技術日益普及的今天，很多人會問：「我還需要 Log 嗎？」答案是肯定的，而且 Log 是不可取代的「唯一真實訊號」。

然而，為了追求新技術，社群中出現了一種名為 **Zero Duration Spans（零持續時間 Span）** 的怪現象。

#### 什麼是 Zero Duration Span？

開發者為了利用 Tracing 工具的視覺化，將原本該是 Log 的單點事件，包裝成「開始時間等於結束時間」的 Span。

OpenTelemetry 技術委員會成員 Jack Berg 對此提出了精闢的見解：

> **"If it walks like a log, talks like a log, it's a log."** （如果它走起來像 Log，叫起來像 Log，那它就是 Log，別裝了。）

#### 判斷標準

* **Span (Traces)**：具有層級結構（Hierarchy）與持續時間（Duration）。用來回答「這個請求花了多久？路徑為何？」。
    
* **Log**：發生在特定時間點的事件。用來回答「當下發生了什麼事？」。
    

**最佳實踐**：誠實面對資料的本質，不要硬套用 Span 的概念。Log 依然是一等公民。

### 2\. 結構化革命：從「給人看」到「機器優先」

傳統的 Log 是一行行給人類閱讀的字串（Text-based），但在微服務與海量資料的場景下，這種模式已經行不通。OpenTelemetry 正推動 Log 往 **結構化（Structured）** 與 **強型別（Strongly typed）** 發展。

#### 為什麼需要結構化？

* **查詢效率**：試想在幾億行 Log 中 `grep` 字串，與在資料庫中查詢 `attributes.http_status_code == 500` 的區別。
    
* **關聯性**：OTel 的目標是讓 Logs、Traces、Metrics 使用統一的語意規範（Semantic Conventions）。
    

#### 兩難與解法

結構化 Log（如 JSON）對機器友善，但對人類閱讀不便。

* **建議做法**：保留 Log 的結構化欄位（Attributes）供機器分析，但同時保留一個 `message` 欄位或是將其轉化為易讀的 `Event Name` 供人類快速瀏覽。
    

### 3\. 架構演進：File Tail vs. OTLP Direct

你的 Log 是怎麼送到後端的？這涉及到架構的解耦。

#### 傳統模式：File Scraping

應用程式將 Log 寫入磁碟檔案 -&gt; Agent (如 Promtail) 去抓取 (Tail) -&gt; 傳送後端。

* **缺點**：容易丟失 Context（如 Trace ID），且依賴硬碟 I/O。
    

#### 現代模式：OTLP Direct

應用程式透過網路協定（OTLP）直接將 Log 發送出去。

* **優點**：原生支援結構化，保留完整 Context，無需檔案權限。
    

#### 🔥 進階技巧：Local Collector Pattern

Grafana Loki 的維護者 Ed 提出了一個極佳的架構建議：**在應用程式旁跑一個 Local Collector**（作為 Sidecar 或 DaemonSet）。

> **好處**：當你需要將 Log Level 從 INFO 改為 DEBUG 時，你只需要調整 Collector 的過濾規則，**完全不需要重新部署應用程式**。這實現了極致的維運解耦。

### 4\. 實戰指南：如何寫出「有靈魂」的 Log？

當開發者敲下 `logger.error(...)` 時，請記住以下原則：

#### ✅ 1. 寫給未來的自己 (Actionable Errors)

不要只寫「連線失敗」。錯誤訊息必須包含「接下來該做什麼」。

* ❌ Bad: `Connection failed.`
    
* ✅ Good: `Connection to DB failed, retrying in 5s. Please check network config.` **精神：同理心。** 給半夜修 Bug 的人一條明路。
    

#### ✅ 2. Context is King

沒有 Trace ID 或 User ID 的 Log，在高併發環境下幾乎是雜訊。務必確保 Log 包含足夠的上下文屬性。

#### ⛔ 3. 避免高成本操作

* **不要 Log Request Body**：除非在開發環境，否則這會導致儲存成本爆炸，且有洩漏 PII（個資）與 Secrets（金鑰）的風險。
    
* **不要用 Log 做統計**：如果你想知道「API 被呼叫幾次」，請用 Metrics，不要用 Log。
    

### 總結：Be Intentional (保持意圖)

整場討論可以用這兩個字總結：**"Be Intentional"**。

Log 不再是廉價的 `printf`。每一行 Log 都有儲存成本、傳輸成本與認知成本。

* 這條 Log 是給誰看的？（人還是機器？）
    
* 它的目的是什麼？（除錯、稽核還是統計？）
    
* 它包含了足夠的資訊嗎？
    

在 2025 年，寫好 Log 不僅是技術能力的展現，更是一種對系統架構與團隊協作的深層思考。

---

> *參考來源：Grafana & OpenTelemetry Community Call - Logging Best Practices*
