1 #include "git-compat-util.h"
3 #include "repository.h"
4 #include "run-command.h"
7 #include "trace2/tr2_dst.h"
8 #include "trace2/tr2_sysenv.h"
9 #include "trace2/tr2_tbuf.h"
10 #include "trace2/tr2_tgt.h"
11 #include "trace2/tr2_tls.h"
12 #include "trace2/tr2_tmr.h"
14 static struct tr2_dst tr2dst_normal
= {
15 .sysenv_var
= TR2_SYSENV_NORMAL
,
19 * Use the TR2_SYSENV_NORMAL_BRIEF setting to omit the "<time> <file>:<line>"
20 * fields from each line written to the builtin normal target.
22 * Unit tests may want to use this to help with testing.
24 static int tr2env_normal_be_brief
;
26 #define TR2FMT_NORMAL_FL_WIDTH (50)
28 static int fn_init(void)
30 int want
= tr2_dst_trace_want(&tr2dst_normal
);
37 brief
= tr2_sysenv_get(TR2_SYSENV_NORMAL_BRIEF
);
38 if (brief
&& *brief
&&
39 ((want_brief
= git_parse_maybe_bool(brief
)) != -1))
40 tr2env_normal_be_brief
= want_brief
;
45 static void fn_term(void)
47 tr2_dst_trace_disable(&tr2dst_normal
);
50 static void normal_fmt_prepare(const char *file
, int line
, struct strbuf
*buf
)
52 strbuf_setlen(buf
, 0);
54 if (!tr2env_normal_be_brief
) {
55 struct tr2_tbuf tb_now
;
57 tr2_tbuf_local_time(&tb_now
);
58 strbuf_addstr(buf
, tb_now
.buf
);
59 strbuf_addch(buf
, ' ');
62 strbuf_addf(buf
, "%s:%d ", file
, line
);
63 while (buf
->len
< TR2FMT_NORMAL_FL_WIDTH
)
64 strbuf_addch(buf
, ' ');
68 static void normal_io_write_fl(const char *file
, int line
,
69 const struct strbuf
*buf_payload
)
71 struct strbuf buf_line
= STRBUF_INIT
;
73 normal_fmt_prepare(file
, line
, &buf_line
);
74 strbuf_addbuf(&buf_line
, buf_payload
);
75 tr2_dst_write_line(&tr2dst_normal
, &buf_line
);
76 strbuf_release(&buf_line
);
79 static void fn_version_fl(const char *file
, int line
)
81 struct strbuf buf_payload
= STRBUF_INIT
;
83 strbuf_addf(&buf_payload
, "version %s", git_version_string
);
84 normal_io_write_fl(file
, line
, &buf_payload
);
85 strbuf_release(&buf_payload
);
88 static void fn_start_fl(const char *file
, int line
,
89 uint64_t us_elapsed_absolute UNUSED
, const char **argv
)
91 struct strbuf buf_payload
= STRBUF_INIT
;
93 strbuf_addstr(&buf_payload
, "start ");
94 sq_append_quote_argv_pretty(&buf_payload
, argv
);
95 normal_io_write_fl(file
, line
, &buf_payload
);
96 strbuf_release(&buf_payload
);
99 static void fn_exit_fl(const char *file
, int line
, uint64_t us_elapsed_absolute
,
102 struct strbuf buf_payload
= STRBUF_INIT
;
103 double elapsed
= (double)us_elapsed_absolute
/ 1000000.0;
105 strbuf_addf(&buf_payload
, "exit elapsed:%.6f code:%d", elapsed
, code
);
106 normal_io_write_fl(file
, line
, &buf_payload
);
107 strbuf_release(&buf_payload
);
110 static void fn_signal(uint64_t us_elapsed_absolute
, int signo
)
112 struct strbuf buf_payload
= STRBUF_INIT
;
113 double elapsed
= (double)us_elapsed_absolute
/ 1000000.0;
115 strbuf_addf(&buf_payload
, "signal elapsed:%.6f code:%d", elapsed
,
117 normal_io_write_fl(__FILE__
, __LINE__
, &buf_payload
);
118 strbuf_release(&buf_payload
);
121 static void fn_atexit(uint64_t us_elapsed_absolute
, int code
)
123 struct strbuf buf_payload
= STRBUF_INIT
;
124 double elapsed
= (double)us_elapsed_absolute
/ 1000000.0;
126 strbuf_addf(&buf_payload
, "atexit elapsed:%.6f code:%d", elapsed
, code
);
127 normal_io_write_fl(__FILE__
, __LINE__
, &buf_payload
);
128 strbuf_release(&buf_payload
);
131 static void maybe_append_string_va(struct strbuf
*buf
, const char *fmt
,
137 va_copy(copy_ap
, ap
);
138 strbuf_vaddf(buf
, fmt
, copy_ap
);
144 static void fn_error_va_fl(const char *file
, int line
, const char *fmt
,
147 struct strbuf buf_payload
= STRBUF_INIT
;
149 strbuf_addstr(&buf_payload
, "error");
151 strbuf_addch(&buf_payload
, ' ');
152 maybe_append_string_va(&buf_payload
, fmt
, ap
);
154 normal_io_write_fl(file
, line
, &buf_payload
);
155 strbuf_release(&buf_payload
);
158 static void fn_command_path_fl(const char *file
, int line
, const char *pathname
)
160 struct strbuf buf_payload
= STRBUF_INIT
;
162 strbuf_addf(&buf_payload
, "cmd_path %s", pathname
);
163 normal_io_write_fl(file
, line
, &buf_payload
);
164 strbuf_release(&buf_payload
);
167 static void fn_command_ancestry_fl(const char *file
, int line
, const char **parent_names
)
169 const char *parent_name
= NULL
;
170 struct strbuf buf_payload
= STRBUF_INIT
;
172 /* cmd_ancestry parent <- grandparent <- great-grandparent */
173 strbuf_addstr(&buf_payload
, "cmd_ancestry ");
174 while ((parent_name
= *parent_names
++)) {
175 strbuf_addstr(&buf_payload
, parent_name
);
176 /* if we'll write another one after this, add a delimiter */
177 if (parent_names
&& *parent_names
)
178 strbuf_addstr(&buf_payload
, " <- ");
181 normal_io_write_fl(file
, line
, &buf_payload
);
182 strbuf_release(&buf_payload
);
185 static void fn_command_name_fl(const char *file
, int line
, const char *name
,
186 const char *hierarchy
)
188 struct strbuf buf_payload
= STRBUF_INIT
;
190 strbuf_addf(&buf_payload
, "cmd_name %s", name
);
191 if (hierarchy
&& *hierarchy
)
192 strbuf_addf(&buf_payload
, " (%s)", hierarchy
);
193 normal_io_write_fl(file
, line
, &buf_payload
);
194 strbuf_release(&buf_payload
);
197 static void fn_command_mode_fl(const char *file
, int line
, const char *mode
)
199 struct strbuf buf_payload
= STRBUF_INIT
;
201 strbuf_addf(&buf_payload
, "cmd_mode %s", mode
);
202 normal_io_write_fl(file
, line
, &buf_payload
);
203 strbuf_release(&buf_payload
);
206 static void fn_alias_fl(const char *file
, int line
, const char *alias
,
209 struct strbuf buf_payload
= STRBUF_INIT
;
211 strbuf_addf(&buf_payload
, "alias %s -> ", alias
);
212 sq_append_quote_argv_pretty(&buf_payload
, argv
);
213 normal_io_write_fl(file
, line
, &buf_payload
);
214 strbuf_release(&buf_payload
);
217 static void fn_child_start_fl(const char *file
, int line
,
218 uint64_t us_elapsed_absolute UNUSED
,
219 const struct child_process
*cmd
)
221 struct strbuf buf_payload
= STRBUF_INIT
;
223 strbuf_addf(&buf_payload
, "child_start[%d]", cmd
->trace2_child_id
);
226 strbuf_addstr(&buf_payload
, " cd ");
227 sq_quote_buf_pretty(&buf_payload
, cmd
->dir
);
228 strbuf_addstr(&buf_payload
, ";");
232 * TODO if (cmd->env) { Consider dumping changes to environment. }
233 * See trace_add_env() in run-command.c as used by original trace.c
236 strbuf_addch(&buf_payload
, ' ');
238 strbuf_addstr(&buf_payload
, "git ");
239 sq_append_quote_argv_pretty(&buf_payload
, cmd
->args
.v
);
241 normal_io_write_fl(file
, line
, &buf_payload
);
242 strbuf_release(&buf_payload
);
245 static void fn_child_exit_fl(const char *file
, int line
,
246 uint64_t us_elapsed_absolute UNUSED
,
248 int code
, uint64_t us_elapsed_child
)
250 struct strbuf buf_payload
= STRBUF_INIT
;
251 double elapsed
= (double)us_elapsed_child
/ 1000000.0;
253 strbuf_addf(&buf_payload
, "child_exit[%d] pid:%d code:%d elapsed:%.6f",
254 cid
, pid
, code
, elapsed
);
255 normal_io_write_fl(file
, line
, &buf_payload
);
256 strbuf_release(&buf_payload
);
259 static void fn_child_ready_fl(const char *file
, int line
,
260 uint64_t us_elapsed_absolute UNUSED
,
262 const char *ready
, uint64_t us_elapsed_child
)
264 struct strbuf buf_payload
= STRBUF_INIT
;
265 double elapsed
= (double)us_elapsed_child
/ 1000000.0;
267 strbuf_addf(&buf_payload
, "child_ready[%d] pid:%d ready:%s elapsed:%.6f",
268 cid
, pid
, ready
, elapsed
);
269 normal_io_write_fl(file
, line
, &buf_payload
);
270 strbuf_release(&buf_payload
);
273 static void fn_exec_fl(const char *file
, int line
,
274 uint64_t us_elapsed_absolute UNUSED
,
275 int exec_id
, const char *exe
, const char **argv
)
277 struct strbuf buf_payload
= STRBUF_INIT
;
279 strbuf_addf(&buf_payload
, "exec[%d] ", exec_id
);
281 strbuf_addstr(&buf_payload
, exe
);
282 strbuf_addch(&buf_payload
, ' ');
284 sq_append_quote_argv_pretty(&buf_payload
, argv
);
285 normal_io_write_fl(file
, line
, &buf_payload
);
286 strbuf_release(&buf_payload
);
289 static void fn_exec_result_fl(const char *file
, int line
,
290 uint64_t us_elapsed_absolute UNUSED
,
291 int exec_id
, int code
)
293 struct strbuf buf_payload
= STRBUF_INIT
;
295 strbuf_addf(&buf_payload
, "exec_result[%d] code:%d", exec_id
, code
);
297 strbuf_addf(&buf_payload
, " err:%s", strerror(code
));
298 normal_io_write_fl(file
, line
, &buf_payload
);
299 strbuf_release(&buf_payload
);
302 static void fn_param_fl(const char *file
, int line
, const char *param
,
303 const char *value
, const struct key_value_info
*kvi
)
305 struct strbuf buf_payload
= STRBUF_INIT
;
306 enum config_scope scope
= kvi
->scope
;
307 const char *scope_name
= config_scope_name(scope
);
309 strbuf_addf(&buf_payload
, "def_param scope:%s %s=%s", scope_name
, param
,
311 normal_io_write_fl(file
, line
, &buf_payload
);
312 strbuf_release(&buf_payload
);
315 static void fn_repo_fl(const char *file
, int line
,
316 const struct repository
*repo
)
318 struct strbuf buf_payload
= STRBUF_INIT
;
320 strbuf_addstr(&buf_payload
, "worktree ");
321 sq_quote_buf_pretty(&buf_payload
, repo
->worktree
);
322 normal_io_write_fl(file
, line
, &buf_payload
);
323 strbuf_release(&buf_payload
);
326 static void fn_printf_va_fl(const char *file
, int line
,
327 uint64_t us_elapsed_absolute UNUSED
,
331 struct strbuf buf_payload
= STRBUF_INIT
;
333 maybe_append_string_va(&buf_payload
, fmt
, ap
);
334 normal_io_write_fl(file
, line
, &buf_payload
);
335 strbuf_release(&buf_payload
);
338 static void fn_timer(const struct tr2_timer_metadata
*meta
,
339 const struct tr2_timer
*timer
,
342 const char *event_name
= is_final_data
? "timer" : "th_timer";
343 struct strbuf buf_payload
= STRBUF_INIT
;
344 double t_total
= NS_TO_SEC(timer
->total_ns
);
345 double t_min
= NS_TO_SEC(timer
->min_ns
);
346 double t_max
= NS_TO_SEC(timer
->max_ns
);
348 strbuf_addf(&buf_payload
, ("%s %s/%s"
350 " total:%8.6f min:%8.6f max:%8.6f"),
351 event_name
, meta
->category
, meta
->name
,
352 timer
->interval_count
,
353 t_total
, t_min
, t_max
);
355 normal_io_write_fl(__FILE__
, __LINE__
, &buf_payload
);
356 strbuf_release(&buf_payload
);
359 static void fn_counter(const struct tr2_counter_metadata
*meta
,
360 const struct tr2_counter
*counter
,
363 const char *event_name
= is_final_data
? "counter" : "th_counter";
364 struct strbuf buf_payload
= STRBUF_INIT
;
366 strbuf_addf(&buf_payload
, "%s %s/%s value:%"PRIu64
,
367 event_name
, meta
->category
, meta
->name
,
370 normal_io_write_fl(__FILE__
, __LINE__
, &buf_payload
);
371 strbuf_release(&buf_payload
);
374 struct tr2_tgt tr2_tgt_normal
= {
375 .pdst
= &tr2dst_normal
,
380 .pfn_version_fl
= fn_version_fl
,
381 .pfn_start_fl
= fn_start_fl
,
382 .pfn_exit_fl
= fn_exit_fl
,
383 .pfn_signal
= fn_signal
,
384 .pfn_atexit
= fn_atexit
,
385 .pfn_error_va_fl
= fn_error_va_fl
,
386 .pfn_command_path_fl
= fn_command_path_fl
,
387 .pfn_command_ancestry_fl
= fn_command_ancestry_fl
,
388 .pfn_command_name_fl
= fn_command_name_fl
,
389 .pfn_command_mode_fl
= fn_command_mode_fl
,
390 .pfn_alias_fl
= fn_alias_fl
,
391 .pfn_child_start_fl
= fn_child_start_fl
,
392 .pfn_child_exit_fl
= fn_child_exit_fl
,
393 .pfn_child_ready_fl
= fn_child_ready_fl
,
394 .pfn_thread_start_fl
= NULL
,
395 .pfn_thread_exit_fl
= NULL
,
396 .pfn_exec_fl
= fn_exec_fl
,
397 .pfn_exec_result_fl
= fn_exec_result_fl
,
398 .pfn_param_fl
= fn_param_fl
,
399 .pfn_repo_fl
= fn_repo_fl
,
400 .pfn_region_enter_printf_va_fl
= NULL
,
401 .pfn_region_leave_printf_va_fl
= NULL
,
403 .pfn_data_json_fl
= NULL
,
404 .pfn_printf_va_fl
= fn_printf_va_fl
,
405 .pfn_timer
= fn_timer
,
406 .pfn_counter
= fn_counter
,