This guide shows how to add tracing to your code.
Note: For more information on the Fuchsia tracing system, see Fuchsia tracing system.
Before you begin, make sure you have completed the following:
- Familiarized yourself with the Fuchsia tracing system. See Fuchsia tracing system.
- Registered your component as a tracing provider. See Registering a trace provider.
- Included the
libtrace
library to capture trace data. See libtrace: The C and C++ trace event library.
Once your component is a trace provider, you can perform the following types of tracing:
Note: The tracing macros should be added to the code of your component. For more information on the C and C++ tracing macros, see Tracing: C and C++ macros.
To write an instant event representing a single moment in time:
-
{C and C++}
TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS, "message", TA_STRING("Hello, World!"));
This example specifies a category of helloworld
, a name of hello_world_test
,
a scope of TRACE_SCOPE_PROCESS
, and a key and value pair.
For more information on the TRACE_INSTANT
macro, see
TRACE_INSTANT.
There are cases where you might wish to entirely disable tracing such
as when you are about to make a final release. If the NTRACE
macro
is in your code, then the tracing macros don't generate any code:
-
{C and C++}
#define NTRACE // disable tracing #include <lib/trace/event.h>
Make sure that you define the NTRACE
macro before the #include
statement.
In this example, the rx_count
and tx_count
fields are used only with
tracing, so if NTRACE
is asserted, which indicates that tracing is disabled,
the fields don't take up space in the my_statistics_t
structure.
-
{C and C++}
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;
However, you do need to conditionally compile the code for managing
the recording of the statistics. For example, you can use the
TRACE_INSTANT
macro:
-
{C and C++}
#ifndef NTRACE status.tx_count++; TRACE_INSTANT("bandwidth", "txpackets", TRACE_SCOPE_PROCESS, "count", TA_UINT64(status.tx_count)); #endif // NTRACE
For more information on the NTRACE
macro, see
NTRACE.
In some cases, you may need to determine if tracing is on at runtime.
If tracing is compiled in your code because NTRACE
is not defined,
the TRACE_ENABLED()
macro determines if tracing for your trace
provider is on.
If tracing is compiled out, then TRACE_ENABLED()
always returns
false.
For example:
-
{C and C++}
#ifndef NTRACE if (TRACE_ENABLED()) { int v = do_something_expensive(); TRACE_INSTANT(... } #endif // NTRACE
This example uses both the #ifndef
and the TRACE_ENABLED()
macro
together because the function do_something_expensive()
might not exist in the
trace-disabled version of your code.
For more information on the TRACE_ENABLED
macro, see
TRACE_ENABLED.
In some cases, you may need to time a function or procedure.
This example is from a blobfs
vnode constructor. See
//src/storage/blobfs/blobfs.cc.
-
{C++}
zx_status_t VnodeBlob::InitCompressed() { TRACE_DURATION("blobfs", "Blobfs::InitCompressed", "size", inode_.blob_size, "blocks", inode_.num_blocks); ...
This example records the length of time spent in the constructor, along with the size and number of blocks. Since this is a C++ example, the data types can be inferred by the compiler.
For more information on the TRACE_DURATION
macro, see
TRACE_DURATION.
Once you have added a tracing statement to your component, you can now collect a trace. For more information, see Recording a Fuchsia trace.