本指南說明如何在程式碼中加入非同步追蹤。
必要條件
開始之前,請確認已完成下列事項:
此外,請務必在程式碼中使用相關程式庫:
C
#include <lib/trace/event.h>
C++
#include <lib/trace/event.h>
荒漠油廠
use fuchsia_trace::{ArgValue, Scope, ...};
新增非同步追蹤
如果作業橫跨多個執行緒,就會使用一組非同步追蹤函式。
舉例來說,在多執行緒伺服器中,要求會由一個執行緒處理,然後在作業進行期間放回佇列。過一段時間後,另一個執行緒會收到作業已完成的通知,並「接手」處理該要求。非同步追蹤的目標是允許這些不相干的追蹤事件相互關聯。
非同步追蹤會考量到多個不同的處理流程使用相同的程式碼路徑。在先前的範例中,我們想瞭解特定函式執行時間長度,或特定時間點的特定值。非同步追蹤的目標是追蹤相同資料,但追蹤的是邏輯處理流程,而非以程式位置為基礎的流程。
在佇列處理範例中,接收要求的程式碼會為每個要求加上「隨機數」標記,也就是跟著要求傳遞的專屬值。這個隨機數可透過 TRACE_NONCE() 產生,只要遞增全域計數器即可。
讓我們看看運作方式。 首先,請宣告要保留隨機值的空間。這通常位於要求本身的內容結構中:
typedef struct {
...
// add the nonce to your context structure
trace_async_id_t async_id;
} my_request_context_t;
收到要求後,您會擷取隨機數,並開始非同步追蹤流程:
// 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() 相同,您會傳遞隨機值來識別這個特定流程。流程 ID 是不帶正負號的 64 位元整數。
然後,您可以選擇呼叫 TRACE_FLOW_STEP(),指出該流程中的追蹤作業。
完成後,請使用 TRACE_FLOW_END() 結束流程。
舉例來說,您可以在用戶端和伺服器之間使用流程,追蹤從用戶端開始、經過伺服器,再回到用戶端的端對端要求。