Skip to content

Commit ee4512e

Browse files
jeffhostetlergitster
authored andcommitted
trace2: create new combined trace facility
Create a new unified tracing facility for git. The eventual intent is to replace the current trace_printf* and trace_performance* routines with a unified set of git_trace2* routines. In addition to the usual printf-style API, trace2 provides higer-level event verbs with fixed-fields allowing structured data to be written. This makes post-processing and analysis easier for external tools. Trace2 defines 3 output targets. These are set using the environment variables "GIT_TR2", "GIT_TR2_PERF", and "GIT_TR2_EVENT". These may be set to "1" or to an absolute pathname (just like the current GIT_TRACE). * GIT_TR2 is intended to be a replacement for GIT_TRACE and logs command summary data. * GIT_TR2_PERF is intended as a replacement for GIT_TRACE_PERFORMANCE. It extends the output with columns for the command process, thread, repo, absolute and relative elapsed times. It reports events for child process start/stop, thread start/stop, and per-thread function nesting. * GIT_TR2_EVENT is a new structured format. It writes event data as a series of JSON records. Calls to trace2 functions log to any of the 3 output targets enabled without the need to call different trace_printf* or trace_performance* routines. Signed-off-by: Jeff Hostetler <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e544221 commit ee4512e

39 files changed

+3806
-18
lines changed

Makefile

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,16 @@ LIB_OBJS += tempfile.o
10171017
LIB_OBJS += thread-utils.o
10181018
LIB_OBJS += tmp-objdir.o
10191019
LIB_OBJS += trace.o
1020+
LIB_OBJS += trace2.o
1021+
LIB_OBJS += trace2/tr2_cfg.o
1022+
LIB_OBJS += trace2/tr2_cmd_name.o
1023+
LIB_OBJS += trace2/tr2_dst.o
1024+
LIB_OBJS += trace2/tr2_sid.o
1025+
LIB_OBJS += trace2/tr2_tbuf.o
1026+
LIB_OBJS += trace2/tr2_tgt_event.o
1027+
LIB_OBJS += trace2/tr2_tgt_normal.o
1028+
LIB_OBJS += trace2/tr2_tgt_perf.o
1029+
LIB_OBJS += trace2/tr2_tls.o
10201030
LIB_OBJS += trailer.o
10211031
LIB_OBJS += transport.o
10221032
LIB_OBJS += transport-helper.o
@@ -1596,7 +1606,9 @@ ifdef NO_INET_PTON
15961606
LIB_OBJS += compat/inet_pton.o
15971607
BASIC_CFLAGS += -DNO_INET_PTON
15981608
endif
1599-
ifndef NO_UNIX_SOCKETS
1609+
ifdef NO_UNIX_SOCKETS
1610+
BASIC_CFLAGS += -DNO_UNIX_SOCKETS
1611+
else
16001612
LIB_OBJS += unix-socket.o
16011613
PROGRAM_OBJS += credential-cache.o
16021614
PROGRAM_OBJS += credential-cache--daemon.o

builtin/submodule--helper.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,11 +1816,10 @@ static int update_submodules(struct submodule_update_clone *suc)
18161816
{
18171817
int i;
18181818

1819-
run_processes_parallel(suc->max_jobs,
1820-
update_clone_get_next_task,
1821-
update_clone_start_failure,
1822-
update_clone_task_finished,
1823-
suc);
1819+
run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task,
1820+
update_clone_start_failure,
1821+
update_clone_task_finished, suc, "submodule",
1822+
"parallel/update");
18241823

18251824
/*
18261825
* We saved the output and put it out all at once now.

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "gettext.h"
1010
#include "convert.h"
1111
#include "trace.h"
12+
#include "trace2.h"
1213
#include "string-list.h"
1314
#include "pack-revindex.h"
1415
#include "hash.h"

common-main.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@ static void restore_sigpipe_to_default(void)
2525

2626
int main(int argc, const char **argv)
2727
{
28+
int result;
29+
2830
/*
2931
* Always open file descriptors 0/1/2 to avoid clobbering files
3032
* in die(). It also avoids messing up when the pipes are dup'ed
3133
* onto stdin/stdout/stderr in the child processes we spawn.
3234
*/
3335
sanitize_stdfds();
36+
restore_sigpipe_to_default();
37+
38+
trace2_initialize();
39+
trace2_cmd_start(argv);
3440

3541
git_resolve_executable_dir(argv[0]);
3642

@@ -40,7 +46,9 @@ int main(int argc, const char **argv)
4046

4147
attr_start();
4248

43-
restore_sigpipe_to_default();
49+
result = cmd_main(argc, argv);
50+
51+
trace2_cmd_exit(result);
4452

45-
return cmd_main(argc, argv);
53+
return result;
4654
}

