Commit | Line | Data |
---|---|---|
5e0cbfb0 PP |
1 | --- |
2 | id: tracepoint-provider | |
3 | --- | |
4 | ||
5 | Before jumping into defining tracepoints and inserting | |
6 | them into the application source code, you must understand what a | |
7 | _tracepoint provider_ is. | |
8 | ||
9 | For the sake of this guide, consider the following two files: | |
10 | ||
11 | `tp.h`: | |
12 | ||
13 | ~~~ c | |
14 | #undef TRACEPOINT_PROVIDER | |
15 | #define TRACEPOINT_PROVIDER my_provider | |
16 | ||
17 | #undef TRACEPOINT_INCLUDE | |
18 | #define TRACEPOINT_INCLUDE "./tp.h" | |
19 | ||
20 | #if !defined(_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) | |
21 | #define _TP_H | |
22 | ||
23 | #include <lttng/tracepoint.h> | |
24 | ||
25 | TRACEPOINT_EVENT( | |
26 | my_provider, | |
27 | my_first_tracepoint, | |
28 | TP_ARGS( | |
29 | int, my_integer_arg, | |
30 | char*, my_string_arg | |
31 | ), | |
32 | TP_FIELDS( | |
33 | ctf_string(my_string_field, my_string_arg) | |
34 | ctf_integer(int, my_integer_field, my_integer_arg) | |
35 | ) | |
36 | ) | |
37 | ||
38 | TRACEPOINT_EVENT( | |
39 | my_provider, | |
40 | my_other_tracepoint, | |
41 | TP_ARGS( | |
42 | int, my_int | |
43 | ), | |
44 | TP_FIELDS( | |
45 | ctf_integer(int, some_field, my_int) | |
46 | ) | |
47 | ) | |
48 | ||
49 | #endif /* _TP_H */ | |
50 | ||
51 | #include <lttng/tracepoint-event.h> | |
52 | ~~~ | |
53 | ||
54 | `tp.c`: | |
55 | ||
56 | ~~~ c | |
57 | #define TRACEPOINT_CREATE_PROBES | |
58 | ||
59 | #include "tp.h" | |
60 | ~~~ | |
61 | ||
62 | The two files above are defining a _tracepoint provider_. A tracepoint | |
63 | provider is some sort of namespace for _tracepoint definitions_. Tracepoint | |
64 | definitions are written above with the `TRACEPOINT_EVENT()` macro, and allow | |
65 | eventual `tracepoint()` calls respecting their definitions to be inserted | |
66 | into the user application's C source code (we explore this in a | |
67 | later section). | |
68 | ||
69 | Many tracepoint definitions may be part of the same tracepoint provider | |
70 | and many tracepoint providers may coexist in a user space application. A | |
71 | tracepoint provider is packaged either: | |
72 | ||
73 | * directly into an existing user application's C source file | |
74 | * as an object file | |
75 | * as a static library | |
76 | * as a shared library | |
77 | ||
78 | The two files above, `tp.h` and `tp.c`, show a typical template for | |
79 | writing a tracepoint provider. LTTng-UST was designed so that two | |
80 | tracepoint providers should not be defined in the same header file. | |
81 | ||
82 | We will now go through the various parts of the above files and | |
83 | give them a meaning. As you may have noticed, the LTTng-UST API for | |
84 | C/C++ applications is some preprocessor sorcery. The LTTng-UST macros | |
85 | used in your application and those in the LTTng-UST headers are | |
86 | combined to produce actual source code needed to make tracing possible | |
87 | using LTTng. | |
88 | ||
89 | Let's start with the header file, `tp.h`. It begins with | |
90 | ||
91 | ~~~ c | |
92 | #undef TRACEPOINT_PROVIDER | |
93 | #define TRACEPOINT_PROVIDER my_provider | |
94 | ~~~ | |
95 | ||
96 | `TRACEPOINT_PROVIDER` defines the name of the provider to which the | |
47bfcb75 | 97 | following tracepoint definitions belong. It is used internally by |
5e0cbfb0 PP |
98 | LTTng-UST headers and _must_ be defined. Since `TRACEPOINT_PROVIDER` |
99 | could have been defined by another header file also included by the same | |
100 | C source file, the best practice is to undefine it first. | |
101 | ||
102 | <div class="tip"> | |
103 | <p><span class="t">Note:</span>Names in LTTng-UST follow the C | |
104 | <em>identifier</em> syntax (starting with a letter and containing either | |
105 | letters, numbers or underscores); they are <em>not</em> C strings | |
106 | (not surrounded by double quotes). This is because LTTng-UST macros | |
107 | use those identifier-like strings to create symbols (named types and | |
108 | variables).</p> | |
109 | </div> | |
110 | ||
111 | The tracepoint provider is a group of tracepoint definitions; its chosen | |
112 | name should reflect this. A hierarchy like Java packages is recommended, | |
4d46e8c0 PP |
113 | using underscores instead of dots, for example, |
114 | `org_company_project_component`. | |
5e0cbfb0 PP |
115 | |
116 | Next is `TRACEPOINT_INCLUDE`: | |
117 | ||
118 | ~~~ c | |
119 | #undef TRACEPOINT_INCLUDE | |
120 | #define TRACEPOINT_INCLUDE "./tp.h" | |
121 | ~~~ | |
122 | ||
123 | This little bit of instrospection is needed by LTTng-UST to include | |
124 | your header at various predefined places. | |
125 | ||
126 | Include guard follows: | |
127 | ||
128 | ~~~ c | |
129 | #if !defined(_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) | |
130 | #define _TP_H | |
131 | ~~~ | |
132 | ||
cd41f97c PP |
133 | Add these precompiler conditionals to ensure the tracepoint event |
134 | generation can include this file more than once. | |
5e0cbfb0 PP |
135 | |
136 | The `TRACEPOINT_EVENT()` macro is defined in a LTTng-UST header file which | |
137 | must be included: | |
138 | ||
139 | ~~~ c | |
140 | #include <lttng/tracepoint.h> | |
141 | ~~~ | |
142 | ||
47bfcb75 | 143 | This also allows the application to use the `tracepoint()` macro. |
5e0cbfb0 PP |
144 | |
145 | Next is a list of `TRACEPOINT_EVENT()` macro calls which create the | |
47bfcb75 | 146 | actual tracepoint definitions. We skip this for the moment and |
5e0cbfb0 PP |
147 | come back to how to use `TRACEPOINT_EVENT()` |
148 | [in a later section](#doc-defining-tracepoints). Just pay attention to | |
149 | the first argument: it's always the name of the tracepoint provider | |
150 | being defined in this header file. | |
151 | ||
152 | End of include guard: | |
153 | ||
154 | ~~~ c | |
155 | #endif /* _TP_H */ | |
156 | ~~~ | |
157 | ||
158 | Finally, include `<lttng/tracepoint-event.h>` to expand the macros: | |
159 | ||
160 | ~~~ c | |
161 | #include <lttng/tracepoint-event.h> | |
162 | ~~~ | |
163 | ||
164 | That's it for `tp.h`. Of course, this is only a header file; it must be | |
165 | included in some C source file to actually use it. This is the job of | |
166 | `tp.c`: | |
167 | ||
168 | ~~~ c | |
169 | #define TRACEPOINT_CREATE_PROBES | |
170 | ||
171 | #include "tp.h" | |
172 | ~~~ | |
173 | ||
174 | When `TRACEPOINT_CREATE_PROBES` is defined, the macros used in `tp.h`, | |
47bfcb75 | 175 | which is included just after, actually create the source code for |
5e0cbfb0 PP |
176 | LTTng-UST probes (global data structures and functions) out of your |
177 | tracepoint definitions. How exactly this is done is out of this text's scope. | |
178 | `TRACEPOINT_CREATE_PROBES` is discussed further | |
179 | in [Building/linking tracepoint providers and the user application](#doc-building-tracepoint-providers-and-user-application). | |
180 | ||
181 | You could include other header files like `tp.h` here to create the probes | |
4d46e8c0 | 182 | of different tracepoint providers, for example: |
5e0cbfb0 PP |
183 | |
184 | ~~~ c | |
185 | #define TRACEPOINT_CREATE_PROBES | |
186 | ||
187 | #include "tp1.h" | |
188 | #include "tp2.h" | |
189 | ~~~ | |
190 | ||
191 | The rule is: probes of a given tracepoint provider | |
192 | must be created in exactly one source file. This source file could be one | |
193 | of your project's; it doesn't have to be on its own like `tp.c`, although | |
194 | [a later section](#doc-building-tracepoint-providers-and-user-application) | |
195 | shows that doing so allows packaging the tracepoint providers | |
196 | independently and keep them out of your application, also making it | |
197 | possible to reuse them between projects. | |
198 | ||
199 | The following sections explain how to define tracepoints, how to use the | |
200 | `tracepoint()` macro to instrument your user space C application and how | |
201 | to build/link tracepoint providers and your application with LTTng-UST | |
202 | support. |