只有累積,沒有奇蹟

2025年2月8日 星期六

[NET] 探索 OpenTelemetry Auto-Instrumentation 的核心技術

前言
Observability 是手段,不是目的。透過 Auto-Instrumentation,我們更接近「讓系統自己說話」的願景。

在 COSCUP 2024 我有幸(不要臉) 再次參與並分享這一年來我在可觀測性實踐上最有趣的內容:「OpenTelemetry 的 Auto-Instrumentation 技術核心與應用實戰」。這篇文章,我會完整拆解 OpenTelemetry SDK 的 Auto-Instrumentation 的原理、架構、實務流程,並從開發者的視角出發,帶你理解什麼是「讓系統自己說話」,希望可以讓想要了解 OTel SDK 底層細節實作的朋友有幫助。


OpenTelemetry 是什麼

OpenTelemetry(簡稱 OTel)是 CNCF(Cloud Native Computing Foundation)旗下的觀測性開源計畫。它整合了 OpenTracing 和 OpenCensus,成為雲原生時代的統一觀測標準。

它主要處理三件事:

  • Instrument:幫助你從應用中收集觀測訊號(Signals)
  • OTLP:無論是 Trace、Metric 還是 Log,都有標準格式
  • Export:支援多種後端(如 Jaeger、Zipkin、Grafana Tempo、Prometheus...)

OpenTelemetry 是目前 CNCF 第二活躍的專案(僅次於 Kubernetes),也是現代 Observability 的標準。


Code-based v.s zero-code

讓程式「可以被觀察」,首先就要「儀表化」程式碼(Instrumentation)。這裡透過一張表整理 Code-based 與 zero-code 兩者的差異,更重要的是實際應用場景

小小建議:「Auto-Instrumentation 優先、Manual 優化補強」

Auto-Instrumentation 設計願景

根據 OpenTelemetry .NET Auto-Instrumentation 官方設計文件,這個 SDK 是以五大設計願景(Vision)為核心來開發的,每一個願景都對應到實務中我們真正關心的「導入門檻」、「維運穩定」、「擴充能力」。

高效能(High Performance)
  • 使用 IL 重寫,不改原始碼
  • Lazy Loading 降低資源開銷
  • 非同步匯出 Trace 資料
開箱即用(Useful by Default)
  • 內建常見欄位與框架支援
  • 啟動即生效
穩定可靠(Reliable)
  • 錯誤不影響應用
  • 具容錯能力與 fallback
可見(Visible)
  • 啟動時列出已啟用套件
  • 支援 metrics 與 debug mode
可擴展(Extensible)
  • 插件化結構,支援自定義與社群套件

Auto-Instrumentation 架構與元件
Application & Runtime(應用與執行環境)
  • Application IL(中間語言)
    .NET 應用程式編譯後的中間碼,是 Auto-Instrumentation 插入追蹤邏輯的目標對象。
  • CLR(Common Language Runtime)
    .NET 的執行核心,提供 ICorProfilerCallback / ICorProfilerInfo 介面供原生 Profiler 攔截執行事件與注入邏輯。
OTel CLR Profiler(Native)
  • 職責: 掛載在 CLR 上,透過 ICorProfiler API 攔截應用啟動流程。
  • 功能: 將 Bytecode Instrumentation 插入 Application IL,實現 Zero-code Observability。
Bytecode Instrumentations
  • 職責: 為特定框架提供具體的儀表邏輯,例如對 HttpClient、SQLClient、gRPC 注入觀測碼。
  • 功能: 在 method 內部插入 OTel API(如 StartSpan、SetAttribute)。
OTel Managed Profiler
  • 職責: 在應用執行階段進行進一步的邏輯注入與監控。
  • 用途: 管理細部的 Trace 拓展,例如更細緻的 DB query 或 gRPC 呼叫資訊。
Source Instrumentation / OTel SDK
  • Source Instrumentation: 指開發者手動使用 OTel API(例如 tracer.StartActiveSpan())插入觀測點。
  • OTel SDK: 提供觀測資料處理能力,負責收集、封裝並導出 Trace、Metrics、Logs 至後端。
架構運作流程
  1. 啟動階段: OTel CLR Profiler 掛載至 CLR,監控模組與 method 載入事件。
  2. 注入階段: Bytecode Instrumentations 對 IL 方法注入 StartSpan 等邏輯。
  3. 執行階段: Managed Profiler 進一步補強觀測點(如內部呼叫、Async 方法)。
  4. 資料導出: 所有訊號被 OTel SDK 收集後導出至 Tempo、Jaeger 等觀測平台。

設計重點 : 「模組化、低侵入、高彈性」


三大流程解析
註冊流程
重點:
  1. 設定環境變數:
    • CORECLR_ENABLE_PROFILING=1
    • CORECLR_PROFILER=OTel CLSID
    • CORECLR_PROFILER_PATH=Profiler DLL 路徑
  2. CoreCLR 啟動階段:
    • 檢查是否啟用 Profiling
    • 從 Registry 查找 CLSID 對應 DLL
    • 解析出 Profiler 的實際路徑
  3. 載入與初始化:
    • 載入 Profiler DLL
    • 呼叫 Initialize 方法註冊
    • 透過 ICorProfilerInfo 註冊事件攔截(Set Event Mask)

請求流程
重點 : 系統如何自動蒐集數據 Data (自己說話)
  1. 應用啟動: CoreCLR 發出多種事件通知,包括類別載入、JIT 編譯、方法進入與離開等。
  2. OTel CLR Profiler 攔截: 根據事件動態判斷並透過 IL 注入觀測邏輯(Bytecode Instrumentation)。
  3. Managed Profiler 建立與關閉 Span: 當方法被呼叫(FunctionEnter)時建立 Span;完成(FunctionLeave)後關閉該 Span。
  4. 外部服務呼叫: 如果方法內呼叫外部服務(API、DB),會建立額外的子 Span 表示呼叫鏈。
  5. OTel SDK 負責收集與導出: 所有已關閉的 Span 會統一被 SDK 收集並匯出至後端系統,如 Jaeger 或 Grafana Tempo。
