1 #include "cache.h"
2 #include "config.h"
3 #include "json-writer.h"
4 #include "quote.h"
5 #include "run-command.h"
6 #include "sigchain.h"
7 #include "thread-utils.h"
8 #include "version.h"
9 #include "trace2/tr2_cfg.h"
10 #include "trace2/tr2_cmd_name.h"
11 #include "trace2/tr2_dst.h"
12 #include "trace2/tr2_sid.h"
13 #include "trace2/tr2_sysenv.h"
14 #include "trace2/tr2_tgt.h"
15 #include "trace2/tr2_tls.h"
16 
17 static int trace2_enabled;
18 
19 static int tr2_next_child_id; /* modify under lock */
20 static int tr2_next_exec_id; /* modify under lock */
21 static int tr2_next_repo_id = 1; /* modify under lock. zero is reserved */
22 
23 /*
24  * A table of the builtin TRACE2 targets.  Each of these may be independently
25  * enabled or disabled.  Each TRACE2 API method will try to write an event to
26  * *each* of the enabled targets.
27  */
28 /* clang-format off */
29 static struct tr2_tgt *tr2_tgt_builtins[] =
30 {
31 	&tr2_tgt_normal,
32 	&tr2_tgt_perf,
33 	&tr2_tgt_event,
34 	NULL
35 };
36 /* clang-format on */
37 
38 /* clang-format off */
39 #define for_each_builtin(j, tgt_j)			\
40 	for (j = 0, tgt_j = tr2_tgt_builtins[j];	\
41 	     tgt_j;					\
42 	     j++, tgt_j = tr2_tgt_builtins[j])
43 /* clang-format on */
44 
45 /* clang-format off */
46 #define for_each_wanted_builtin(j, tgt_j)            \
47 	for_each_builtin(j, tgt_j)                   \
48 		if (tr2_dst_trace_want(tgt_j->pdst))
49 /* clang-format on */
50 
51 /*
52  * Force (rather than lazily) initialize any of the requested
53  * builtin TRACE2 targets at startup (and before we've seen an
54  * actual TRACE2 event call) so we can see if we need to setup
55  * the TR2 and TLS machinery.
56  *
57  * Return the number of builtin targets enabled.
58  */
59 static int tr2_tgt_want_builtins(void)
60 {
61 	struct tr2_tgt *tgt_j;
62 	int j;
63 	int sum = 0;
64 
65 	for_each_builtin (j, tgt_j)
66 		if (tgt_j->pfn_init())
67 			sum++;
68 
69 	return sum;
70 }
71 
72 /*
73  * Properly terminate each builtin target.  Give each target
74  * a chance to write a summary event and/or flush if necessary
75  * and then close the fd.
76  */
77 static void tr2_tgt_disable_builtins(void)
78 {
79 	struct tr2_tgt *tgt_j;
80 	int j;
81 
82 	for_each_builtin (j, tgt_j)
83 		tgt_j->pfn_term();
84 }
85 
86 static int tr2main_exit_code;
87 
88 /*
89  * Our atexit routine should run after everything has finished.
90  *
91  * Note that events generated here might not actually appear if
92  * we are writing to fd 1 or 2 and our atexit routine runs after
93  * the pager's atexit routine (since it closes them to shutdown
94  * the pipes).
95  */
96 static void tr2main_atexit_handler(void)
97 {
98 	struct tr2_tgt *tgt_j;
99 	int j;
100 	uint64_t us_now;
101 	uint64_t us_elapsed_absolute;
102 
103 	us_now = getnanotime() / 1000;
104 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
105 
106 	/*
107 	 * Clear any unbalanced regions so that our atexit message
108 	 * does not appear nested.  This improves the appearance of
109 	 * the trace output if someone calls die(), for example.
110 	 */
111 	tr2tls_pop_unwind_self();
112 
113 	for_each_wanted_builtin (j, tgt_j)
114 		if (tgt_j->pfn_atexit)
115 			tgt_j->pfn_atexit(us_elapsed_absolute,
116 					  tr2main_exit_code);
117 
118 	tr2_tgt_disable_builtins();
119 
120 	tr2tls_release();
121 	tr2_sid_release();
122 	tr2_cmd_name_release();
123 	tr2_cfg_free_patterns();
124 	tr2_cfg_free_env_vars();
125 	tr2_sysenv_release();
126 
127 	trace2_enabled = 0;
128 }
129 
130 static void tr2main_signal_handler(int signo)
131 {
132 	struct tr2_tgt *tgt_j;
133 	int j;
134 	uint64_t us_now;
135 	uint64_t us_elapsed_absolute;
136 
137 	us_now = getnanotime() / 1000;
138 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
139 
140 	for_each_wanted_builtin (j, tgt_j)
141 		if (tgt_j->pfn_signal)
142 			tgt_j->pfn_signal(us_elapsed_absolute, signo);
143 
144 	sigchain_pop(signo);
145 	raise(signo);
146 }
147 
148 void trace2_initialize_clock(void)
149 {
150 	tr2tls_start_process_clock();
151 }
152 
153 void trace2_initialize_fl(const char *file, int line)
154 {
155 	struct tr2_tgt *tgt_j;
156 	int j;
157 
158 	if (trace2_enabled)
159 		return;
160 
161 	tr2_sysenv_load();
162 
163 	if (!tr2_tgt_want_builtins())
164 		return;
165 	trace2_enabled = 1;
166 
167 	tr2_sid_get();
168 
169 	atexit(tr2main_atexit_handler);
170 	sigchain_push(SIGPIPE, tr2main_signal_handler);
171 	tr2tls_init();
172 
173 	/*
174 	 * Emit 'version' message on each active builtin target.
175 	 */
176 	for_each_wanted_builtin (j, tgt_j)
177 		if (tgt_j->pfn_version_fl)
178 			tgt_j->pfn_version_fl(file, line);
179 }
180 
181 int trace2_is_enabled(void)
182 {
183 	return trace2_enabled;
184 }
185 
186 void trace2_cmd_start_fl(const char *file, int line, const char **argv)
187 {
188 	struct tr2_tgt *tgt_j;
189 	int j;
190 	uint64_t us_now;
191 	uint64_t us_elapsed_absolute;
192 
193 	if (!trace2_enabled)
194 		return;
195 
196 	us_now = getnanotime() / 1000;
197 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
198 
199 	for_each_wanted_builtin (j, tgt_j)
200 		if (tgt_j->pfn_start_fl)
201 			tgt_j->pfn_start_fl(file, line, us_elapsed_absolute,
202 					    argv);
203 }
204 
205 int trace2_cmd_exit_fl(const char *file, int line, int code)
206 {
207 	struct tr2_tgt *tgt_j;
208 	int j;
209 	uint64_t us_now;
210 	uint64_t us_elapsed_absolute;
211 
212 	code &= 0xff;
213 
214 	if (!trace2_enabled)
215 		return code;
216 
217 	trace2_collect_process_info(TRACE2_PROCESS_INFO_EXIT);
218 
219 	tr2main_exit_code = code;
220 
221 	us_now = getnanotime() / 1000;
222 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
223 
224 	for_each_wanted_builtin (j, tgt_j)
225 		if (tgt_j->pfn_exit_fl)
226 			tgt_j->pfn_exit_fl(file, line, us_elapsed_absolute,
227 					   code);
228 
229 	return code;
230 }
231 
232 void trace2_cmd_error_va_fl(const char *file, int line, const char *fmt,
233 			    va_list ap)
234 {
235 	struct tr2_tgt *tgt_j;
236 	int j;
237 
238 	if (!trace2_enabled)
239 		return;
240 
241 	/*
242 	 * We expect each target function to treat 'ap' as constant
243 	 * and use va_copy (because an 'ap' can only be walked once).
244 	 */
245 	for_each_wanted_builtin (j, tgt_j)
246 		if (tgt_j->pfn_error_va_fl)
247 			tgt_j->pfn_error_va_fl(file, line, fmt, ap);
248 }
249 
250 void trace2_cmd_path_fl(const char *file, int line, const char *pathname)
251 {
252 	struct tr2_tgt *tgt_j;
253 	int j;
254 
255 	if (!trace2_enabled)
256 		return;
257 
258 	for_each_wanted_builtin (j, tgt_j)
259 		if (tgt_j->pfn_command_path_fl)
260 			tgt_j->pfn_command_path_fl(file, line, pathname);
261 }
262 
263 void trace2_cmd_ancestry_fl(const char *file, int line, const char **parent_names)
264 {
265 	struct tr2_tgt *tgt_j;
266 	int j;
267 
268 	if (!trace2_enabled)
269 		return;
270 
271 	for_each_wanted_builtin (j, tgt_j)
272 		if (tgt_j->pfn_command_ancestry_fl)
273 			tgt_j->pfn_command_ancestry_fl(file, line, parent_names);
274 }
275 
276 void trace2_cmd_name_fl(const char *file, int line, const char *name)
277 {
278 	struct tr2_tgt *tgt_j;
279 	const char *hierarchy;
280 	int j;
281 
282 	if (!trace2_enabled)
283 		return;
284 
285 	tr2_cmd_name_append_hierarchy(name);
286 	hierarchy = tr2_cmd_name_get_hierarchy();
287 
288 	for_each_wanted_builtin (j, tgt_j)
289 		if (tgt_j->pfn_command_name_fl)
290 			tgt_j->pfn_command_name_fl(file, line, name, hierarchy);
291 }
292 
293 void trace2_cmd_mode_fl(const char *file, int line, const char *mode)
294 {
295 	struct tr2_tgt *tgt_j;
296 	int j;
297 
298 	if (!trace2_enabled)
299 		return;
300 
301 	for_each_wanted_builtin (j, tgt_j)
302 		if (tgt_j->pfn_command_mode_fl)
303 			tgt_j->pfn_command_mode_fl(file, line, mode);
304 }
305 
306 void trace2_cmd_alias_fl(const char *file, int line, const char *alias,
307 			 const char **argv)
308 {
309 	struct tr2_tgt *tgt_j;
310 	int j;
311 
312 	if (!trace2_enabled)
313 		return;
314 
315 	for_each_wanted_builtin (j, tgt_j)
316 		if (tgt_j->pfn_alias_fl)
317 			tgt_j->pfn_alias_fl(file, line, alias, argv);
318 }
319 
320 void trace2_cmd_list_config_fl(const char *file, int line)
321 {
322 	if (!trace2_enabled)
323 		return;
324 
325 	tr2_cfg_list_config_fl(file, line);
326 }
327 
328 void trace2_cmd_list_env_vars_fl(const char *file, int line)
329 {
330 	if (!trace2_enabled)
331 		return;
332 
333 	tr2_list_env_vars_fl(file, line);
334 }
335 
336 void trace2_cmd_set_config_fl(const char *file, int line, const char *key,
337 			      const char *value)
338 {
339 	if (!trace2_enabled)
340 		return;
341 
342 	tr2_cfg_set_fl(file, line, key, value);
343 }
344 
345 void trace2_child_start_fl(const char *file, int line,
346 			   struct child_process *cmd)
347 {
348 	struct tr2_tgt *tgt_j;
349 	int j;
350 	uint64_t us_now;
351 	uint64_t us_elapsed_absolute;
352 
353 	if (!trace2_enabled)
354 		return;
355 
356 	us_now = getnanotime() / 1000;
357 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
358 
359 	cmd->trace2_child_id = tr2tls_locked_increment(&tr2_next_child_id);
360 	cmd->trace2_child_us_start = us_now;
361 
362 	for_each_wanted_builtin (j, tgt_j)
363 		if (tgt_j->pfn_child_start_fl)
364 			tgt_j->pfn_child_start_fl(file, line,
365 						  us_elapsed_absolute, cmd);
366 }
367 
368 void trace2_child_exit_fl(const char *file, int line, struct child_process *cmd,
369 			  int child_exit_code)
370 {
371 	struct tr2_tgt *tgt_j;
372 	int j;
373 	uint64_t us_now;
374 	uint64_t us_elapsed_absolute;
375 	uint64_t us_elapsed_child;
376 
377 	if (!trace2_enabled)
378 		return;
379 
380 	us_now = getnanotime() / 1000;
381 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
382 
383 	if (cmd->trace2_child_us_start)
384 		us_elapsed_child = us_now - cmd->trace2_child_us_start;
385 	else
386 		us_elapsed_child = 0;
387 
388 	for_each_wanted_builtin (j, tgt_j)
389 		if (tgt_j->pfn_child_exit_fl)
390 			tgt_j->pfn_child_exit_fl(file, line,
391 						 us_elapsed_absolute,
392 						 cmd->trace2_child_id, cmd->pid,
393 						 child_exit_code,
394 						 us_elapsed_child);
395 }
396 
397 void trace2_child_ready_fl(const char *file, int line,
398 			   struct child_process *cmd,
399 			   const char *ready)
400 {
401 	struct tr2_tgt *tgt_j;
402 	int j;
403 	uint64_t us_now;
404 	uint64_t us_elapsed_absolute;
405 	uint64_t us_elapsed_child;
406 
407 	if (!trace2_enabled)
408 		return;
409 
410 	us_now = getnanotime() / 1000;
411 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
412 
413 	if (cmd->trace2_child_us_start)
414 		us_elapsed_child = us_now - cmd->trace2_child_us_start;
415 	else
416 		us_elapsed_child = 0;
417 
418 	for_each_wanted_builtin (j, tgt_j)
419 		if (tgt_j->pfn_child_ready_fl)
420 			tgt_j->pfn_child_ready_fl(file, line,
421 						  us_elapsed_absolute,
422 						  cmd->trace2_child_id,
423 						  cmd->pid,
424 						  ready,
425 						  us_elapsed_child);
426 }
427 
428 int trace2_exec_fl(const char *file, int line, const char *exe,
429 		   const char **argv)
430 {
431 	struct tr2_tgt *tgt_j;
432 	int j;
433 	int exec_id;
434 	uint64_t us_now;
435 	uint64_t us_elapsed_absolute;
436 
437 	if (!trace2_enabled)
438 		return -1;
439 
440 	us_now = getnanotime() / 1000;
441 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
442 
443 	exec_id = tr2tls_locked_increment(&tr2_next_exec_id);
444 
445 	for_each_wanted_builtin (j, tgt_j)
446 		if (tgt_j->pfn_exec_fl)
447 			tgt_j->pfn_exec_fl(file, line, us_elapsed_absolute,
448 					   exec_id, exe, argv);
449 
450 	return exec_id;
451 }
452 
453 void trace2_exec_result_fl(const char *file, int line, int exec_id, int code)
454 {
455 	struct tr2_tgt *tgt_j;
456 	int j;
457 	uint64_t us_now;
458 	uint64_t us_elapsed_absolute;
459 
460 	if (!trace2_enabled)
461 		return;
462 
463 	us_now = getnanotime() / 1000;
464 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
465 
466 	for_each_wanted_builtin (j, tgt_j)
467 		if (tgt_j->pfn_exec_result_fl)
468 			tgt_j->pfn_exec_result_fl(
469 				file, line, us_elapsed_absolute, exec_id, code);
470 }
471 
472 void trace2_thread_start_fl(const char *file, int line, const char *thread_name)
473 {
474 	struct tr2_tgt *tgt_j;
475 	int j;
476 	uint64_t us_now;
477 	uint64_t us_elapsed_absolute;
478 
479 	if (!trace2_enabled)
480 		return;
481 
482 	if (tr2tls_is_main_thread()) {
483 		/*
484 		 * We should only be called from the new thread's thread-proc,
485 		 * so this is technically a bug.  But in those cases where the
486 		 * main thread also runs the thread-proc function (or when we
487 		 * are built with threading disabled), we need to allow it.
488 		 *
489 		 * Convert this call to a region-enter so the nesting looks
490 		 * correct.
491 		 */
492 		trace2_region_enter_printf_fl(file, line, NULL, NULL, NULL,
493 					      "thread-proc on main: %s",
494 					      thread_name);
495 		return;
496 	}
497 
498 	us_now = getnanotime() / 1000;
499 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
500 
501 	tr2tls_create_self(thread_name, us_now);
502 
503 	for_each_wanted_builtin (j, tgt_j)
504 		if (tgt_j->pfn_thread_start_fl)
505 			tgt_j->pfn_thread_start_fl(file, line,
506 						   us_elapsed_absolute);
507 }
508 
509 void trace2_thread_exit_fl(const char *file, int line)
510 {
511 	struct tr2_tgt *tgt_j;
512 	int j;
513 	uint64_t us_now;
514 	uint64_t us_elapsed_absolute;
515 	uint64_t us_elapsed_thread;
516 
517 	if (!trace2_enabled)
518 		return;
519 
520 	if (tr2tls_is_main_thread()) {
521 		/*
522 		 * We should only be called from the exiting thread's
523 		 * thread-proc, so this is technically a bug.  But in
524 		 * those cases where the main thread also runs the
525 		 * thread-proc function (or when we are built with
526 		 * threading disabled), we need to allow it.
527 		 *
528 		 * Convert this call to a region-leave so the nesting
529 		 * looks correct.
530 		 */
531 		trace2_region_leave_printf_fl(file, line, NULL, NULL, NULL,
532 					      "thread-proc on main");
533 		return;
534 	}
535 
536 	us_now = getnanotime() / 1000;
537 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
538 
539 	/*
540 	 * Clear any unbalanced regions and then get the relative time
541 	 * for the outer-most region (which we pushed when the thread
542 	 * started).  This gives us the run time of the thread.
543 	 */
544 	tr2tls_pop_unwind_self();
545 	us_elapsed_thread = tr2tls_region_elasped_self(us_now);
546 
547 	for_each_wanted_builtin (j, tgt_j)
548 		if (tgt_j->pfn_thread_exit_fl)
549 			tgt_j->pfn_thread_exit_fl(file, line,
550 						  us_elapsed_absolute,
551 						  us_elapsed_thread);
552 
553 	tr2tls_unset_self();
554 }
555 
556 void trace2_def_param_fl(const char *file, int line, const char *param,
557 			 const char *value)
558 {
559 	struct tr2_tgt *tgt_j;
560 	int j;
561 
562 	if (!trace2_enabled)
563 		return;
564 
565 	for_each_wanted_builtin (j, tgt_j)
566 		if (tgt_j->pfn_param_fl)
567 			tgt_j->pfn_param_fl(file, line, param, value);
568 }
569 
570 void trace2_def_repo_fl(const char *file, int line, struct repository *repo)
571 {
572 	struct tr2_tgt *tgt_j;
573 	int j;
574 
575 	if (!trace2_enabled)
576 		return;
577 
578 	if (repo->trace2_repo_id)
579 		return;
580 
581 	repo->trace2_repo_id = tr2tls_locked_increment(&tr2_next_repo_id);
582 
583 	for_each_wanted_builtin (j, tgt_j)
584 		if (tgt_j->pfn_repo_fl)
585 			tgt_j->pfn_repo_fl(file, line, repo);
586 }
587 
588 void trace2_region_enter_printf_va_fl(const char *file, int line,
589 				      const char *category, const char *label,
590 				      const struct repository *repo,
591 				      const char *fmt, va_list ap)
592 {
593 	struct tr2_tgt *tgt_j;
594 	int j;
595 	uint64_t us_now;
596 	uint64_t us_elapsed_absolute;
597 
598 	if (!trace2_enabled)
599 		return;
600 
601 	us_now = getnanotime() / 1000;
602 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
603 
604 	/*
605 	 * Print the region-enter message at the current nesting
606 	 * (indentation) level and then push a new level.
607 	 *
608 	 * We expect each target function to treat 'ap' as constant
609 	 * and use va_copy.
610 	 */
611 	for_each_wanted_builtin (j, tgt_j)
612 		if (tgt_j->pfn_region_enter_printf_va_fl)
613 			tgt_j->pfn_region_enter_printf_va_fl(
614 				file, line, us_elapsed_absolute, category,
615 				label, repo, fmt, ap);
616 
617 	tr2tls_push_self(us_now);
618 }
619 
620 void trace2_region_enter_fl(const char *file, int line, const char *category,
621 			    const char *label, const struct repository *repo, ...)
622 {
623 	va_list ap;
624 	va_start(ap, repo);
625 	trace2_region_enter_printf_va_fl(file, line, category, label, repo,
626 					 NULL, ap);
627 	va_end(ap);
628 
629 }
630 
631 void trace2_region_enter_printf_fl(const char *file, int line,
632 				   const char *category, const char *label,
633 				   const struct repository *repo,
634 				   const char *fmt, ...)
635 {
636 	va_list ap;
637 
638 	va_start(ap, fmt);
639 	trace2_region_enter_printf_va_fl(file, line, category, label, repo, fmt,
640 					 ap);
641 	va_end(ap);
642 }
643 
644 #ifndef HAVE_VARIADIC_MACROS
645 void trace2_region_enter_printf(const char *category, const char *label,
646 				const struct repository *repo, const char *fmt,
647 				...)
648 {
649 	va_list ap;
650 
651 	va_start(ap, fmt);
652 	trace2_region_enter_printf_va_fl(NULL, 0, category, label, repo, fmt,
653 					 ap);
654 	va_end(ap);
655 }
656 #endif
657 
658 void trace2_region_leave_printf_va_fl(const char *file, int line,
659 				      const char *category, const char *label,
660 				      const struct repository *repo,
661 				      const char *fmt, va_list ap)
662 {
663 	struct tr2_tgt *tgt_j;
664 	int j;
665 	uint64_t us_now;
666 	uint64_t us_elapsed_absolute;
667 	uint64_t us_elapsed_region;
668 
669 	if (!trace2_enabled)
670 		return;
671 
672 	us_now = getnanotime() / 1000;
673 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
674 
675 	/*
676 	 * Get the elapsed time in the current region before we
677 	 * pop it off the stack.  Pop the stack.  And then print
678 	 * the perf message at the new (shallower) level so that
679 	 * it lines up with the corresponding push/enter.
680 	 */
681 	us_elapsed_region = tr2tls_region_elasped_self(us_now);
682 
683 	tr2tls_pop_self();
684 
685 	/*
686 	 * We expect each target function to treat 'ap' as constant
687 	 * and use va_copy.
688 	 */
689 	for_each_wanted_builtin (j, tgt_j)
690 		if (tgt_j->pfn_region_leave_printf_va_fl)
691 			tgt_j->pfn_region_leave_printf_va_fl(
692 				file, line, us_elapsed_absolute,
693 				us_elapsed_region, category, label, repo, fmt,
694 				ap);
695 }
696 
697 void trace2_region_leave_fl(const char *file, int line, const char *category,
698 			    const char *label, const struct repository *repo, ...)
699 {
700 	va_list ap;
701 	va_start(ap, repo);
702 	trace2_region_leave_printf_va_fl(file, line, category, label, repo,
703 					 NULL, ap);
704 	va_end(ap);
705 }
706 
707 void trace2_region_leave_printf_fl(const char *file, int line,
708 				   const char *category, const char *label,
709 				   const struct repository *repo,
710 				   const char *fmt, ...)
711 {
712 	va_list ap;
713 
714 	va_start(ap, fmt);
715 	trace2_region_leave_printf_va_fl(file, line, category, label, repo, fmt,
716 					 ap);
717 	va_end(ap);
718 }
719 
720 #ifndef HAVE_VARIADIC_MACROS
721 void trace2_region_leave_printf(const char *category, const char *label,
722 				const struct repository *repo, const char *fmt,
723 				...)
724 {
725 	va_list ap;
726 
727 	va_start(ap, fmt);
728 	trace2_region_leave_printf_va_fl(NULL, 0, category, label, repo, fmt,
729 					 ap);
730 	va_end(ap);
731 }
732 #endif
733 
734 void trace2_data_string_fl(const char *file, int line, const char *category,
735 			   const struct repository *repo, const char *key,
736 			   const char *value)
737 {
738 	struct tr2_tgt *tgt_j;
739 	int j;
740 	uint64_t us_now;
741 	uint64_t us_elapsed_absolute;
742 	uint64_t us_elapsed_region;
743 
744 	if (!trace2_enabled)
745 		return;
746 
747 	us_now = getnanotime() / 1000;
748 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
749 	us_elapsed_region = tr2tls_region_elasped_self(us_now);
750 
751 	for_each_wanted_builtin (j, tgt_j)
752 		if (tgt_j->pfn_data_fl)
753 			tgt_j->pfn_data_fl(file, line, us_elapsed_absolute,
754 					   us_elapsed_region, category, repo,
755 					   key, value);
756 }
757 
758 void trace2_data_intmax_fl(const char *file, int line, const char *category,
759 			   const struct repository *repo, const char *key,
760 			   intmax_t value)
761 {
762 	struct strbuf buf_string = STRBUF_INIT;
763 
764 	if (!trace2_enabled)
765 		return;
766 
767 	strbuf_addf(&buf_string, "%" PRIdMAX, value);
768 	trace2_data_string_fl(file, line, category, repo, key, buf_string.buf);
769 	strbuf_release(&buf_string);
770 }
771 
772 void trace2_data_json_fl(const char *file, int line, const char *category,
773 			 const struct repository *repo, const char *key,
774 			 const struct json_writer *value)
775 {
776 	struct tr2_tgt *tgt_j;
777 	int j;
778 	uint64_t us_now;
779 	uint64_t us_elapsed_absolute;
780 	uint64_t us_elapsed_region;
781 
782 	if (!trace2_enabled)
783 		return;
784 
785 	us_now = getnanotime() / 1000;
786 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
787 	us_elapsed_region = tr2tls_region_elasped_self(us_now);
788 
789 	for_each_wanted_builtin (j, tgt_j)
790 		if (tgt_j->pfn_data_json_fl)
791 			tgt_j->pfn_data_json_fl(file, line, us_elapsed_absolute,
792 						us_elapsed_region, category,
793 						repo, key, value);
794 }
795 
796 void trace2_printf_va_fl(const char *file, int line, const char *fmt,
797 			 va_list ap)
798 {
799 	struct tr2_tgt *tgt_j;
800 	int j;
801 	uint64_t us_now;
802 	uint64_t us_elapsed_absolute;
803 
804 	if (!trace2_enabled)
805 		return;
806 
807 	us_now = getnanotime() / 1000;
808 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
809 
810 	/*
811 	 * We expect each target function to treat 'ap' as constant
812 	 * and use va_copy.
813 	 */
814 	for_each_wanted_builtin (j, tgt_j)
815 		if (tgt_j->pfn_printf_va_fl)
816 			tgt_j->pfn_printf_va_fl(file, line, us_elapsed_absolute,
817 						fmt, ap);
818 }
819 
820 void trace2_printf_fl(const char *file, int line, const char *fmt, ...)
821 {
822 	va_list ap;
823 
824 	va_start(ap, fmt);
825 	trace2_printf_va_fl(file, line, fmt, ap);
826 	va_end(ap);
827 }
828 
829 #ifndef HAVE_VARIADIC_MACROS
830 void trace2_printf(const char *fmt, ...)
831 {
832 	va_list ap;
833 
834 	va_start(ap, fmt);
835 	trace2_printf_va_fl(NULL, 0, fmt, ap);
836 	va_end(ap);
837 }
838 #endif
839 
840 const char *trace2_session_id(void)
841 {
842 	return tr2_sid_get();
843 }
844