可觀測性與追蹤

USDT 探針(靜態定義追蹤探針)

/ you-ESS-dee-TEE /

tracepoint 給核心穩定、由開發者放置的觀察點。USDT 是同一個好點子,但用於使用者空間程式:它讓一個應用程式或函式庫的「作者」,直接在自己的程式碼裡、在對那個程式有意義的事件上,做進具名、穩定的追蹤點——「一個查詢開始了」「一次垃圾回收開始了」「一個請求被重試了」。USDT 代表 User Statically-Defined Tracing(使用者靜態定義追蹤)。

它實務上這樣運作。開發者用一個探針巨集在原始碼裡標出一個位置,給它一個名字與要暴露的值(例如一個名叫 query__start、攜帶 SQL 文字與連線 id 的探針)。編譯後,這會在二進位檔的 notes 區段裡留下一個特殊標記,說「在這個位址有一個名叫 query__start 的探針,帶有這些引數」。關鍵在於,當沒有追蹤器掛上時,這個探針會編譯成基本上就一條 no-op 指令,所以在正常運作下幾乎不花成本。當某個追蹤工具(bpftrace、BCC 或 perf)被要求掛到那個探針時,它讀取標記、找到位址,並在那裡放一個 uprobe 式的中斷點,以在每次抵達那個位置時擷取那些具名引數。PostgreSQL、MySQL、Python、Node.js、JVM 之類的資料庫與語言執行期都隨附 USDT 探針,正是為了讓維運者能追蹤有意義的應用程式事件,而不必去讀原始碼。

它之所以重要,是因為它橋接了一道鴻溝:動態 uprobes 能觸及任何函式,但只看得到原始、不穩定的內部,而 USDT 給你穩定、「有意義」、作者背書的事件,還帶友善的引數——這是應用程式自己的可觀測性契約。誠實的提醒:USDT 探針只存在於作者選擇加入的地方,而且只在建置時包含了它們才有(有些發行版把它們編掉了);未啟用的探針近乎免費但不是完全免費;而且因為名稱與引數是作者維護的一個介面,它們跨主要版本仍可能改變,雖然那正是一個好作者會明確設法避免的事。

// 在應用程式的 C 原始碼中,作者植入一個具名探針: DTRACE_PROBE2(myapp, query__start, sql_text, conn_id); // 之後,維運者不需重新編譯就掛上: $ bpftrace -e 'usdt:/usr/bin/myapp:myapp:query__start { printf("%s\n", str(arg0)); }'

作者定義一個穩定、具名、帶友善引數的應用程式事件;維運者即時追蹤它,不必碰或重建程式。

儘管巨集名叫 DTRACE_PROBE,USDT 並不是 DTrace——這個探針定義慣例是從 DTrace 繼承來的,但在 Linux 上這個探針是由 eBPF/bpftrace/perf 消費的,而非 DTrace 本身。

又稱
statically defined tracing probeuser statically-defined tracepointSDT probe使用者靜態定義追蹤點USDT