|  | # 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]. | 
|  |  | 
|  | Also, make sure to use the relevant library in your code: | 
|  |  | 
|  | <<../_common/_tracing_headers.md>> | 
|  |  | 
|  | ## 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). | 
|  | * [Time an event](#time-an-event). | 
|  | * [Disable tracing](#disable-tracing). | 
|  | * [Determine if tracing is on](#determine-if-tracing-is-on). | 
|  |  | 
|  | For the list of all available tracing macros, see | 
|  |  | 
|  | * [Rust Tracing macros][rust-macros]. | 
|  | * [C/C++ Tracing macros][c-cpp-macros]. | 
|  |  | 
|  | ### Trace an instant event {:#trace-an-instant-event} | 
|  |  | 
|  | The following example writes an instant event representing a single moment in time: | 
|  |  | 
|  | * {Rust} | 
|  |  | 
|  | ```rust | 
|  | fuchsia_trace::instant!(c"helloworld", c"hello_world_test", fuchsia_trace::Scope::Process, "message" => "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 `instant!` macro, see | 
|  | [`instant!`][trace-instant-rust]. | 
|  |  | 
|  | * {C++} | 
|  |  | 
|  | ```cpp | 
|  | TRACE_INSTANT("helloworld", "hello_world_test", TRACE_SCOPE_PROCESS, "message", "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]. | 
|  |  | 
|  | * {C } | 
|  |  | 
|  | ```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]. | 
|  |  | 
|  | ### Time an event {:#time-an-event transformation="converted"} | 
|  |  | 
|  | This example shows you how to time a function or procedure: | 
|  |  | 
|  | Note: This example is based on a a [`blobfs`][blobfs-cc] vnode constructor. | 
|  |  | 
|  | * {Rust} | 
|  |  | 
|  | ```rust | 
|  | fn InitCompressed() { | 
|  | fuchsia_trace::duration!(c"helloworld", c"hello_world_test", fuchsia_trace::Scope::Process, "message" => "Hello, World!"); | 
|  | ... | 
|  | // Duration ends due to RAII | 
|  | } | 
|  | ``` | 
|  |  | 
|  | This example records the length of time spent in the constructor, | 
|  | along with the size and number of blocks. | 
|  |  | 
|  | For more information on the `duration!` macro, see | 
|  | [`duration!`][trace-duration-rust]. | 
|  |  | 
|  | * {C++} | 
|  |  | 
|  | ```cpp | 
|  | zx_status_t VnodeBlob::InitCompressed() { | 
|  | TRACE_DURATION("blobfs", "Blobfs::InitCompressed", "size", inode_.blob_size, | 
|  | "blocks", inode_.num_blocks); | 
|  | ... | 
|  | // Duration ends due to RAII | 
|  | } | 
|  | ``` | 
|  |  | 
|  | 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 compiler can infer the data types. | 
|  |  | 
|  | For more information on the `TRACE_DURATION` macro, see | 
|  | [`TRACE_DURATION`][trace-duration]. | 
|  |  | 
|  | * {C } | 
|  |  | 
|  | ```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"); | 
|  | } | 
|  | ``` | 
|  |  | 
|  | This example records the length of time spent in the constructor, | 
|  | along with the size and number of blocks. | 
|  |  | 
|  | For more information on the `TRACE_DURATION_BEGIN` and `TRACE_DURATION_END` macros, see | 
|  | [`TRACE_DURATION_BEGIN`][trace-duration-begin] and [`TRACE_DURATION_END`][trace-duration-end]. | 
|  |  | 
|  | ### 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. | 
|  |  | 
|  | * {Rust} | 
|  |  | 
|  | ```rust | 
|  | if fuchsia_trace::is_enabled() { | 
|  | let v = do_something_expensive(); | 
|  | fuchsia_trace::instant!(... | 
|  | } | 
|  | ``` | 
|  |  | 
|  | The rust trace bindings don't support compile time checking if tracing is disabled. | 
|  | However, if tracing is disabled at compile time, checking `is_enabled` is | 
|  | not performance intensive. | 
|  |  | 
|  | For more information on `is_enabled`, see | 
|  | [`is_enabled`][trace-enabled-rust]. | 
|  |  | 
|  | * {C++} | 
|  |  | 
|  | 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. | 
|  |  | 
|  | ```cpp | 
|  | #ifndef NTRACE | 
|  | if (TRACE_ENABLED()) { | 
|  | int v = do_something_expensive(); | 
|  | TRACE_INSTANT(... | 
|  | } | 
|  | #endif  // NTRACE | 
|  | ``` | 
|  | The example above 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]. | 
|  |  | 
|  | * {C } | 
|  |  | 
|  | 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 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]. | 
|  |  | 
|  | 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 | 
|  | [c-cpp-macros]: /docs/reference/tracing/c_cpp_macros.md | 
|  | [rust-macros]: https://fuchsia-docs.firebaseapp.com/rust/fuchsia_trace/index.html | 
|  | [trace-instant]: /docs/reference/tracing/c_cpp_macros.md#TRACE_INSTANT | 
|  | [trace-instant-rust]: https://fuchsia-docs.firebaseapp.com/rust/fuchsia_trace/macro.instant.html | 
|  | [ntrace]: /docs/reference/tracing/c_cpp_macros.md#NTRACE | 
|  | [trace-enabled]: /docs/reference/tracing/c_cpp_macros.md#TRACE_ENABLED | 
|  | [trace-enabled-rust]: https://fuchsia-docs.firebaseapp.com/rust/fuchsia_trace/fn.is_enabled.html | 
|  | [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 | 
|  | [trace-duration-begin]: /docs/reference/tracing/c_cpp_macros.md#TRACE_DURATION_BEGIN | 
|  | [trace-duration-end]: /docs/reference/tracing/c_cpp_macros.md#TRACE_DURATION_END | 
|  | [trace-duration-rust]: https://fuchsia-docs.firebaseapp.com/rust/fuchsia_trace/fn.duration.html | 
|  | [record-and-visualize-a-trace]: /docs/development/tracing/tutorial/record-and-visualize-a-trace.md |