compat/mingw.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1551,19 +1551,23 @@ static int try_shell_exec(const char *cmd, char *const *argv)
15511551
return 0;
15521552
prog = path_lookup(interpr, 1);
15531553
if (prog) {
1554+
int exec_id;
15541555
int argc = 0;
15551556
const char **argv2;
15561557
while (argv[argc]) argc++;
15571558
ALLOC_ARRAY(argv2, argc + 1);
15581559
argv2[0] = (char *)cmd; /* full path to the script file */
15591560
memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
1561+
exec_id = trace2_exec(prog, argv2);
15601562
pid = mingw_spawnv(prog, argv2, 1);
15611563
if (pid >= 0) {
15621564
int status;
15631565
if (waitpid(pid, &status, 0) < 0)
15641566
status = 255;
1567+
trace2_exec_result(exec_id, status);
15651568
exit(status);
15661569
}
1570+
trace2_exec_result(exec_id, -1);
15671571
pid = 1; /* indicate that we tried but failed */
15681572
free(prog);
15691573
free(argv2);
@@ -1576,12 +1580,17 @@ int mingw_execv(const char *cmd, char *const *argv)
15761580
/* check if git_command is a shell script */
15771581
if (!try_shell_exec(cmd, argv)) {
15781582
int pid, status;
1583+
int exec_id;
15791584

1585+
exec_id = trace2_exec(cmd, (const char **)argv);
15801586
pid = mingw_spawnv(cmd, (const char **)argv, 0);
1581-
if (pid < 0)
1587+
if (pid < 0) {
1588+
trace2_exec_result(exec_id, -1);
15821589
return -1;
1590+
}
15831591
if (waitpid(pid, &status, 0) < 0)
15841592
status = 255;
1593+
trace2_exec_result(exec_id, status);
15851594
exit(status);
15861595
}
15871596
return -1;

compat/mingw.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ static inline int fcntl(int fd, int cmd, ...)
147147
errno = EINVAL;
148148
return -1;
149149
}
150-
/* bash cannot reliably detect negative return codes as failure */
151-
#define exit(code) exit((code) & 0xff)
150+
152151
#define sigemptyset(x) (void)0
153152
static inline int sigaddset(sigset_t *set, int signum)
154153
{ return 0; }

config.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,8 @@ int git_config_set_gently(const char *key, const char *value)
26552655
void git_config_set(const char *key, const char *value)
26562656
{
26572657
git_config_set_multivar(key, value, NULL, 0);
2658+
2659+
trace2_cmd_set_config(key, value);
26582660
}
26592661

26602662
/*

exec-cmd.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ static int git_get_exec_path(struct strbuf *buf, const char *argv0)
209209
return -1;
210210
}
211211

212+
trace2_cmd_path(buf->buf);
213+
212214
return 0;
213215
}
214216

git-compat-util.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,13 @@ static inline int is_missing_file_error(int errno_)
12591259

12601260
extern int cmd_main(int, const char **);
12611261

1262+
/*
1263+
* Intercept all calls to exit() and route them to trace2 to
1264+
* optionally emit a message before calling the real exit().
1265+
*/
1266+
int trace2_cmd_exit_fl(const char *file, int line, int code);
1267+
#define exit(code) exit(trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))
1268+
12621269
/*
12631270
* You can mark a stack variable with UNLEAK(var) to avoid it being
12641271
* reported as a leak by tools like LSAN or valgrind. The argument

git.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
147147
git_set_exec_path(cmd + 1);
148148
else {
149149
puts(git_exec_path());
150+
trace2_cmd_name("_query_");
150151
exit(0);
151152
}
152153
} else if (!strcmp(cmd, "--html-path")) {
153154
puts(system_path(GIT_HTML_PATH));
155+
trace2_cmd_name("_query_");
154156
exit(0);
155157
} else if (!strcmp(cmd, "--man-path")) {
156158
puts(system_path(GIT_MAN_PATH));
159+
trace2_cmd_name("_query_");
157160
exit(0);
158161
} else if (!strcmp(cmd, "--info-path")) {
159162
puts(system_path(GIT_INFO_PATH));
163+
trace2_cmd_name("_query_");
160164
exit(0);
161165
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
162166
use_pager = 1;
@@ -285,6 +289,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
285289
(*argv)++;
286290
(*argc)--;
287291
} else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
292+
trace2_cmd_name("_query_");
288293
if (!strcmp(cmd, "parseopt")) {
289294
struct string_list list = STRING_LIST_INIT_DUP;
290295
int i;
@@ -332,9 +337,14 @@ static int handle_alias(int *argcp, const char ***argv)
332337
commit_pager_choice();
333338

334339
child.use_shell = 1;
340+
child.trace2_child_class = "shell_alias";
335341
argv_array_push(&child.args, alias_string + 1);
336342
argv_array_pushv(&child.args, (*argv) + 1);
337343

344+
trace2_cmd_alias(alias_command, child.args.argv);
345+
trace2_cmd_list_config();
346+
trace2_cmd_name("_run_shell_alias_");
347+
338348
ret = run_command(&child);
339349
if (ret >= 0) /* normal exit */
340350
exit(ret);
@@ -369,6 +379,9 @@ static int handle_alias(int *argcp, const char ***argv)
369379
/* insert after command name */
370380
memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
371381

