OpenObserve 與 OpenTelemetry:整合式觀測性平台介紹

盧建霖 Patrick Lu 2026/10/20 10:20:13
81

前言

系統從單體走向微服務,從單一機房走向多雲與地端並存之後,「出了問題要去哪裡看」變得越來越難回答。一個使用者請求可能經過前端、多個後端服務與資料庫;記錄放在各台主機上,指標在另一套系統,追蹤又在第三套。排查時光是在不同工具之間切換、對時間、比對識別碼,就耗掉大半時間。

同一時間,OpenTelemetry(簡稱 OTel)已成為業界主流的遙測資料標準。資料的「產生與傳輸」有了共通語言之後,下一個問題是:資料要存在哪裡、用什麼來看?

本文介紹 OpenObserve,一個把記錄、指標、追蹤、儀表板與警示整合在同一個平台的開源方案,說明它與 OTel 搭配能帶來的好處,並誠實列出導入前需要留意的限制。內容有一部分來自我實際架設測試環境的經驗,並包含兩個不同環境、不同程式語言的實測案例:因雲端專案轉地端而測試的 Kubernetes 遙測與 Node.js 應用程式追蹤,以及內部虛擬機以 Docker 安裝的 OpenDGR 追蹤,詳見第七節。


一、先釐清:什麼是觀測性

傳統監控是預先決定要看什麼(CPU、記憶體、服務是否存活),超過門檻就發出警示,適合回答「已知的問題有沒有發生」。觀測性則要求系統輸出足夠豐富的資料,讓我們遇到「沒預料過的問題」時,也能事後從資料推敲原因。

三種核心訊號各自回答不同的問題:

  • 指標(Metrics):隨時間變化的數字,例如 CPU 使用率、每秒請求數、錯誤率。體積小,適合看趨勢與設定警示。
  • 記錄(Logs):事件的文字紀錄,細節最多,適合查證「當時到底發生了什麼」。
  • 追蹤(Traces):一個請求跨越多個服務的完整路徑與每一段的耗時,適合回答「慢在哪裡」。

再加上儀表板(視覺化)與警示(主動通知),構成完整的觀測性能力。單看任何一種訊號都有盲點,真正的價值在於能把它們串起來看。


二、OpenTelemetry 為什麼重要

OTel 是由 CNCF 託管的開源專案,提供一套與廠商無關的標準,主要包含:

  • SDK 與自動檢測:Java agent、Node.js、.NET、Python 等語言都有對應的檢測方式,多數情況不需修改程式碼就能產生追蹤與指標。
  • OTLP 協定:遙測資料的標準傳輸格式,可透過 gRPC 或 HTTP 傳送。
  • Collector:獨立的中繼程式,以「接收(receivers)、處理(processors)、匯出(exporters)」的管線運作,可以統一做批次、取樣、過濾與欄位轉換。
  • 語意慣例(Semantic Conventions):統一屬性名稱,例如 service.name、deployment.environment.name,讓不同語言、不同團隊產生的資料能互相對得上。

對企業而言最大的意義是避免鎖定:應用程式只要輸出 OTLP,後端平台就可以更換,不必因為換了一套觀測平台,就得重新改寫每個服務的檢測程式。

需要提醒的是,各語言 SDK 對三種訊號的成熟度不一,導入前仍應確認所用語言與版本的支援狀況。


三、OpenObserve 是什麼

OpenObserve(常簡稱 O2)是一個開源的觀測性平台,把記錄、指標、追蹤放在同一個系統裡儲存與查詢,並內建使用介面、儀表板與警示。依官方說明與我的實測,主要特色如下:

  • 一體化:單一平台涵蓋 Logs、Metrics、Traces,另外也提供 RUM(真實使用者監控)與 SLO 等功能。

  • 原生支援 OTLP:可直接接收 OTLP/HTTP 與 OTLP/gRPC,透過 OTel Collector 的 otlphttp 匯出器即可送入。
  • 相容既有生態:支援 Prometheus remote_write,既有的 Prometheus 與各種 exporter 不必重做,就能把指標送進來;官方也提供從 Prometheus 與 Mimir 遷移指標的文件(見延伸閱讀)。
  • 熟悉的查詢方式:Logs 與 Traces 可用 SQL 查詢,Metrics 支援 PromQL。
  • 儲存架構:設計重點是以物件儲存(如 S3 相容服務)搭配欄式格式儲存資料,目標是降低儲存成本。實際成本與效能會隨資料量與環境而異,建議用自己的資料實測,不要直接採信廠商宣稱的倍數。
  • 部署彈性:可用單一容器快速啟動做驗證,也有叢集模式;提供自行架設與雲端託管兩種形式。

