本指南說明如何在程式碼中加入非同步追蹤。
必要條件
開始之前,請先確認您已完成下列事項:
新增非同步追蹤
有一組非同步追蹤函式,如果作業橫跨多個執行緒,就能使用一組非同步追蹤函式。
舉例來說,在多執行緒伺服器中,要求會由一個執行緒處理,然後在作業執行期間放回佇列中。一段時間後,另一個執行緒會收到作業已完成的通知,並「測試」該要求處理作業。非同步追蹤的目標,是藉由允許這些不連續的追蹤記錄事件建立關聯。
非同步追蹤會將相同的程式碼路徑用於多個不同的處理流程。在先前的範例中,我們希望查看特定函式的執行時間,或特定時間點的值為何。透過非同步追蹤,我們希望追蹤相同的資料,但適用於邏輯處理流程,而不是以程式位置為基礎的流程。
在佇列處理範例中,接收要求的程式碼會將每個要求標記為「nonce」,這是出現在要求周圍的唯一值。這個 Nonce 可以使用 TRACE_NONCE()
產生,而後者只會遞增全域計數器。
接著來看看運作方式。 首先,您必須宣告存放 Nonce 的位置。以下內容通常位於要求本身的結構定義結構中:
typedef struct {
...
// add the nonce to your context structure
trace_async_id_t async_id;
} my_request_context_t;
要求送達後,請擷取 Nonce,並開始非同步追蹤流程:
// a new request; start asynchronous tracing
ctx->async_id = TRACE_NONCE();
TRACE_ASYNC_BEGIN("category", "name", ctx->async_id, "key", TA_STRING("value"));
您可以使用 TRACE_ASYNC_INSTANT()
巨集定期記錄追蹤事件 (與上方 TRACE_INSTANT()
巨集的操作類似):
TRACE_ASYNC_INSTANT("category", "name", ctx->async_id, "state", TA_STRING("phase2"));
並透過 TRACE_ASYNC_END()
清理:
TRACE_ASYNC_END("category", "name", ctx->async_id);
請勿混淆使用「非同步」功能和在程序中執行的非同步迴圈,兩者無關。
流量追蹤
非同步追蹤適合在相同程序內進行追蹤,但或許是透過不同的執行緒進行追蹤。
有一種較高層級的追蹤機制稱為「資料流」追蹤,可在程序或抽象層之間使用。
呼叫 TRACE_FLOW_BEGIN()
以標示「資料流」的開始。和 TRACE_ASYNC_BEGIN()
一樣,您可以傳入 Nonce 來表示這個特定流程。流程 ID 是無正負號的 64 位元整數。
接著,您可以選擇呼叫 TRACE_FLOW_STEP()
,指出該流程中的追蹤作業。
完成後,系統會使用 TRACE_FLOW_END()
結束流程。
例如,在用戶端與伺服器之間使用流程,可用於追蹤用戶端、透過伺服器和傳回用戶端的端對端要求。