本頁說明如何在 Fuchsia 元件的程式碼中新增追蹤功能。
必要條件
開始之前,請務必完成下列工作:
此外,請務必在程式碼中使用相關程式庫:
C
#include <lib/trace/event.h>
C++
#include <lib/trace/event.h>
荒漠油廠
use fuchsia_trace::{ArgValue, Scope, ...};
在程式碼中使用追蹤巨集
將元件註冊為追蹤記錄供應器後,即可在元件的程式碼中新增追蹤記錄。
下列動作通常很有用,而且可以使用追蹤巨集輕鬆在程式碼中新增:
- 追蹤即時事件。
- 事件時間。
- 停用追蹤。
- 判斷追蹤功能是否已開啟。
如需所有可用追蹤巨集的清單,請參閱
追蹤即時事件
以下範例會寫入代表單一時間點的即時事件:
荒漠油廠
fuchsia_trace::instant!(c"helloworld", c"hello_world_test", fuchsia_trace::Scope::Process, "message" => "Hello, World!");
這個範例指定了 helloworld 類別、hello_world_test 名稱、TRACE_SCOPE_PROCESS 範圍,以及鍵/值配對。
如要進一步瞭解 instant! 巨集,請參閱「instant!」。
C++
TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS, "message", "Hello, World!");
這個範例指定了 helloworld 類別、hello_world_test 名稱、TRACE_SCOPE_PROCESS 範圍,以及鍵/值配對。
如要進一步瞭解 TRACE_INSTANT 巨集,請參閱「TRACE_INSTANT」。
C
TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS, "message", TA_STRING("Hello, World!"));
這個範例指定了 helloworld 類別、hello_world_test 名稱、TRACE_SCOPE_PROCESS 範圍,以及鍵/值配對。
如要進一步瞭解 TRACE_INSTANT 巨集,請參閱「TRACE_INSTANT」。
為活動設定時間
這個範例說明如何計算函式或程序的執行時間:
荒漠油廠
fn InitCompressed() {
fuchsia_trace::duration!(c"helloworld", c"hello_world_test", fuchsia_trace::Scope::Process, "message" => "Hello, World!");
...
// Duration ends due to RAII
}
這個範例會記錄建構函式中耗費的時間長度,以及區塊的大小和數量。
如要進一步瞭解 duration! 巨集,請參閱「duration!」。
C++
zx_status_t VnodeBlob::InitCompressed() {
TRACE_DURATION("blobfs", "Blobfs::InitCompressed", "size", inode_.blob_size,
"blocks", inode_.num_blocks);
...
// Duration ends due to RAII
}
這個範例會記錄建構函式中耗費的時間長度,以及區塊的大小和數量。由於這是 C++ 範例,編譯器可以推斷資料型別。
如要進一步瞭解 TRACE_DURATION 巨集,請參閱「TRACE_DURATION」。
C
zx_status_t VnodeBlob_InitCompressed(inode_t inode) {
TRACE_DURATION_BEGIN("blobfs", "Blobfs_InitCompressed", "size", inode.blob_size, "blocks",
inode.num_blocks);
...
TRACE_DURATION_END("blobfs", "Blobfs_InitCompressed");
}
這個範例會記錄建構函式中耗費的時間長度,以及區塊的大小和數量。
如要進一步瞭解 TRACE_DURATION_BEGIN 和 TRACE_DURATION_END 巨集,請參閱TRACE_DURATION_BEGIN和TRACE_DURATION_END。
停用追蹤
在某些情況下,您可能會想完全停用追蹤功能 (例如即將將元件發布至正式環境時)。如果程式碼中加入 NTRACE 巨集,追蹤巨集就不會產生任何程式碼。
以下範例 (適用於 C 和 C++) 顯示 NTRACE 巨集:
#define NTRACE // disable tracing
#include <lib/trace/event.h>
請務必在 #include 陳述式之前定義 NTRACE 巨集。
在下方範例中,rx_count 和 tx_count 欄位只會用於追蹤,因此如果斷言 NTRACE (表示追蹤功能已停用),這些欄位就不會佔用 my_statistics_t 結構中的空間。
typedef struct {
#ifndef NTRACE // reads as "if tracing is not disabled"
uint64_t rx_count;
uint64_t tx_count;
#endif
uint64_t npackets;
} my_statistics_t;
不過,如果您確實需要有條件地編譯程式碼,以便管理統計資料的記錄作業,可以使用 TRACE_INSTANT 巨集:
#ifndef NTRACE
status.tx_count++;
TRACE_INSTANT("bandwidth", "txpackets", TRACE_SCOPE_PROCESS,
"count", TA_UINT64(status.tx_count));
#endif // NTRACE
如要進一步瞭解 NTRACE 巨集,請參閱「NTRACE」。
判斷追蹤功能是否已開啟
在某些情況下,您可能需要在執行階段判斷追蹤是否開啟。
荒漠油廠
if fuchsia_trace::category_enabled!(c"my_category") {
let v = do_something_expensive();
fuchsia_trace::instant!(c"my_category", ...
}
如要檢查任何追蹤功能是否已啟用,但不想檢查特定類別,可以使用 fuchsia_trace::is_enabled(),但請注意,這可能會造成較高的負擔,因為系統不會像檢查類別一樣快取這項功能。
如果追蹤功能已停用,Rust 追蹤繫結就不支援編譯時間檢查。
詳情請參閱「category_enabled」和「is_enabled」。
C++
如果追蹤作業是在程式碼中編譯,因為 NTRACE 未定義,
您可以使用 TRACE_CATEGORY_ENABLED() 檢查是否已啟用特定類別。
#ifndef NTRACE
if (TRACE_CATEGORY_ENABLED("my_category")) {
int v = do_something_expensive();
TRACE_INSTANT("my_category", ...
}
#endif // NTRACE
如要檢查任何追蹤功能是否已啟用,但不想檢查特定類別,可以使用 TRACE_ENABLED(),但請注意,這可能會造成較高的負擔,因為系統不會像檢查類別一樣快取這項功能。
上述範例使用 #ifndef NTRACE,因為函式 do_something_expensive() 可能只會在啟用追蹤功能時編譯。
詳情請參閱「TRACE_CATEGORY_ENABLED」和「TRACE_ENABLED」。
C
如果追蹤作業是在程式碼中編譯,因為 NTRACE 未定義,
您可以使用 TRACE_CATEGORY_ENABLED() 檢查是否已啟用特定類別。
#ifndef NTRACE
if (TRACE_CATEGORY_ENABLED("my_category")) {
int v = do_something_expensive();
TRACE_INSTANT("my_category", ...
}
#endif // NTRACE
如要檢查任何追蹤功能是否已啟用,但不想檢查特定類別,可以使用 TRACE_ENABLED(),但請注意,這可能會造成較高的負擔,因為系統不會像檢查類別一樣快取這項功能。
上述範例使用 #ifndef NTRACE,因為函式 do_something_expensive() 可能只會在啟用追蹤功能時編譯。
詳情請參閱「TRACE_CATEGORY_ENABLED」和「TRACE_ENABLED」。
將追蹤程式碼新增至元件後,您現在可以從元件收集追蹤記錄。詳情請參閱下一節「記錄及顯示追蹤記錄」頁面。