Adding tracing in your code
This guide shows how to add tracing to your code.
Note: For more information on the Fuchsia tracing system, see Fuchsia tracing system.
Prerequisites
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.
Add tracing to your component
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.
Trace an instant event {#instant-event}
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.
Disable tracing {#disable-tracing}
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.
Determine if tracing is on {#determine-if-tracing-is-on}
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.
Time an event {#time-an-event}
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.