在代码中添加跟踪记录

本页介绍了如何向 Fuchsia 组件的代码添加跟踪功能。

前提条件

在开始之前,请确保您已完成以下任务:

此外,请务必在代码中使用相关库:

C

#include <lib/trace/event.h>

C++

#include <lib/trace/event.h>

Rust

use fuchsia_trace::{ArgValue, Scope, ...};

在代码中使用跟踪宏

将组件注册为轨迹提供程序后,您就可以在组件的代码中添加轨迹了。

以下操作通常很有用,并且可以使用跟踪宏轻松添加到代码中:

如需查看所有可用跟踪宏的列表,请参阅

跟踪即时事件

以下示例会写入一个瞬时事件,表示一瞬间的时间:

Rust

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

为活动计时

以下示例展示了如何对函数或过程进行计时:

Rust

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

确定跟踪功能是否处于开启状态

在某些情况下,您可能需要确定跟踪功能在运行时是否处于开启状态。

Rust

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

上述示例同时使用了 #ifndefTRACE_ENABLED() 宏,因为函数 do_something_expensive() 可能不存在于已停用轨迹的代码版本中。

如需详细了解 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

上述示例同时使用了 #ifndefTRACE_ENABLED() 宏,因为函数 do_something_expensive() 可能不存在于已停用轨迹的代码版本中。

如需详细了解 TRACE_ENABLED 宏,请参阅 TRACE_ENABLED

向组件添加跟踪代码后,您现在可以从组件收集轨迹。如需了解详情,请参阅下一部分中的记录和可视化轨迹