本页介绍了如何向 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_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
。
确定跟踪功能是否处于开启状态
在某些情况下,您可能需要确定跟踪功能在运行时是否处于开启状态。
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
上述示例同时使用了 #ifndef
和 TRACE_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
上述示例同时使用了 #ifndef
和 TRACE_ENABLED()
宏,因为函数 do_something_expensive()
可能不存在于已停用轨迹的代码版本中。
如需详细了解 TRACE_ENABLED
宏,请参阅 TRACE_ENABLED
。
向组件添加跟踪代码后,您现在可以从组件收集轨迹。如需了解详情,请参阅下一部分中的记录和可视化轨迹。