Skip to content

Commit 2a4785a

Browse files
jeffhostetlerdscho
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 <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 0ff703c commit 2a4785a

39 files changed

Lines changed: 3729 additions & 20 deletions

Makefile

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,16 @@ LIB_OBJS += tempfile.o
10211021
LIB_OBJS += thread-utils.o
10221022
LIB_OBJS += tmp-objdir.o
10231023
LIB_OBJS += trace.o
1024+
LIB_OBJS += trace2.o
1025+
LIB_OBJS += trace2/tr2_cfg.o
1026+
LIB_OBJS += trace2/tr2_cmd_name.o
1027+
LIB_OBJS += trace2/tr2_dst.o
1028+
LIB_OBJS += trace2/tr2_sid.o
1029+
LIB_OBJS += trace2/tr2_tbuf.o
1030+
LIB_OBJS += trace2/tr2_tgt_event.o
1031+
LIB_OBJS += trace2/tr2_tgt_normal.o
1032+
LIB_OBJS += trace2/tr2_tgt_perf.o
1033+
LIB_OBJS += trace2/tr2_tls.o
10241034
LIB_OBJS += trailer.o
10251035
LIB_OBJS += transport.o
10261036
LIB_OBJS += transport-helper.o
@@ -1604,7 +1614,9 @@ ifdef NO_INET_PTON
16041614
LIB_OBJS += compat/inet_pton.o
16051615
BASIC_CFLAGS += -DNO_INET_PTON
16061616
endif
1607-
ifndef NO_UNIX_SOCKETS
1617+
ifdef NO_UNIX_SOCKETS
1618+
BASIC_CFLAGS += -DNO_UNIX_SOCKETS
1619+
else
16081620
LIB_OBJS += unix-socket.o
16091621
PROGRAM_OBJS += credential-cache.o
16101622
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
@@ -1959,6 +1959,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
19591959
return 0;
19601960
prog = path_lookup(interpr, 1);
19611961
if (prog) {
1962+
int exec_id;
19621963
int argc = 0;
19631964
#ifndef _MSC_VER
19641965
const
@@ -1968,13 +1969,16 @@ static int try_shell_exec(const char *cmd, char *const *argv)
19681969
ALLOC_ARRAY(argv2, argc + 1);
19691970
argv2[0] = (char *)cmd; /* full path to the script file */
19701971
memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
1972+
exec_id = trace2_exec(prog, argv2);
19711973
pid = mingw_spawnv(prog, argv2, interpr);
19721974
if (pid >= 0) {
19731975
int status;
19741976
if (waitpid(pid, &status, 0) < 0)
19751977
status = 255;
1978+
trace2_exec_result(exec_id, status);
19761979
exit(status);
19771980
}
1981+
trace2_exec_result(exec_id, -1);
19781982
pid = 1; /* indicate that we tried but failed */
19791983
free(prog);
19801984
free(argv2);
@@ -1987,12 +1991,17 @@ int mingw_execv(const char *cmd, char *const *argv)
19871991
/* check if git_command is a shell script */
19881992
if (!try_shell_exec(cmd, argv)) {
19891993
int pid, status;
1994+
int exec_id;
19901995

1996+
exec_id = trace2_exec(cmd, (const char **)argv);
19911997
pid = mingw_spawnv(cmd, (const char **)argv, NULL);
1992-
if (pid < 0)
1998+
if (pid < 0) {
1999+
trace2_exec_result(exec_id, -1);
19932000
return -1;
2001+
}
19942002
if (waitpid(pid, &status, 0) < 0)
19952003
status = 255;
2004+
trace2_exec_result(exec_id, status);
19962005
exit(status);
19972006
}
19982007
return -1;

compat/mingw.h

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

config.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,8 @@ int git_config_set_gently(const char *key, const char *value)
27082708
void git_config_set(const char *key, const char *value)
27092709
{
27102710
git_config_set_multivar(key, value, NULL, 0);
2711+
2712+
trace2_cmd_set_config(key, value);
27112713
}
27122714

27132715
/*

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
@@ -1322,6 +1322,13 @@ struct fscache;
13221322

13231323
extern int cmd_main(int, const char **);
13241324

1325+
/*
1326+
* Intercept all calls to exit() and route them to trace2 to
1327+
* optionally emit a message before calling the real exit().
1328+
*/
1329+
int trace2_cmd_exit_fl(const char *file, int line, int code);
1330+
#define exit(code) exit(trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))
1331+
13251332
/*
13261333
* You can mark a stack variable with UNLEAK(var) to avoid it being
13271334
* reported as a leak by tools like LSAN or valgrind. The argument

git.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
150150
git_set_exec_path(cmd + 1);
151151
else {
152152
puts(git_exec_path());
153+
trace2_cmd_name("_query_");
153154
exit(0);
154155
}
155156
} else if (!strcmp(cmd, "--html-path")) {
156157
puts(system_path(GIT_HTML_PATH));
158+
trace2_cmd_name("_query_");
157159
exit(0);
158160
} else if (!strcmp(cmd, "--man-path")) {
159161
puts(system_path(GIT_MAN_PATH));
162+
trace2_cmd_name("_query_");
160163
exit(0);
161164
} else if (!strcmp(cmd, "--info-path")) {
162165
puts(system_path(GIT_INFO_PATH));
166+
trace2_cmd_name("_query_");
163167
exit(0);
164168
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
165169
use_pager = 1;
@@ -288,6 +292,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
288292
(*argv)++;
289293
(*argc)--;
290294
} else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
295+
trace2_cmd_name("_query_");
291296
if (!strcmp(cmd, "parseopt")) {
292297
struct string_list list = STRING_LIST_INIT_DUP;
293298
int i;
@@ -335,9 +340,14 @@ static int handle_alias(int *argcp, const char ***argv)
335340
commit_pager_choice();
336341

337342
child.use_shell = 1;
343+
child.trace2_child_class = "shell_alias";
338344
argv_array_push(&child.args, alias_string + 1);
339345
argv_array_pushv(&child.args, (*argv) + 1);
340346

347+
trace2_cmd_alias(alias_command, child.args.argv);
348+
trace2_cmd_list_config();
349+
trace2_cmd_name("_run_shell_alias_");
350+
341351
ret = run_command(&child);
342352
if (ret >= 0) /* normal exit */
343353
exit(ret);
@@ -372,6 +382,9 @@ static int handle_alias(int *argcp, const char ***argv)
372382
/* insert after command name */
373383
memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
374384

385+
trace2_cmd_alias(alias_command, new_argv);
386+
trace2_cmd_list_config();
387+
375388
*argv = new_argv;
376389
*argcp += count - 1;
377390

@@ -484,6 +497,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
484497
die("pre-command hook aborted command");
485498

486499
trace_argv_printf(argv, "trace: built-in: git");
500+
trace2_cmd_name(p->cmd);
501+
trace2_cmd_list_config();
487502

488503
validate_cache_entries(the_repository->index);
489504
exit_code = status = p->fn(argc, argv, prefix);
@@ -741,10 +756,17 @@ static void execv_dashed_external(const char **argv)
741756
cmd.clean_on_exit = 1;
742757
cmd.wait_after_clean = 1;
743758
cmd.silent_exec_failure = 1;
759+
cmd.trace2_child_class = "dashed";
744760

745761
if (run_pre_command_hook(cmd.args.argv))
746762
die("pre-command hook aborted command");
747763

764+
trace2_cmd_name("_run_dashed_");
765+
766+
/*
767+
* The code in run_command() logs trace2 child_start/child_exit
768+
* events, so we do not need to report exec/exec_result events here.
769+
*/
748770
trace_argv_printf(cmd.args.argv, "trace: exec:");
749771

750772
/*
@@ -754,6 +776,12 @@ static void execv_dashed_external(const char **argv)
754776
* the program.
755777
*/
756778
exit_code = status = run_command(&cmd);
779+
780+
/*
781+
* If the child process ran and we are now going to exit, emit a
782+
* generic string as our trace2 command verb to indicate that we
783+
* launched a dashed command.
784+
*/
757785
if (status >= 0)
758786
exit(status);
759787
else if (errno != ENOENT)
@@ -784,6 +812,15 @@ static int run_argv(int *argcp, const char ***argv)
784812
struct argv_array args = ARGV_ARRAY_INIT;
785813
int i;
786814

815+
/*
816+
* The current process is committed to launching a
817+
* child process to run the command named in (**argv)
818+
* and exiting. Log a generic string as the trace2
819+
* command verb to indicate this. Note that the child
820+
* process will log the actual verb when it runs.
821+
*/
822+
trace2_cmd_name("_run_git_alias_");
823+
787824
if (get_super_prefix())
788825
die("%s doesn't support --super-prefix", **argv);
789826

@@ -799,8 +836,8 @@ static int run_argv(int *argcp, const char ***argv)
799836
* if we fail because the command is not found, it is
800837
* OK to return. Otherwise, we just pass along the status code.
801838
*/
802-
i = run_command_v_opt(args.argv, RUN_SILENT_EXEC_FAILURE |
803-
RUN_CLEAN_ON_EXIT);
839+
i = run_command_v_opt_tr2(args.argv, RUN_SILENT_EXEC_FAILURE |
840+
RUN_CLEAN_ON_EXIT, "git_alias");
804841
if (i >= 0 || errno != ENOENT)
805842
exit(i);
806843
die("could not execute builtin %s", **argv);

0 commit comments

Comments
 (0)