數據流
重點
  • Application: 應用程式啟動,觸發 Auto-Instrumentation。
  • OTel CLR Profiler: 原生層級注入元件,處理 IL 攔截與上下文傳遞。
  • Bytecode Instrumentation: 插入具體的追蹤邏輯至目標方法(如 HTTP 請求)。
  • OTel Managed Profiler: 管理應用邏輯層級的觀測行為,呼叫 Instrumentation Handler。
  • OTel SDK: 中央資料處理站,封裝資料並準備匯出。
  • Collector: 集中資料後導出至 Jaeger(Trace)或 Prometheus(Metrics)。

ASP.NET Core 實作範例
  1. services.AddOpenTelemetry()
  2. .WithTracing(builder => builder
  3. .AddAspNetCoreInstrumentation()
  4. .AddHttpClientInstrumentation()
  5. .AddGrpcClientInstrumentation()
  6. .AddOtlpExporter());

這段程式會自動收集:

  • http.method, http.status_code, http.url
  • trace_id, span_id, user_agent.original
.AddAspNetCoreInstrumentation()
  • Application : 在應用程式層級攔截整體 ASP.NET Core 的 Middleware Pipeline。自動追蹤整個 HTTP 請求從進入到離開的過程。
  • Controller : 對個別 Controller 進行觀測,例如:哪個 endpoint 被呼叫、哪些路由參數被解析
.AddHttpClientInstrumentation()、.AddGrpcClientInstrumentation()
  • 程式對外發出的 HTTP 請求(如 API 呼叫)
  • gRPC 呼叫事件,包含 method 名、service 名、status code
  • 只要你用標準的 HttpClient 或 .NET gRPC,這些都會被攔截、追蹤並補上 TraceContext。
.AddOtlpExporter()
  • 把觀測資料送到你的可視化平台
  • 例如 : OTLP → Grafana Tempo / Honeycomb / Lightstep / Jaeger / New Relic
用 C4 概念則可以劃出 Container 與 Component 內容
Container
Component

小結
Auto-Instrumentation 讓開發者可以不用動原始碼,就輕鬆讓系統「說出程式碼執行的狀態」,對於初學者在導入可觀測性文化中重要的環節,希望這篇介紹 Auto-Instrumentation 對各位有幫助,若以上內容有不清處的地方,歡迎留言討論,Hayyp Coding :)

參考
opentelemetry-dotnet
opentelemetry-dotnet-instrumentation
opentelemetry-dotnet-instrumentation/docs/design.md
dotnet/runtime/blob/main/docs/design/coreclr/botr/profiling

Related Posts:

  • [NETCore] 結構化日誌 Serilog - Events Types 和 Enrichment 前言 前兩篇分別介紹了關於 Serilog 的基礎應用與設定,這篇就來針對事件類型 Event Type 與 介紹幾個常用的 Enricher,若有問題或是錯誤的地方歡迎提出來一起討論。 Event Type 結構化日誌的好處是可以清楚的分辨"每一次"紀錄的事件,舉例來說下列簡單的代碼是透過 Serilog 寫入log 到 Console 與 File 檔案,紀錄內容是 3 筆資料 Log.Logger = new LoggerCo… Read More
  • [NETCore] Serilog 好幫手 - Serilog Analyzer前言 前面透過幾篇文章介紹了關於 Serilog 在 ASP.NET Core 中的應用,分別是 結構化日誌 Serilog 初體驗 結構化日誌 Serilog - 配置設定 結構化日誌 Serilog - Events Types 和 Enrichment 三篇文章從 Serilog 基本使用以及設定都做簡單的介紹,今天要分享的是 Serilog Analyzer 擴充套件,它是基於 Roslyn 針對代碼進行分析,可以… Read More
  • [NETCore] ASP.NET Core 啟動異常 - HTTP Error 500.30 - ANCM In-Process Start Failure 問題  在開發專案時跳出異常訊息,錯誤訊息為  HTTP Error 500.30 - ANCM In-Process Start Failure ,這篇就針對此案例作簡單紀錄與分享,若是有不清楚或是錯誤的地方歡迎討論予糾正。 解決方法  廢話不多說,先看案發現場的錯誤畫面 執行異常的程式代碼,看起來很單純的代碼 public static void Main(s… Read More
  • [NETCore] 結構化日誌 Serilog 初體驗前言 在 .NET 使用日誌框架第一時間會想到 NLog 或是 Log4Net 兩種 Log 常使用的 Library,Serilog 是這幾年快速崛起的 Log 框架之一,Serilog 是以 Structured logging 為基礎進行設計,透過 logging API 可以輕鬆的記錄應用程式中對象屬性,方便快速進行 logging 內容進行查詢與分析,並將其紀錄內容透過 json (可指定) 的方式輸出,這篇就介紹 … Read More
  • [NETCore] 在 ASP.NET Core Web API 中使用 Serilog 前言 近期專案都在嘗試 Serilog,對於使用上有點小小心得,因此整理這篇文章分享 Serilog 在 ASP.NET Core API 上的使用與設定,也接續之前 Serilog 的系列介紹文 : 傳送門 的實際應用心得,希望可以幫到有需要的朋友,若有問題或是錯誤的地方歡迎提出來一起討論或是給予指導。 ASP.NET Core logging 首先先建立新的 ASP.NET Core Web Applicat… Read More

0 意見:

張貼留言

Copyright © 2025 m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com