Add tracing in your code

This page describes how to add tracing to your Fuchsia component's code.

Prerequisites

Before you begin, make sure you have completed the following tasks:

Use tracing macros in your code

Once your component is registered as a trace provider, you can add tracing in your component's code.

The following actions are often useful and can easily be added in the code using the tracing macros:

For the list of all available tracing macros, see Tracing: C and C++ macros.

Trace an instant event

The following example (for C and C++) writes an instant event representing a single moment in time:

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

There are cases where you may wish to entirely disable tracing (for instance, when you are about to release the component into production). If the NTRACE macro is added in your code, the tracing macros do not generate any code.

The following example (for C and C++) shows the NTRACE macro:

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

Make sure that you define the NTRACE macro before the #includestatement.

In the example below, 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 do not take up space in the my_statistics_t structure.

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, if you do need to conditionally compile the code for managing the recording of the statistics, you can use the TRACE_INSTANT macro:

#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

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, TRACE_ENABLED() always returns false.

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

The example above (for C and C++) uses both the #ifndef and the TRACE_ENABLED() macro together because the function do_something_expensive() may not exist in the trace-disabled version of your code.

For more information on the TRACE_ENABLED macro, see TRACE_ENABLED.

Time an event

If you need to time a function or procedure, see the example below (for C++) from a blobfs vnode constructor:

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 tracing code to your component, you can now collect a trace from the component. For more information, see the next Record and visualize a trace page.