1# Adding tracing to device drivers 2 3This document describes how to add tracing to device drivers. 4 5## Overview 6 7Please read [Fuchsia Tracing System Design](../tracing/design.md) 8for an overview of tracing. 9 10## Trace Provider 11 12Drivers don't have to specify a Trace Provider, the devhost process 13via `libdriver.so` provides it. It is mentioned here in case the topic 14comes up. 15 16## Adding trace records 17 18### Source additions 19 20Trace records are easiest to add by invoking the `TRACE_*()` macros 21from `ddk/trace/event.h`. 22 23There are various kinds of trace records that can be emitted. 24Please see `trace/internal/event_common.h` for a description 25of the various macros. 26 27Looking up macro documentation from internal implementation files 28is a temporary situation. Ultimately such documentation will live 29in a more appropriate place. 30 31Example: 32 33```c++ 34#include <ddk/trace/event.h> 35 36void DoSomething(int a, std::string b) { 37 TRACE_DURATION("example:example1", "DoSomething", "a", a, "b", b); 38 39 // Do something 40} 41``` 42 43The first two arguments to most macros are the "category" and the 44event name. Here they are "example:example1" and "DoSomething" respectively. 45 46Trace categories are how the tracing system lets the user specify 47what data to collect. If a category is not requested by the user 48then the data is not collected. 49 50Categories don't need to be unique across the driver. 51One typically groups several events under the same category. 52By convention categories have the format 53"<provider-name>:<category-name>[:<subcategory1-name>...]". 54"<provider-name>" for drivers should generally by the driver name. 55This is done to avoid collisions in category names across the 56entire system. A potential augmentation to this convention is to prefix 57all driver categories with "driver:". E.g., "driver:ethernet:packets". 58Avoiding naming collisions with other trace providers is important, 59otherwise the user may ask for a particular category and get completely 60unrelated data from a different trace provider. 61 62The event name is included in the trace to describe what the event 63is about. It is typically unique for each event. 64 65Note that currently the default is that no code will be generated 66by the addition of these `TRACE_*()` macros. Akin to <assert.h>'s use of 67`#define NDEBUG` to disable `assert()`s, tracing uses `#define NTRACE` to 68disable tracing. `NTRACE` is currently defined by default unless 69`ENABLE_DRIVER_TRACING=true` is passed to `make`. See below. 70 71### Makefile additions 72 73The following addition to your driver's `rules.mk` file is needed to 74pick up tracing support: 75 76```make 77ifeq ($(call TOBOOL,$(ENABLE_DRIVER_TRACING)),true) 78MODULE_STATIC_LIBS += system/ulib/trace.driver 79endif 80MODULE_HEADER_DEPS += system/ulib/trace system/ulib/trace-engine 81``` 82 83## Booting with tracing 84 85To be super conservative, not only does tracing currently require a special 86compile flag to enable it: `ENABLE_DRIVER_TRACING=true`, 87it also requires an extra kernel command line flag to enable it: 88`driver.tracing.enable=1` 89 90`ENABLE_DRIVER_TRACING=true` is now the default. To disable compiling in 91driver tracing support, pass `ENABLE_DRIVER_TRACING=false` to make. 92 93`driver.tracing.enable=1` is also now the default. To disable partipation 94of drivers in Fuchsia tracing, boot the kernel with `driver.tracing.enable=0`. 95 96Example: 97 98First build: 99 100```sh 101$ fx set $arch 102$ fx build-zircon 103$ fx build 104``` 105 106Then boot. With QEMU: 107 108```sh 109$ fx run -- -k -N 110``` 111 112Or on h/w (augment with options specific to your h/w): 113 114```sh 115$ fx serve 116``` 117 118These extra requirements will be removed once tracing support stabilizes. 119 120## Using tracing 121 122Once the system is booted you can collect traces on the target and 123then manually copy them to your development host. 124These examples use the category from the source additions described above. 125 126Example: 127 128```sh 129fuchsia$ trace record --categories=example:example1 130host$ fx cp --to-host /data/trace.json trace.json 131``` 132 133However, it's easier to invoke the `traceutil` program on your development 134host and it will copy the files directly to your host and prepare them for 135viewing with the Chrome trace viewer. 136 137```sh 138host$ fx traceutil record --categories=example:example1 139``` 140 141See the [Tracing Usage Guide](https://fuchsia.googlesource.com/garnet/+/master/docs/tracing_usage_guide.md) 142for further info. 143