本指南說明如何在程式碼中加入非同步追蹤功能。
必要條件
開始之前,請確認您已完成下列事項:
此外,請務必在程式碼中使用相關的程式庫:
C
#include <lib/trace/event.h>
C++
#include <lib/trace/event.h>
荒漠油廠
use fuchsia_trace::{ArgValue, Scope, ...};
新增非同步追蹤
當作業橫跨多個執行緒時,系統會使用一組非同步追蹤函式。
舉例來說,在多執行緒伺服器中,要求會由一個執行緒處理,然後在作業進行期間放回佇列。過了一段時間後,另一個執行緒會收到作業已完成的通知,並「接手」處理該要求。非同步追蹤的目標是讓這些不連續的追蹤事件產生關聯。
非同步追蹤會考量到相同的程式碼路徑會用於多個不同的處理流程。在先前的範例中,我們想瞭解特定函式執行的時間長度,或特定值在特定時間點的值。使用非同步追蹤功能時,我們會追蹤相同的資料,但會以邏輯處理流程為準,而非以程式位置為準的流程。
在佇列處理範例中,接收要求的程式碼會為每個要求加上「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);
請勿將這裡的「async」用法與程序中執行的非同步迴圈混淆,兩者並無關聯。
流程追蹤
非同步追蹤功能適用於同一個程序內的追蹤,但可能會透過不同的執行緒進行。
有一種稱為「流程」追蹤的較高層級追蹤機制,可用於處理程序或抽象層之間。
您可以呼叫 TRACE_FLOW_BEGIN()
來標示「流程」的開始。就像 TRACE_ASYNC_BEGIN()
一樣,您可以傳入 Nonce 來識別這個特定流程。流量 ID 為未經簽署的 64 位元整數。
接著,您可以 (選用) 呼叫 TRACE_FLOW_STEP()
,指出該資料流中的追蹤作業。
完成後,請使用 TRACE_FLOW_END()
結束流程。
舉例來說,您可以在用戶端和伺服器之間使用流程,追蹤從用戶端到伺服器,再回到用戶端的端對端要求。