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