四、功能導覽

4.1 記錄(Logs)

集中查詢各主機與服務的記錄,可用欄位篩選或 SQL。我實測以 OTel Collector 的 journald receiver 蒐集 Ubuntu VM 的 systemd 以及 Windows VM 的記錄,並匯入 OpenObserve 查詢。

4.2 指標(Metrics)

可接收 OTel 指標(例如 hostmetrics receiver 蒐集的 CPU、記憶體、磁碟、網路),也能接收 Prometheus 格式的資料,並直接在儀表板上畫成趨勢圖。

4.3 追蹤(Traces)

顯示一個請求跨服務的呼叫關係與各段耗時。OpenTelemetry 官方也提供一套 Demo 應用程式(模擬電商的多個微服務),可以用來測試追蹤等功能。

4.4 儀表板(Dashboards)

結構為「資料夾、儀表板、面板(Panel)」三層,內建多種圖表類型(折線、長條、表格、圓餅等),也有範本可用。表格面板支援樞紐(Breakdown)欄位做交叉整理;較進階的查詢可切換成自訂 SQL。

4.5 警示(Alerts)

可建立排程警示:定期執行查詢,符合條件就通知,通知目的地可設定為 Webhook、Email 等。我實測串接了 Discord,通知可以正常送出。

「機器下線」這類情境,因為平台沒有內建的主機存活狀態,做法是偵測「一段時間內沒有資料進來」,或使用 Collector 的 httpcheck receiver 這類主動探測的指標。我實測採用前者,下面的查詢已確認可以在主機停止回報後觸發警示,並透過 Discord 收到通知。

SELECT host_name, max(_timestamp) AS last_seen
FROM "system_cpu_time"
GROUP BY host_name
HAVING to_timestamp_micros(max(_timestamp)) < now() - interval '5 minutes'
  • 做法:以每台主機都會固定送出的 system_cpu_time 為對象,依 host_name 分組,找出最後一筆資料超過門檻(此例為 5 分鐘)的主機。警示類型為排程,警示彙總選「多重警示」,一條規則就能涵蓋所有主機,新主機只要有送這個指標就會自動納入。
  • 觸發條件:查詢只會回傳離線的主機,所以條件要設成「筆數大於等於 1」,不是小於 1。
  • 回溯視窗要大於判定門檻:例如視窗 60 分鐘、門檻 5 分鐘;否則主機離線超過視窗後會從結果消失,警示就不會再報。
  • 限制:離線超過回溯視窗的主機不再被偵測;從未上線過的新主機偵測不到;判斷的是「資料有沒有進來」,Collector 停止與主機當機看起來是一樣的。

4.6 資料管線(Pipelines)

可在資料進入儲存前後做欄位轉換與過濾。不過我的作法是把轉換規則放在 OTel Collector 端(見第六節),讓規則與後端平台解耦。


五、整合式平台的好處

5.1 排查時不必在多個工具之間切換

同一個介面可以查記錄、指標與追蹤,並透過共同的屬性(例如 service_name、trace_id 等欄位)把它們串起來。實務上的排查路徑會變成:收到警示、打開儀表板確認範圍、點進追蹤找出慢的環節、再回頭看該時段的記錄。

5.2 維運元件變少

常見的自建組合是 Prometheus 做指標、Loki 做記錄、Tempo 做追蹤、Grafana 做視覺化,通常還要另外處理警示。每個元件都有各自的部署、升級、容量規劃、備份與權限設定。整合式平台把這些收斂成一套,維運負擔與出錯機會都跟著減少。

5.3 資料標準與治理可以一次定義

認證、保留期限、命名規範集中管理。搭配 Collector 的 transform processor,可以在資料進入平台之前,統一強制命名規範並遮蔽個人資料,不必依賴每個服務各自做對。

5.4 以 OTLP 為介面,降低鎖定風險

應用程式只認 OTLP 與 Collector,後端是 OpenObserve 還是其他平台,只需改 Collector 的匯出設定。這讓我們日後評估或更換後端的成本很低。

5.5 成本較可預期

以物件儲存為基礎的設計,在資料量大、保留期限長的情境下,儲存成本有機會比傳統做法低。再搭配 Collector 端的取樣,可以進一步控制進入平台的資料量。實際效益仍需依自己的資料量實測。

5.6 學習門檻較低

記錄與追蹤可以用 SQL 查詢,多數工程師都熟悉;既有的 PromQL 經驗也能直接用在指標上。


六、我的參考架構