382+
trace2_cmd_alias(alias_command, new_argv);
383+
trace2_cmd_list_config();
384+
372385
*argv = new_argv;
373386
*argcp += count - 1;
374387

@@ -417,6 +430,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
417430
setup_work_tree();
418431

419432
trace_argv_printf(argv, "trace: built-in: git");
433+
trace2_cmd_name(p->cmd);
434+
trace2_cmd_list_config();
420435

421436
validate_cache_entries(the_repository->index);
422437
status = p->fn(argc, argv, prefix);
@@ -666,7 +681,14 @@ static void execv_dashed_external(const char **argv)
666681
cmd.clean_on_exit = 1;
667682
cmd.wait_after_clean = 1;
668683
cmd.silent_exec_failure = 1;
684+
cmd.trace2_child_class = "dashed";
669685

686+
trace2_cmd_name("_run_dashed_");
687+
688+
/*
689+
* The code in run_command() logs trace2 child_start/child_exit
690+
* events, so we do not need to report exec/exec_result events here.
691+
*/
670692
trace_argv_printf(cmd.args.argv, "trace: exec:");
671693

672694
/*
@@ -676,6 +698,12 @@ static void execv_dashed_external(const char **argv)
676698
* the program.
677699
*/
678700
status = run_command(&cmd);
701+
702+
/*
703+
* If the child process ran and we are now going to exit, emit a
704+
* generic string as our trace2 command verb to indicate that we
705+
* launched a dashed command.
706+
*/
679707
if (status >= 0)
680708
exit(status);
681709
else if (errno != ENOENT)
@@ -701,6 +729,43 @@ static int run_argv(int *argcp, const char ***argv)
701729
if (!done_alias)
702730
handle_builtin(*argcp, *argv);
703731

732+
#if 0 // TODO In GFW, need to amend a7924b655e940b06cb547c235d6bed9767929673 to include trace2_ and _tr2 lines.
733+
else if (get_builtin(**argv)) {
734+
struct argv_array args = ARGV_ARRAY_INIT;
735+
int i;
736+
737+
/*
738+
* The current process is committed to launching a
739+
* child process to run the command named in (**argv)
740+
* and exiting. Log a generic string as the trace2
741+
* command verb to indicate this. Note that the child
742+
* process will log the actual verb when it runs.
743+
*/
744+
trace2_cmd_name("_run_git_alias_");
745+
746+
if (get_super_prefix())
747+
die("%s doesn't support --super-prefix", **argv);
748+
749+
commit_pager_choice();
750+
751+
argv_array_push(&args, "git");
752+
for (i = 0; i < *argcp; i++)
753+
argv_array_push(&args, (*argv)[i]);
754+
755+
trace_argv_printf(args.argv, "trace: exec:");
756+
757+
/*
758+
* if we fail because the command is not found, it is
759+
* OK to return. Otherwise, we just pass along the status code.
760+
*/
761+
i = run_command_v_opt_tr2(args.argv, RUN_SILENT_EXEC_FAILURE |
762+
RUN_CLEAN_ON_EXIT, "git_alias");
763+
if (i >= 0 || errno != ENOENT)
764+
exit(i);
765+
die("could not execute builtin %s", **argv);
766+
}
767+
#endif // a7924b655e940b06cb547c235d6bed9767929673
768+
704769
/* .. then try the external ones */
705770
execv_dashed_external(*argv);
706771

remote-curl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,13 @@ int cmd_main(int argc, const char **argv)
13851385
string_list_init(&options.deepen_not, 1);
13861386
string_list_init(&options.push_options, 1);
13871387

1388+
/*
1389+
* Just report "remote-curl" here (folding all the various aliases
1390+
* ("git-remote-http", "git-remote-https", and etc.) here since they
1391+
* are all just copies of the same actual executable.
1392+
*/
1393+
trace2_cmd_name("remote-curl");
1394+
13881395
remote = remote_get(argv[1]);
13891396

13901397
if (argc > 2) {

repository.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ static int repo_init_gitdir(struct repository *repo, const char *gitdir)
126126
void repo_set_worktree(struct repository *repo, const char *path)
127127
{
128128
repo->worktree = real_pathdup(path, 1);
129+
130+
trace2_def_repo(repo);
129131
}
130132

131133
static int read_and_verify_repository_format(struct repository_format *format,

repository.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ struct repository {
9292
/* Repository's current hash algorithm, as serialized on disk. */
9393
const struct git_hash_algo *hash_algo;
9494

95+
/* A unique-id for tracing purposes. */
96+
int trace2_repo_id;
97+
9598
/* Configurations */
9699

97100
/* Indicate if a repository has a different 'commondir' from 'gitdir' */

0 commit comments

Comments
 (0)