/src/haproxy/include/haproxy/trace.h
Line | Count | Source |
1 | | /* |
2 | | * include/haproxy/trace.h |
3 | | * This file provides functions for runtime tracing |
4 | | * |
5 | | * Copyright (C) 2000-2019 Willy Tarreau - w@1wt.eu |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation, version 2.1 |
10 | | * exclusively. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #ifndef _HAPROXY_TRACE_H |
23 | | #define _HAPROXY_TRACE_H |
24 | | |
25 | | #include <import/ist.h> |
26 | | #include <haproxy/api.h> |
27 | | #include <haproxy/list.h> |
28 | | #include <haproxy/sink-t.h> |
29 | | #include <haproxy/tools.h> |
30 | | #include <haproxy/trace-t.h> |
31 | | |
32 | | /* Make a string from the location of the trace producer as "file:line" */ |
33 | | #define TRC_LOC _TRC_LOC(__FILE__, __LINE__) |
34 | | #define _TRC_LOC(f,l) __TRC_LOC(f, ":", l) |
35 | | #define __TRC_LOC(f,c,l) f c #l |
36 | | |
37 | | #if defined(USE_TRACE) |
38 | | |
39 | | /* truncate a macro arg list to exactly 5 args and replace missing ones with NULL. |
40 | | * The first one (a0) is always ignored. |
41 | | */ |
42 | 0 | #define TRC_5ARGS(a0,a1,a2,a3,a4,a5,...) DEFNULL(a1),DEFNULL(a2),DEFNULL(a3),DEFNULL(a4),DEFNULL(a5) |
43 | | |
44 | | /* reports whether trace is active for the source and the arguments. It uses |
45 | | * the same criteria as trace() (locking, filtering etc) so it's safe to use |
46 | | * from application code to decide whether or not to engage in heavier data |
47 | | * preparation processing. |
48 | | */ |
49 | | #define _trace_enabled(level, mask, src, args...) \ |
50 | 0 | (unlikely(((src)->state != TRACE_STATE_STOPPED || (src)->follow) && \ |
51 | 0 | __trace_enabled(level, mask, src, ##args, NULL) > 0)) |
52 | | |
53 | | /* sends a trace for the given source. Arguments are passed in the exact same |
54 | | * order as in the __trace() function, which is only called if (src)->state is |
55 | | * not TRACE_STATE_STOPPED. This is the only case where arguments are evaluated. |
56 | | */ |
57 | | #define _trace(level, mask, src, args...) \ |
58 | 0 | do { \ |
59 | 0 | if (unlikely((src)->state != TRACE_STATE_STOPPED || (src)->follow)) \ |
60 | 0 | __trace(level, mask, src, ##args); \ |
61 | 0 | } while (0) |
62 | | |
63 | | /* For convenience, TRACE() alone uses the file's default TRACE_LEVEL, most |
64 | | * likely TRACE_LEVEL_DEVELOPER, though the other explicit variants specify |
65 | | * the desired level and will work when TRACE_LEVEL is not set. The 5 optional |
66 | | * arguments are the 4 source-specific arguments that are passed to the cb() |
67 | | * callback dedicated to decoding, and which may be used for special tracking. |
68 | | * These 4 arguments as well as the cb() function pointer may all be NULL, or |
69 | | * simply omitted (in which case they will be replaced by a NULL). This |
70 | | * ordering allows many TRACE() calls to be placed using copy-paste and just |
71 | | * change the message at the beginning. Only TRACE_DEVEL(), TRACE_ENTER() and |
72 | | * TRACE_LEAVE() will report the calling function's name. TRACE_PRINTF() does |
73 | | * require all the optional a1..a4 to be passed (possibly zero) so that they're |
74 | | * always followed by the format string, then the values to be formatted. |
75 | | * |
76 | | * TRACE_* will call the _trace() macro which will test if the trace is enabled |
77 | | * before calling the __trace() function. _trace() shouldn't be a function (nor |
78 | | * inline) itself because we don't want the caller to compute its arguments if |
79 | | * traces are not enabled. |
80 | | * |
81 | | * TRACE_ENABLED() reports whether or not trace is enabled for the current |
82 | | * source, level, mask and arguments. |
83 | | */ |
84 | 0 | #define TRACE_ENABLED(level, mask, args...) (_trace_enabled((level), (mask), TRACE_SOURCE, ist(TRC_LOC), ist(__FUNCTION__), ##args)) |
85 | | |
86 | | #define TRACE(msg, mask, args...) \ |
87 | | _trace(TRACE_LEVEL, (mask), TRACE_SOURCE, ist(TRC_LOC), IST_NULL, TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
88 | | |
89 | | #define TRACE_ERROR(msg, mask, args...) \ |
90 | 0 | _trace(TRACE_LEVEL_ERROR, (mask), TRACE_SOURCE, ist(TRC_LOC), IST_NULL, TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
91 | | |
92 | | #define TRACE_USER(msg, mask, args...) \ |
93 | | _trace(TRACE_LEVEL_USER, (mask), TRACE_SOURCE, ist(TRC_LOC), IST_NULL, TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
94 | | |
95 | | #define TRACE_DATA(msg, mask, args...) \ |
96 | 0 | _trace(TRACE_LEVEL_DATA, (mask), TRACE_SOURCE, ist(TRC_LOC), IST_NULL, TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
97 | | |
98 | | #define TRACE_PROTO(msg, mask, args...) \ |
99 | 0 | _trace(TRACE_LEVEL_PROTO, (mask), TRACE_SOURCE, ist(TRC_LOC), IST_NULL, TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
100 | | |
101 | | #define TRACE_STATE(msg, mask, args...) \ |
102 | 0 | _trace(TRACE_LEVEL_STATE, (mask), TRACE_SOURCE, ist(TRC_LOC), IST_NULL, TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
103 | | |
104 | | #define TRACE_DEVEL(msg, mask, args...) \ |
105 | 0 | _trace(TRACE_LEVEL_DEVELOPER, (mask), TRACE_SOURCE, ist(TRC_LOC), ist(__FUNCTION__), TRC_5ARGS(0,##args,0,0,0,0,0), ist(msg)) |
106 | | |
107 | | #define TRACE_ENTER(mask, args...) \ |
108 | 0 | _trace(TRACE_LEVEL_DEVELOPER, (mask), TRACE_SOURCE, ist(TRC_LOC), ist(__FUNCTION__), TRC_5ARGS(0,##args,0,0,0,0,0), ist("entering")) |
109 | | |
110 | | #define TRACE_LEAVE(mask, args...) \ |
111 | 0 | _trace(TRACE_LEVEL_DEVELOPER, (mask), TRACE_SOURCE, ist(TRC_LOC), ist(__FUNCTION__), TRC_5ARGS(0,##args,0,0,0,0,0), ist("leaving")) |
112 | | |
113 | | #define TRACE_POINT(mask, args...) \ |
114 | 0 | _trace(TRACE_LEVEL_DEVELOPER, (mask), TRACE_SOURCE, ist(TRC_LOC), ist(__FUNCTION__), TRC_5ARGS(0,##args,0,0,0,0,0), ist("in")) |
115 | | |
116 | | /* This produces a printf-like trace at level <level> for event mask <mask> and |
117 | | * trace arguments <a1..a4>. All args mandatory, but may be zero. No output |
118 | | * callback will be used since we expect the caller to pass a fully formatted |
119 | | * message that must not be degraded. The output will be truncated to |
120 | | * TRACE_MAX_MSG-1 bytes (1023 by default). Caller must include <stdio.h> for |
121 | | * snprintf(). One call will lead to one independent message, which means that |
122 | | * multiple messages may be interleaved between threads, hence the caller is |
123 | | * encouraged to prepend a context at the beginning of the format string when |
124 | | * dumping lists or arrays. The _LOC variation takes the caller's location and |
125 | | * function name as an ist and a (const char *) respectively, it is meant for |
126 | | * being called from wrapper function which will work on behalf of a caller. |
127 | | */ |
128 | | #define TRACE_PRINTF(level, mask, a1, a2, a3, a4, fmt, args...) \ |
129 | 0 | TRACE_PRINTF_LOC(level, mask, ist(TRC_LOC), __FUNCTION__, a1, a2, a3, a4, fmt, ##args) |
130 | | |
131 | | #define TRACE_PRINTF_LOC(level, mask, trc_loc, func, a1, a2, a3, a4, fmt, args...) \ |
132 | 0 | do { \ |
133 | 0 | if (TRACE_ENABLED((level), (mask), a1, a2, a3, a4)) { \ |
134 | 0 | char _msg[TRACE_MAX_MSG]; \ |
135 | 0 | size_t _msg_len; \ |
136 | 0 | _msg_len = snprintf(_msg, sizeof(_msg), (fmt), ##args); \ |
137 | 0 | if (_msg_len >= sizeof(_msg)) \ |
138 | 0 | _msg_len = sizeof(_msg) - 1; \ |
139 | 0 | _trace((level), (mask), TRACE_SOURCE, \ |
140 | 0 | trc_loc, ist(func), a1, a2, a3, a4, \ |
141 | 0 | &trace_no_cb, ist2(_msg, _msg_len)); \ |
142 | 0 | } \ |
143 | 0 | } while (0) |
144 | | #else |
145 | | # define TRACE_ENABLED(level, mask, args...) 0 |
146 | | # define TRACE(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
147 | | # define TRACE_ERROR(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
148 | | # define TRACE_USER(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
149 | | # define TRACE_DATA(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
150 | | # define TRACE_PROTO(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
151 | | # define TRACE_STATE(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
152 | | # define TRACE_DEVEL(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
153 | | # define TRACE_ENTER(mask, args...) __eat_all_args(mask, ##args) |
154 | | # define TRACE_LEAVE(mask, args...) __eat_all_args(mask, ##args) |
155 | | # define TRACE_POINT(mask, args...) __eat_all_args(mask, ##args) |
156 | | # define TRACE_PRINTF(level, args...) __eat_all_args(level, ##args) |
157 | | # define TRACE_PRINTF_LOC(level, args...) __eat_all_args(level, ##args) |
158 | | #endif |
159 | | |
160 | | #if defined (USE_TRACE) && (defined(DEBUG_DEV) || defined(DEBUG_FULL)) |
161 | | # define DBG_TRACE(msg, mask, args...) TRACE(msg, mask, ##args) |
162 | | # define DBG_TRACE_ERROR(msg, mask, args...) TRACE_ERROR(msg, mask, ##args) |
163 | | # define DBG_TRACE_USER(msg, mask, args...) TRACE_USER(msg, mask, ##args) |
164 | | # define DBG_TRACE_DATA(msg, mask, args...) TRACE_DATA(msg, mask, ##args) |
165 | | # define DBG_TRACE_PROTO(msg, mask, args...) TRACE_PROTO(msg, mask, ##args) |
166 | | # define DBG_TRACE_STATE(msg, mask, args...) TRACE_STATE(msg, mask, ##args) |
167 | | # define DBG_TRACE_DEVEL(msg, mask, args...) TRACE_DEVEL(msg, mask, ##args) |
168 | | # define DBG_TRACE_ENTER(mask, args...) TRACE_ENTER(mask, ##args) |
169 | | # define DBG_TRACE_LEAVE(mask, args...) TRACE_LEAVE(mask, ##args) |
170 | | # define DBG_TRACE_POINT(mask, args...) TRACE_POINT(mask, ##args) |
171 | | # define DBG_TRACE_PRINTF(level, args...) TRACE_PRINTF(level, ##args) |
172 | | # define DBG_TRACE_PRINTF_LOC(level, args...) TRACE_PRINTF_LOC(level, ##args) |
173 | | #else |
174 | | # define DBG_TRACE(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
175 | | # define DBG_TRACE_ERROR(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
176 | 0 | # define DBG_TRACE_USER(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
177 | | # define DBG_TRACE_DATA(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
178 | | # define DBG_TRACE_PROTO(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
179 | 0 | # define DBG_TRACE_STATE(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
180 | 0 | # define DBG_TRACE_DEVEL(msg, mask, args...) __eat_all_args(msg, mask, ##args) |
181 | 0 | # define DBG_TRACE_ENTER(mask, args...) __eat_all_args(mask, ##args) |
182 | 0 | # define DBG_TRACE_LEAVE(mask, args...) __eat_all_args(mask, ##args) |
183 | 0 | # define DBG_TRACE_POINT(mask, args...) __eat_all_args(mask, ##args) |
184 | | # define DBG_TRACE_PRINTF(level, args...) __eat_all_args(level, ##args) |
185 | | # define DBG_TRACE_PRINTF_LOC(level, args...) __eat_all_args(level, ##args) |
186 | | #endif |
187 | | |
188 | | extern struct list trace_sources; |
189 | | extern THREAD_LOCAL struct buffer trace_buf; |
190 | | |
191 | | int __trace_enabled(enum trace_level level, uint64_t mask, struct trace_source *src, |
192 | | const struct ist where, const struct ist ist_func, |
193 | | const void *a1, const void *a2, const void *a3, const void *a4, |
194 | | const void **plockptr); |
195 | | |
196 | | void __trace(enum trace_level level, uint64_t mask, struct trace_source *src, |
197 | | const struct ist where, const struct ist ist_func, |
198 | | const void *a1, const void *a2, const void *a3, const void *a4, |
199 | | void (*cb)(enum trace_level level, uint64_t mask, const struct trace_source *src, |
200 | | const struct ist where, const struct ist func, |
201 | | const void *a1, const void *a2, const void *a3, const void *a4), |
202 | | const struct ist msg); |
203 | | |
204 | | void trace_no_cb(enum trace_level level, uint64_t mask, const struct trace_source *src, |
205 | | const struct ist where, const struct ist func, |
206 | | const void *a1, const void *a2, const void *a3, const void *a4); |
207 | | |
208 | | void trace_register_source(struct trace_source *source); |
209 | | |
210 | | int trace_add_cmd(const char *arg_src, char **errmsg); |
211 | | void trace_parse_cmds(void); |
212 | | |
213 | | /* return a single char to describe a trace state */ |
214 | | static inline char trace_state_char(enum trace_state st) |
215 | 0 | { |
216 | 0 | return (st == TRACE_STATE_RUNNING) ? 'R' : |
217 | 0 | (st == TRACE_STATE_WAITING) ? 'w' : |
218 | 0 | '.'; |
219 | 0 | } Unexecuted instantiation: debug.c:trace_state_char Unexecuted instantiation: haproxy.c:trace_state_char Unexecuted instantiation: peers.c:trace_state_char Unexecuted instantiation: session.c:trace_state_char Unexecuted instantiation: stream.c:trace_state_char Unexecuted instantiation: tcp_rules.c:trace_state_char Unexecuted instantiation: tcpcheck.c:trace_state_char Unexecuted instantiation: trace.c:trace_state_char Unexecuted instantiation: applet.c:trace_state_char Unexecuted instantiation: backend.c:trace_state_char Unexecuted instantiation: check.c:trace_state_char Unexecuted instantiation: filters.c:trace_state_char Unexecuted instantiation: haterm.c:trace_state_char Unexecuted instantiation: http_ana.c:trace_state_char Unexecuted instantiation: mux_spop.c:trace_state_char |
220 | | |
221 | | /* return a single char to describe an event state */ |
222 | | static inline char trace_event_char(uint64_t conf, uint64_t ev) |
223 | 0 | { |
224 | 0 | return (conf & ev) ? '+' : '-'; |
225 | 0 | } Unexecuted instantiation: debug.c:trace_event_char Unexecuted instantiation: haproxy.c:trace_event_char Unexecuted instantiation: peers.c:trace_event_char Unexecuted instantiation: session.c:trace_event_char Unexecuted instantiation: stream.c:trace_event_char Unexecuted instantiation: tcp_rules.c:trace_event_char Unexecuted instantiation: tcpcheck.c:trace_event_char Unexecuted instantiation: trace.c:trace_event_char Unexecuted instantiation: applet.c:trace_event_char Unexecuted instantiation: backend.c:trace_event_char Unexecuted instantiation: check.c:trace_event_char Unexecuted instantiation: filters.c:trace_event_char Unexecuted instantiation: haterm.c:trace_event_char Unexecuted instantiation: http_ana.c:trace_event_char Unexecuted instantiation: mux_spop.c:trace_event_char |
226 | | |
227 | | /* Temporarily disable trace using a cumulative counter. If called multiple |
228 | | * times, the same number of resume must be used to reactivate tracing. |
229 | | * |
230 | | * Returns the incremented counter value or 0 if already at the maximum value. |
231 | | */ |
232 | | static inline uint8_t trace_disable(void) |
233 | 0 | { |
234 | 0 | if (unlikely(th_ctx->trc_disable_ctr == UCHAR_MAX)) |
235 | 0 | return 0; |
236 | 0 | return ++th_ctx->trc_disable_ctr; |
237 | 0 | } Unexecuted instantiation: debug.c:trace_disable Unexecuted instantiation: haproxy.c:trace_disable Unexecuted instantiation: peers.c:trace_disable Unexecuted instantiation: session.c:trace_disable Unexecuted instantiation: stream.c:trace_disable Unexecuted instantiation: tcp_rules.c:trace_disable Unexecuted instantiation: tcpcheck.c:trace_disable Unexecuted instantiation: trace.c:trace_disable Unexecuted instantiation: applet.c:trace_disable Unexecuted instantiation: backend.c:trace_disable Unexecuted instantiation: check.c:trace_disable Unexecuted instantiation: filters.c:trace_disable Unexecuted instantiation: haterm.c:trace_disable Unexecuted instantiation: http_ana.c:trace_disable Unexecuted instantiation: mux_spop.c:trace_disable |
238 | | |
239 | | /* Resume tracing after a temporarily disabling. It may be called several times |
240 | | * as disable operation is cumulative. |
241 | | */ |
242 | | static inline void trace_resume(void) |
243 | 0 | { |
244 | 0 | if (th_ctx->trc_disable_ctr) |
245 | 0 | --th_ctx->trc_disable_ctr; |
246 | 0 | } Unexecuted instantiation: debug.c:trace_resume Unexecuted instantiation: haproxy.c:trace_resume Unexecuted instantiation: peers.c:trace_resume Unexecuted instantiation: session.c:trace_resume Unexecuted instantiation: stream.c:trace_resume Unexecuted instantiation: tcp_rules.c:trace_resume Unexecuted instantiation: tcpcheck.c:trace_resume Unexecuted instantiation: trace.c:trace_resume Unexecuted instantiation: applet.c:trace_resume Unexecuted instantiation: backend.c:trace_resume Unexecuted instantiation: check.c:trace_resume Unexecuted instantiation: filters.c:trace_resume Unexecuted instantiation: haterm.c:trace_resume Unexecuted instantiation: http_ana.c:trace_resume Unexecuted instantiation: mux_spop.c:trace_resume |
247 | | |
248 | | /* Resume tracing immediately even after multiple disable operations. |
249 | | * |
250 | | * Returns the old counter value. Useful to reactivate trace disabling at the |
251 | | * previous level. |
252 | | */ |
253 | | static inline uint8_t trace_force_resume(void) |
254 | 0 | { |
255 | 0 | const int val = th_ctx->trc_disable_ctr; |
256 | 0 | th_ctx->trc_disable_ctr = 0; |
257 | 0 | return val; |
258 | 0 | } Unexecuted instantiation: debug.c:trace_force_resume Unexecuted instantiation: haproxy.c:trace_force_resume Unexecuted instantiation: peers.c:trace_force_resume Unexecuted instantiation: session.c:trace_force_resume Unexecuted instantiation: stream.c:trace_force_resume Unexecuted instantiation: tcp_rules.c:trace_force_resume Unexecuted instantiation: tcpcheck.c:trace_force_resume Unexecuted instantiation: trace.c:trace_force_resume Unexecuted instantiation: applet.c:trace_force_resume Unexecuted instantiation: backend.c:trace_force_resume Unexecuted instantiation: check.c:trace_force_resume Unexecuted instantiation: filters.c:trace_force_resume Unexecuted instantiation: haterm.c:trace_force_resume Unexecuted instantiation: http_ana.c:trace_force_resume Unexecuted instantiation: mux_spop.c:trace_force_resume |
259 | | |
260 | | /* Set trace disabling counter to <disable>. Mostly useful with the value |
261 | | * returned from trace_force_resume() to restore tracing disable status to the |
262 | | * previous level. |
263 | | */ |
264 | | static inline void trace_reset_disable(uint8_t disable) |
265 | 0 | { |
266 | 0 | th_ctx->trc_disable_ctr = disable; |
267 | 0 | } Unexecuted instantiation: debug.c:trace_reset_disable Unexecuted instantiation: haproxy.c:trace_reset_disable Unexecuted instantiation: peers.c:trace_reset_disable Unexecuted instantiation: session.c:trace_reset_disable Unexecuted instantiation: stream.c:trace_reset_disable Unexecuted instantiation: tcp_rules.c:trace_reset_disable Unexecuted instantiation: tcpcheck.c:trace_reset_disable Unexecuted instantiation: trace.c:trace_reset_disable Unexecuted instantiation: applet.c:trace_reset_disable Unexecuted instantiation: backend.c:trace_reset_disable Unexecuted instantiation: check.c:trace_reset_disable Unexecuted instantiation: filters.c:trace_reset_disable Unexecuted instantiation: haterm.c:trace_reset_disable Unexecuted instantiation: http_ana.c:trace_reset_disable Unexecuted instantiation: mux_spop.c:trace_reset_disable |
268 | | |
269 | | #endif /* _HAPROXY_TRACE_H */ |
270 | | |
271 | | /* |
272 | | * Local variables: |
273 | | * c-indent-level: 8 |
274 | | * c-basic-offset: 8 |
275 | | * End: |
276 | | */ |