我規劃的是多環境(AWS、GCP、Azure、地端)共用同一個後端的架構:

  1. 各環境的應用程式以 OTel 自動檢測(Java agent、.NET、Node.js)產生資料,送往同環境內的本地 Collector。
  2. 本地 Collector 負責批次與初步過濾,再轉送到中央 Gateway Collector。
  3. Gateway Collector 統一處理:命名規範強制(例如 service.name 轉小寫、必填屬性檢查)、個資遮蔽、追蹤取樣(錯誤全留、正常請求依比例取樣)。
  4. 最後匯出到 OpenObserve。

基礎設施層面:VM 上以 systemd 服務方式執行 otelcol-contrib,使用 hostmetrics 與 journald 蒐集主機資料;Kubernetes 環境可透過 OpenTelemetry Operator,用註解的方式自動注入檢測,不需修改映像檔。

這個架構的重點是規則放在 Collector,不放在各個服務。服務數量與語言越多,把規則集中在一個地方,越容易維持一致,也越容易調整。


七、實測案例:兩種環境、兩種語言

除了基礎環境的驗證,我剛好有兩個機會,把 OpenObserve 放進實際的應用程式環境測試:一個是 Kubernetes 上的 Node.js 應用程式,一個是虛擬機上以 Docker 執行的 Java 應用程式。以下記錄做法與過程中確認的事項。

7.1 案例一:Kubernetes 遙測與 Node.js 應用程式追蹤

某個雲端專案因需求要轉為地端部署,讓我有機會在地端的 Kubernetes 上,測試 OpenObserve 的 Kubernetes 遙測,以及對 Node.js 應用程式的追蹤。

  • 環境:RKE2 v1.36.4 安裝的單節點架構、應用程式 Node.js 20.11.0
  • 做法:依 OpenObserve 的 Kubernetes 資料來源導覽安裝 Collector,並啟用選用的「自動為應用程式啟用追蹤檢測」。它利用 OpenTelemetry Operator,在 Pod 建立時為有加註解的工作負載注入 Node.js 的檢測,不需修改程式碼,也不需重建映像檔。註解的名稱是 instrumentation.opentelemetry.io/inject-nodejs,值指向叢集內的 Instrumentation 資源。
  • **留意一:注入只發生在 Pod 建立的當下。**已經在跑的 Pod 要重建才會生效。官方範例是對整個命名空間加註解,再重啟所有 Deployment,風險較高;我傾向只對單一 Deployment 的 Pod 範本加註解,並透過既有的 CI/CD 在下次部署時自然帶入,先在測試環境驗證。
  • **留意二:span 狀態是 UNSET 屬於正常。**這是 OTel 的預設值,表示沒有發生錯誤,也沒有被明確標記為成功;只有出錯時才會是 ERROR。
  • **留意三:記錄裡的 trace_id 與 span_id 不一定有值。**通常只有經過有被檢測的日誌函式庫輸出的記錄,才會被自動帶上這兩個欄位;直接寫到標準輸出的記錄多半是空的,這與追蹤是否成功是兩件事。
  • 結果:

7.2 案例二:虛擬機上以 Docker 執行的 OpenDGR(Java)追蹤

內部虛擬機測試環境以 Docker Compose 安裝了 OpenDGR,我用它驗證容器內的 Java 應用程式如何接上追蹤。

  • 做法:以 OpenTelemetry Java agent,透過 JAVA_TOOL_OPTIONS 環境變數載入,不改動原本的 compose 檔與啟動腳本。另外建立一份額外的 compose 設定檔,把 agent 檔案唯讀掛進容器,並設定服務名稱與 OTLP 端點;要還原時,只要不帶這份額外設定檔重新啟動該服務即可。
  • 連線方式:這台主機上沒有以容器執行的 Collector,只有以系統服務執行的 Collector,所以容器透過主機位址連線;該 Collector 也需要加上 OTLP 接收與 traces pipeline。
  • **留意一:agent 預設會同時送出 traces、metrics、logs。**Java SDK 三種匯出器的預設值都是 otlp,Collector 沒有對應 pipeline 的訊號會被拒絕。測試階段可以把 OTEL_METRICS_EXPORTER 與 OTEL_LOGS_EXPORTER 設成 none,只保留需要的訊號。
  • **留意二:JVM 只能在啟動時載入 agent。**容器必須重建,服務會短暫中斷,要選離峰時段,並先備份原本的設定。
  • 留意三:agent 送出的記錄,在有 span 的情況下會自動帶 trace_id 與 span_id,可以從追蹤直接跳到同一個請求的記錄。
  • 結果:

