tracing-your-own-user-application: minor fixes
[lttng-docs.git] / contents / getting-started / tracing-your-own-user-application.md
1 ---
2 id: tracing-your-own-user-application
3 ---
4
5 The previous section helped you create a trace out of Linux kernel events.
6 This section steps you through a simple example showing you how to trace
7 a _Hello world_ program written in C.
8
9 Make sure the LTTng-tools and LTTng-UST packages
10 [are installed](#doc-installing-lttng).
11
12 Tracing is just like having `printf()` calls at specific locations of
13 your source code, albeit LTTng is much more faster and flexible than
14 `printf()`. In the LTTng realm, **`tracepoint()`** is analogous to
15 `printf()`.
16
17 Unlike `printf()`, though, `tracepoint()` does not use a format string to
18 know the types of its arguments: the formats of all tracepoints must be
19 defined before using them. So before even writing our _Hello world_ program,
20 we need to define the format of our tracepoint. This is done by creating a
21 **tracepoint provider**, which consists of a tracepoint provider header
22 (`.h` file) and a tracepoint provider definition (`.c` file).
23
24 The tracepoint provider header contains some boilerplate as well as a
25 list of tracepoint definitions and other optional definition entries
26 which we skip for this quickstart. Each tracepoint is defined using the
27 `TRACEPOINT_EVENT()` macro. For each tracepoint, you must provide:
28
29 * a **provider name**, which is the "scope" or namespace of this
30 tracepoint (this usually includes the company and project names)
31 * a **tracepoint name**
32 * a **list of arguments** for the eventual `tracepoint()` call, each
33 item being:
34 * the argument C type
35 * the argument name
36 * a **list of fields**, which correspond to the actual fields of the
37 recorded events for this tracepoint
38
39 Here's an example of a simple tracepoint provider header with two
40 arguments: an integer and a string:
41
42 ~~~ c
43 #undef TRACEPOINT_PROVIDER
44 #define TRACEPOINT_PROVIDER hello_world
45
46 #undef TRACEPOINT_INCLUDE
47 #define TRACEPOINT_INCLUDE "./tp.h"
48
49 #if !defined(_HELLO_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
50 #define _HELLO_TP_H
51
52 #include <lttng/tracepoint.h>
53
54 TRACEPOINT_EVENT(
55 hello_world,
56 my_first_tracepoint,
57 TP_ARGS(
58 int, my_integer_arg,
59 char*, my_string_arg
60 ),
61 TP_FIELDS(
62 ctf_string(my_string_field, my_string_arg)
63 ctf_integer(int, my_integer_field, my_integer_arg)
64 )
65 )
66
67 #endif /* _HELLO_TP_H */
68
69 #include <lttng/tracepoint-event.h>
70 ~~~
71
72 The exact syntax is well explained in the
73 [C application](#doc-c-application) instrumentation guide of the
74 [Using LTTng](#doc-using-lttng) chapter, as well as in the
75 <a href="/man/3/lttng-ust" class="ext">LTTng-UST man page</a>.
76
77 Save the above snippet as `hello-tp.h`.
78
79 Write the tracepoint provider definition as `hello-tp.c`:
80
81 ~~~ c
82 #define TRACEPOINT_CREATE_PROBES
83 #define TRACEPOINT_DEFINE
84
85 #include "hello-tp.h"
86 ~~~
87
88 Create the tracepoint provider:
89
90 <pre class="term">
91 gcc -c -I. hello-tp.c
92 </pre>
93
94 Now, by including `hello-tp.h` in your own application, you may use the
95 tracepoint defined above by properly refering to it when calling
96 `tracepoint()`:
97
98 ~~~ c
99 #include <stdio.h>
100 #include "hello-tp.h"
101
102 int main(int argc, char *argv[])
103 {
104 int x;
105
106 puts("Hello, World!\nPress Enter to continue...");
107
108 /*
109 * The following getchar() call is only placed here for the purpose
110 * of this demonstration, for pausing the application in order for
111 * you to have time to list its events. It's not needed otherwise.
112 */
113 getchar();
114
115 /*
116 * A tracepoint() call. Arguments, as defined in hello-tp.h:
117 *
118 * 1st: provider name (always)
119 * 2nd: tracepoint name (always)
120 * 3rd: my_integer_arg (first user-defined argument)
121 * 4th: my_string_arg (second user-defined argument)
122 *
123 * Notice the provider and tracepoint names are NOT strings;
124 * they are in fact parts of variables created by macros in
125 * hello-tp.h.
126 */
127 tracepoint(hello_world, my_first_tracepoint, 23, "hi there!");
128
129 for (x = 0; x < argc; ++x) {
130 tracepoint(hello_world, my_first_tracepoint, x, argv[x]);
131 }
132
133 puts("Quitting now!");
134
135 tracepoint(hello_world, my_first_tracepoint, x * x, "x^2");
136
137 return 0;
138 }
139 ~~~
140
141 Save this as `hello.c`, next to `hello-tp.c`.
142
143 Notice `hello-tp.h`, the tracepoint provider header, is included
144 by `hello.c`.
145
146 You are now ready to compile the application with LTTng-UST support:
147
148 <pre class="term">
149 gcc -c hello.c
150 gcc -o hello hello.o hello-tp.o -llttng-ust -ldl</strong>
151 </pre>
152
153 Here's the whole build process:
154
155 <div class="img">
156 <img src="/images/docs26/ust-flow.png" alt="User space tracing's build process">
157 </div>
158
159 If you followed the
160 [Tracing the Linux kernel](#doc-tracing-the-linux-kernel) tutorial, the
161 following steps should look familiar.
162
163 First, run the application with a few arguments:
164
165 <pre class="term">
166 ./hello world and beyond
167 </pre>
168
169 You should see
170
171 ~~~ text
172 Hello, World!
173 Press Enter to continue...
174 ~~~
175
176 Use the `lttng` tool to list all available user space events:
177
178 <pre class="term">
179 lttng list --userspace
180 </pre>
181
182 You should see the `hello_world:my_first_tracepoint` tracepoint listed
183 under the `./hello` process.
184
185 Create a tracing session:
186
187 <pre class="term">
188 lttng create
189 </pre>
190
191 Enable the `hello_world:my_first_tracepoint` tracepoint:
192
193 <pre class="term">
194 lttng enable-event --userspace hello_world:my_first_tracepoint
195 </pre>
196
197 Start tracing:
198
199 <pre class="term">
200 lttng start
201 </pre>
202
203 Go back to the running `hello` application and press Enter. All `tracepoint()`
204 calls are executed and the program finally exits.
205
206 Stop tracing:
207
208 <pre class="term">
209 lttng stop
210 </pre>
211
212 Done! You may use `lttng view` to list the recorded events. This command
213 starts
214 <a href="http://diamon.org/babeltrace" class="ext"><code>babeltrace</code></a>
215 in the background, if it's installed:
216
217 <pre class="term">
218 lttng view
219 </pre>
220
221 should output something like:
222
223 ~~~ text
224 [18:10:27.684304496] (+?.?????????) hostname hello_world:my_first_tracepoint: { cpu_id = 0 }, { my_string_field = "hi there!", my_integer_field = 23 }
225 [18:10:27.684338440] (+0.000033944) hostname hello_world:my_first_tracepoint: { cpu_id = 0 }, { my_string_field = "./hello", my_integer_field = 0 }
226 [18:10:27.684340692] (+0.000002252) hostname hello_world:my_first_tracepoint: { cpu_id = 0 }, { my_string_field = "world", my_integer_field = 1 }
227 [18:10:27.684342616] (+0.000001924) hostname hello_world:my_first_tracepoint: { cpu_id = 0 }, { my_string_field = "and", my_integer_field = 2 }
228 [18:10:27.684343518] (+0.000000902) hostname hello_world:my_first_tracepoint: { cpu_id = 0 }, { my_string_field = "beyond", my_integer_field = 3 }
229 [18:10:27.684357978] (+0.000014460) hostname hello_world:my_first_tracepoint: { cpu_id = 0 }, { my_string_field = "x^2", my_integer_field = 16 }
230 ~~~
231
232 When you're done, you may destroy the tracing session, which does _not_
233 destroy the generated trace files, leaving them available for further
234 analysis:
235
236 <pre class="term">
237 lttng destroy
238 </pre>
239
240 The next section presents other alternatives to view and analyze your
241 LTTng traces.
This page took 0.033839 seconds and 4 git commands to generate.