在程式碼中加入追蹤記錄

本頁說明如何在 Fuchsia 元件的程式碼中加入追蹤功能。

必要條件

開始之前,請確認您已完成下列工作:

在程式碼中使用追蹤巨集

將元件註冊為追蹤記錄提供者後,您就可以在元件的程式碼中加入追蹤記錄。

下列動作通常很實用,只要使用追蹤記錄巨集,就能輕鬆加入程式碼中:

如需所有可用的追蹤巨集清單,請參閱

追蹤即時事件

以下範例會寫入代表單一時間點的即時事件:

荒漠油廠

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_BEGINTRACE_DURATION_END 巨集,請參閱 TRACE_DURATION_BEGINTRACE_DURATION_END

停用追蹤

在某些情況下,您可能會想要完全停用追蹤功能 (例如,當您準備將元件發布至實際環境時)。如果程式碼中新增了 NTRACE 巨集,追蹤巨集就不會產生任何程式碼。

以下範例 (適用於 C 和 C++) 會顯示 NTRACE 巨集:

#define NTRACE  // disable tracing
#include <lib/trace/event.h>

請務必在 #include 陳述式之前定義 NTRACE 巨集。

在下方範例中,rx_counttx_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::is_enabled() {
  let v = do_something_expensive();
  fuchsia_trace::instant!(...
}

如果追蹤功能已停用,Rust 追蹤繫結不支援編譯時間檢查。不過,如果在編譯時停用追蹤功能,檢查 is_enabled 不會造成大量效能消耗。

如要進一步瞭解 is_enabled,請參閱 is_enabled

C++

如果 NTRACE 未定義,而在程式碼中編譯追蹤,TRACE_ENABLED() 巨集會判斷追蹤服務供應商是否已啟用追蹤功能。如果追蹤已編譯,TRACE_ENABLED() 一律會傳回 false。

#ifndef NTRACE
    if (TRACE_ENABLED()) {
        int v = do_something_expensive();
        TRACE_INSTANT(...
    }
#endif  // NTRACE

由於函式 do_something_expensive() 可能不存在於程式碼的追蹤停用版本中,因此上述範例會同時使用 #ifndefTRACE_ENABLED() 巨集。

如要進一步瞭解 TRACE_ENABLED 巨集,請參閱 TRACE_ENABLED

C 罩杯

如果未定義 NTRACE,系統會在程式碼中編譯追蹤記錄,TRACE_ENABLED() 巨集會判斷追蹤記錄供應器是否已開啟。如果是編譯的追蹤記錄,TRACE_ENABLED() 一律會傳回 false。

#ifndef NTRACE
    if (TRACE_ENABLED()) {
        int v = do_something_expensive();
        TRACE_INSTANT(...
    }
#endif  // NTRACE

由於函式 do_something_expensive() 可能不存在於程式碼的追蹤停用版本中,因此上述範例會同時使用 #ifndefTRACE_ENABLED() 巨集。

如要進一步瞭解 TRACE_ENABLED 巨集,請參閱 TRACE_ENABLED

在元件中加入追蹤程式碼後,您現在可以從元件收集追蹤記錄。詳情請參閱下一篇「記錄及顯示追蹤記錄」頁面。