7.3 兩個案例的共通點

  • 應用程式端不用改程式碼:Node.js 靠 Operator 注入,Java 靠 agent 載入,動的都只是部署設定。
  • 資料都先送到 Collector,再轉送到 OpenObserve:帳密只存在 Collector,與第六節的架構一致。
  • 不同的執行環境與語言,進到同一個後端,用同一個介面查詢:這正是以 OTLP 為共通介面、後端統一的好處。

八、標準化:讓導入可以複製

要讓 OTel 變成團隊的標準作業,而不是每個專案各自摸索,我整理了一份規範,核心包含:

  • 命名規則:service.name 採 team-service 格式,全小寫、以連字號分隔;環境資訊一律放在 deployment.environment.name(語意慣例 v1.27.0 起取代舊的 deployment.environment;實際採用哪一個,以所用檢測版本送出的欄位為準,並全團隊統一),值固定為 dev、uat、prod。
  • 必填屬性:service.name、service.version、deployment.environment.name、team.owner(team.owner 為我自訂的屬性,不屬於 OTel 標準)。
  • 全服務統一設定:例如 OTEL_PROPAGATORS 必須一致,否則跨服務的追蹤會斷掉。
  • 各語言範本:Java、.NET、Node.js、Python 各有標準的 Dockerfile 片段與環境變數清單。
  • 上線檢查清單:確認檢測版本與語言相符、命名符合規範、資料確實在平台上出現,並且 OpenObserve 的欄位列表中出現預期的欄位名稱(底線形式)。

8.1 欄位名稱對照:設定時用點號,查詢時用底線

OTel 的屬性名稱以點號分隔,例如 service.name,這是在應用程式的環境變數、Collector 設定與 OTTL 規則裡使用的寫法。但在 OpenObserve 中,這些點號會顯示為底線:Traces 頁面看到的是 service_name、db_name,查詢與警示裡用到的 host_name、http_url 也是同樣的轉換;指標名稱也一樣,例如 system.cpu.time 在 OpenObserve 是名為 system_cpu_time 的 stream。

  • 對照:service.name 對應 service_name、service.version 對應 service_version、deployment.environment.name 對應 deployment_environment_name、team.owner 對應 team_owner。其中 service_name 已在 Traces 頁面確認,其餘是依相同規則推得,請在實際資料的欄位列表中確認。
  • 哪裡用哪一種:應用程式的 OTEL_RESOURCE_ATTRIBUTES、Collector 的 resource 與 transform processor(OTTL,例如 attributes["service.name"])一律用點號;OpenObserve 的 SQL、PromQL、警示與儀表板篩選一律用底線,例如 WHERE service_name = ...。
  • 兩種寫法不能混用:在 OpenObserve 查詢裡寫點號,或在 OTTL 裡寫底線,都對不到原本的欄位,結果是查不到資料,或設定到另一個不同的屬性。
  • 規範管的是「值」,不是欄位名稱本身:全小寫、連字號、dev、uat、prod 這些規則管的是欄位的值,與欄位名稱的轉換無關。
  • host_name 的值不受命名規則控制:它來自作業系統的主機名稱,例如 Windows 主機常是大寫的預設名稱;用 host_name 分組或建立警示時,要留意大小寫是否一致。
  • 以實際畫面為準:規範文件建議附上「OTel 名稱與 OpenObserve 欄位」的對照表,並以 Traces、Logs、Metrics 頁面實際的欄位列表為準。

九、實測心得與踩雷紀錄

以下是我實際架設過程中遇到的問題,提供給之後要導入的同事參考:

  • 資料沒出現,先查時間範圍。 查詢的時間區間太短,或測試資料的時間戳記是舊的,都會讓畫面看起來沒資料。
  • 容器網路要想清楚。 Collector 的 receiver 要綁定 0.0.0.0,不能填特定 IP 或主機名稱;兩個獨立的 Docker Compose 專案預設在不同網路,彼此看不到對方,需要共用網路或改走主機連線;環境變數若同時被拿來當「自己監聽的位址」和「要送去的目標」,很容易出錯。
  • journald 的資料需要整理。 journald receiver 預設會把整筆 journal 內容放進 body,severity 也會是 0,需要用 operators 把訊息與欄位拆開,再以 transform 把優先權對應成 severity。
  • OTTL 函式名稱要查證。 例如轉小寫是 ToLowerCase,寫成其他名稱會直接解析失敗;欄位可能不存在時,要加上條件避免執行期警告。
  • 範本面板沒資料,先看它查的是哪個 stream。 例如 Uptime 範本需要 httpcheck receiver 產生的指標;另外,httpcheck 對每個目標會同時產生各個狀態碼類別的序列,判斷成功時要限定 2xx,否則回傳 500 也可能被誤判為成功。
  • Kubernetes 自動注入需要 Pod 重建才會生效。 建議把註解寫在 Deployment 的 Pod 範本,並透過 CI/CD 部署,先在測試環境驗證;一次重啟整個命名空間的風險較高,不建議在正式環境直接執行。
  • 偵測機器下線要換個角度。 如果探測程式跑在被監控的機器自己身上,機器掛了探測也跟著停,只會看到「沒資料」而不是「失敗」,應該由另一台機器去探測。
  • **欄位名稱在 Collector 與 OpenObserve 之間的寫法不同。**設定與 OTTL 用點號(service.name),OpenObserve 的查詢、警示與儀表板用底線(service_name);在 Collector 規則裡寫成底線,或在 SQL 裡寫成點號,都會對不上欄位(見 8.1)。

