blob: a0ebc21a732b284bf88355e90cdd934d69787a46 [file] [log] [blame] [view] [edit]
# 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:
* [Familiarize yourself with the Fuchsia tracing system][fuchsia-tracing-system].
* [Register your component as a tracing provider][register-a-trace-provider].
* [Include the `libtrace` library to capture trace data][libtrace-trace-event].
## Use tracing macros in your code {:#use-tracing-macros-in-your-code}
Once your component is registered as a [trace provider][register-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:
* [Trace an instant event](#trace-an-instant-event).
* [Disable tracing](#disable-tracing).
* [Determine if tracing is on](#determine-if-tracing-is-on).
* [Time an event](#time-an-event).
For the list of all available tracing macros, see
[Tracing: C and C++ macros][c-cpp-macros].
### Trace an instant event {:#trace-an-instant-event}
The following example (for C and C++) writes an instant event
representing a single moment in time:
```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`][trace-instant].
### Disable tracing {:#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:
```c
#define NTRACE // disable tracing
#include <lib/trace/event.h>
```
Make sure that you define the `NTRACE` macro before the `#include`statement.
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.
```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, if you do need to conditionally compile the code for managing
the recording of the statistics, you can use the `TRACE_INSTANT` macro:
```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`][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, `TRACE_ENABLED()` always
returns false.
```c
#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`][trace-enabled].
### Time an event {:#time-an-event transformation="converted"}
If you need to time a function or procedure, see the example below (for C++)
from a [`blobfs`][blobfs-cc] vnode constructor:
```cpp
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`][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][record-and-visualize-a-trace] page.
<!-- Reference links -->
[fuchsia-tracing-system]: /docs/concepts/kernel/tracing-system.md
[register-a-trace-provider]: /docs/development/tracing/tutorial/register-a-trace-provider.md
[libtrace-trace-event]: /docs/reference/tracing/libraries.md#libtrace-trace-event
[c-cpp-macros]: /docs/reference/tracing/c_cpp_macros.md
[trace-instant]: /docs/reference/tracing/c_cpp_macros.md#TRACE_INSTANT
[ntrace]: /docs/reference/tracing/c_cpp_macros.md#NTRACE
[trace-enabled]: /docs/reference/tracing/c_cpp_macros.md#TRACE_ENABLED
[blobfs-cc]: https://cs.opensource.google/fuchsia/fuchsia/+/main:/src/storage/blobfs/blobfs.cc
[trace-duration]: /docs/reference/tracing/c_cpp_macros.md#TRACE_DURATION
[record-and-visualize-a-trace]: /docs/development/tracing/tutorial/record-and-visualize-a-trace.md