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 | |
97 | following tracepoint definitions will belong. It is used internally by | |
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, | |
113 | using underscores instead of dots, e.g., `org_company_project_component`. | |
114 | ||
115 | Next is `TRACEPOINT_INCLUDE`: | |
116 | ||
117 | ~~~ c | |
118 | #undef TRACEPOINT_INCLUDE | |
119 | #define TRACEPOINT_INCLUDE "./tp.h" | |
120 | ~~~ | |
121 | ||
122 | This little bit of instrospection is needed by LTTng-UST to include | |
123 | your header at various predefined places. | |
124 | ||
125 | Include guard follows: | |
126 | ||
127 | ~~~ c | |
128 | #if !defined(_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ) | |
129 | #define _TP_H | |
130 | ~~~ | |
131 | ||
132 | Add this precompiler conditionals to ensure the tracepoint event generation | |
133 | can include this file more than once. | |
134 | ||
135 | The `TRACEPOINT_EVENT()` macro is defined in a LTTng-UST header file which | |
136 | must be included: | |
137 | ||
138 | ~~~ c | |
139 | #include <lttng/tracepoint.h> | |
140 | ~~~ | |
141 | ||
142 | This will also allow the application to use the `tracepoint()` macro. | |
143 | ||
144 | Next is a list of `TRACEPOINT_EVENT()` macro calls which create the | |
145 | actual tracepoint definitions. We will skip this for the moment and | |
146 | come back to how to use `TRACEPOINT_EVENT()` | |
147 | [in a later section](#doc-defining-tracepoints). Just pay attention to | |
148 | the first argument: it's always the name of the tracepoint provider | |
149 | being defined in this header file. | |
150 | ||
151 | End of include guard: | |
152 | ||
153 | ~~~ c | |
154 | #endif /* _TP_H */ | |
155 | ~~~ | |
156 | ||
157 | Finally, include `<lttng/tracepoint-event.h>` to expand the macros: | |
158 | ||
159 | ~~~ c | |
160 | #include <lttng/tracepoint-event.h> | |
161 | ~~~ | |
162 | ||
163 | That's it for `tp.h`. Of course, this is only a header file; it must be | |
164 | included in some C source file to actually use it. This is the job of | |
165 | `tp.c`: | |
166 | ||
167 | ~~~ c | |
168 | #define TRACEPOINT_CREATE_PROBES | |
169 | ||
170 | #include "tp.h" | |
171 | ~~~ | |
172 | ||
173 | When `TRACEPOINT_CREATE_PROBES` is defined, the macros used in `tp.h`, | |
174 | which is included just after, will actually create the source code for | |
175 | LTTng-UST probes (global data structures and functions) out of your | |
176 | tracepoint definitions. How exactly this is done is out of this text's scope. | |
177 | `TRACEPOINT_CREATE_PROBES` is discussed further | |
178 | in [Building/linking tracepoint providers and the user application](#doc-building-tracepoint-providers-and-user-application). | |
179 | ||
180 | You could include other header files like `tp.h` here to create the probes | |
181 | of different tracepoint providers, e.g.: | |
182 | ||
183 | ~~~ c | |
184 | #define TRACEPOINT_CREATE_PROBES | |
185 | ||
186 | #include "tp1.h" | |
187 | #include "tp2.h" | |
188 | ~~~ | |
189 | ||
190 | The rule is: probes of a given tracepoint provider | |
191 | must be created in exactly one source file. This source file could be one | |
192 | of your project's; it doesn't have to be on its own like `tp.c`, although | |
193 | [a later section](#doc-building-tracepoint-providers-and-user-application) | |
194 | shows that doing so allows packaging the tracepoint providers | |
195 | independently and keep them out of your application, also making it | |
196 | possible to reuse them between projects. | |
197 | ||
198 | The following sections explain how to define tracepoints, how to use the | |
199 | `tracepoint()` macro to instrument your user space C application and how | |
200 | to build/link tracepoint providers and your application with LTTng-UST | |
201 | support. |