十、與常見替代方案的比較

沒有哪一個選擇適合所有情況,以下是我評估時的整理:

  • 自建 Grafana 組合(Prometheus、Loki、Tempo、Grafana)
    • 優點:生態與社群成熟,儀表板與外掛豐富,各元件可獨立擴充,彈性高。
    • 代價:元件多,部署、升級、備份與權限都要各自維運。
  • OpenObserve
    • 優點:一體化,部署與維運單純,可用 SQL 查詢,原生支援 OTLP。
    • 代價:專案相對年輕,社群與第三方整合規模較小;部分進階功能(例如單一登入、細緻的權限控管)可能屬於企業版,需依官方授權說明確認。
  • 商業 SaaS 平台
    • 優點:幾乎不用維運,功能完整。
    • 代價:費用通常隨用量成長,且需考量資料存放位置與廠商鎖定。

十一、風險與限制

  • 成熟度:相較於已經發展多年的方案,OpenObserve 的使用案例與社群資源較少,遇到問題時可參考的資料也較少。
  • 授權:開源版與企業版的功能範圍不同,開源版的授權條款(AGPL)對內部使用與對外提供服務的影響,請與法務或資安確認,並以官方最新說明為準。
  • 資料保留與備份:保留期限、備份與災難復原需要自行規劃。
  • 個人資料:遙測資料可能夾帶個人資料,需要在 Collector 端先做遮蔽,不能假設應用程式不會輸出。
  • 團隊能力:需要有人熟悉 OTel Collector 的設定與除錯,否則問題容易卡在資料進不來的環節。
  • 效能與規模:我目前只做過小規模驗證,正式環境的資料量、查詢效能與高可用性,仍需另外評估。

十二、建議的導入路線

  1. 概念驗證:用單機容器架設 OpenObserve 與一個 Collector,接上一到兩個服務,確認三種訊號都能進來。
  2. 標準化:定案命名規範、必填屬性、各語言範本與上線檢查清單。
  3. 擴大範圍:建立多環境的本地 Collector 與中央 Gateway,建立儀表板範本與警示規則。
  4. 正式環境評估:高可用部署、保留與備份策略、權限與認證、成本實測。

可以用「從發現問題到找出原因所需的時間」作為成效指標,與導入前比較。


十三、快速試用

以下是最小的試用環境(帳號密碼請自行設定,不要使用範例值):

services:
  openobserve:
    image: o2cr.ai/openobserve/openobserve:latest
    container_name: openobserve
    networks:
      - openobserve
    ports:
      - "5080:5080"
    environment:
      ZO_ROOT_USER_EMAIL: "admin@example.com"
      ZO_ROOT_USER_PASSWORD: "請自行設定"
      ZO_COMPACT_DATA_RETENTION_DAYS: "30"
    volumes:
      - oo-data:/data
networks:
  openobserve: {}

volumes:
  oo-data:

Collector 的匯出設定(Authorization 是帳號與密碼以冒號相連後,做 base64 編碼的結果):

exporters:
  otlphttp/openobserve:
    endpoint: "http://openobserve:5080/api/default"
    headers:
      Authorization: "Basic <base64 編碼的帳號:密碼>"
    tls:
      insecure: true

接著在 service.pipelines 的 traces、metrics、logs 各自加上這個匯出器,用 curl 或任一個已檢測的服務送一筆資料,就能在 OpenObserve 介面看到結果。


結語

當 OTel 讓資料的產生變得標準化,後端平台的選擇就回到務實的問題:維運成本、查詢體驗、成本與彈性。OpenObserve 把記錄、指標、追蹤與警示放在同一處,對於人力有限、又希望避免被單一廠商綁住的團隊,是一個值得實測的選項。它不是沒有代價,但只要以 OTLP 與 Collector 作為穩定的中間層,就算日後調整後端,應用程式端的投入也不會白費。


延伸閱讀

盧建霖 Patrick Lu