@matheusbsbs / matheus-bagliano / commits / 3d3adaad91
Fork 0

trace2: teach Git to log environment variables

Via trace2, Git can already log interesting config parameters (see the trace2_cmd_list_config() function). However, this can grant an incomplete picture because many config parameters also allow overrides via environment variables. To allow for more complete logs, we add a new trace2_cmd_list_env_vars() function and supporting implementation, modeled after the pre-existing config param logging implementation. Signed-off-by: Josh Steadmon <steadmon@google.com> Acked-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Josh Steadmon committed Mar 20, 2020 at 14:06 UTC 3d3adaad914441a6e7b916eb8dfd5ae638aab068
11 files changed +143 -1
Documentation/config/trace2.txt
+9
@@ -48,6 +48,15 @@ trace2.configParams::
48 May be overridden by the `GIT_TRACE2_CONFIG_PARAMS` environment
49 variable. Unset by default.
50
51 +trace2.envVars::
52 + A comma-separated list of "important" environment variables that should
53 + be recorded in the trace2 output. For example,
54 + `GIT_HTTP_USER_AGENT,GIT_CONFIG` would cause the trace2 output to
55 + contain events listing the overrides for HTTP user agent and the
56 + location of the Git configuration file (assuming any are set). May be
57 + overriden by the `GIT_TRACE2_ENV_VARS` environment variable. Unset by
58 + default.
59 +
60 trace2.destinationDebug::
61 Boolean. When true Git will print error messages when a
62 trace target destination cannot be opened for writing.
Documentation/technical/api-trace2.txt
+2 -1
@@ -656,7 +656,8 @@ The "exec_id" field is a command-unique id and is only useful if the
656 ------------
657
658 `"def_param"`::
659 - This event is generated to log a global parameter.
659 + This event is generated to log a global parameter, such as a config
660 + setting, command-line flag, or environment variable.
661 +
662 ------------
663 {
git.c
+3
@@ -351,6 +351,7 @@ static int handle_alias(int *argcp, const char ***argv)
351
352 trace2_cmd_alias(alias_command, child.args.argv);
353 trace2_cmd_list_config();
354 + trace2_cmd_list_env_vars();
355 trace2_cmd_name("_run_shell_alias_");
356
357 ret = run_command(&child);
@@ -388,6 +389,7 @@ static int handle_alias(int *argcp, const char ***argv)
389
390 trace2_cmd_alias(alias_command, new_argv);
391 trace2_cmd_list_config();
392 + trace2_cmd_list_env_vars();
393
394 *argv = new_argv;
395 *argcp += count - 1;
@@ -439,6 +441,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
441 trace_argv_printf(argv, "trace: built-in: git");
442 trace2_cmd_name(p->cmd);
443 trace2_cmd_list_config();
444 + trace2_cmd_list_env_vars();
445
446 validate_cache_entries(the_repository->index);
447 status = p->fn(argc, argv, prefix);
t/helper/test-tool.c
+1
@@ -111,6 +111,7 @@ int cmd_main(int argc, const char **argv)
111 argc--;
112 trace2_cmd_name(cmds[i].name);
113 trace2_cmd_list_config();
114 + trace2_cmd_list_env_vars();
115 return cmds[i].fn(argc, argv);
116 }
117 }
t/t0212-trace2-event.sh
+37
@@ -199,6 +199,43 @@ test_expect_success JSON_PP 'event stream, list config' '
199 test_cmp expect actual
200 '
201
202 +# Test listing of all "interesting" environment variables.
203 +
204 +test_expect_success JSON_PP 'event stream, list env vars' '
205 + test_when_finished "rm trace.event actual expect" &&
206 + GIT_TRACE2_EVENT="$(pwd)/trace.event" \
207 + GIT_TRACE2_ENV_VARS="A_VAR,OTHER_VAR,MISSING" \
208 + A_VAR=1 OTHER_VAR="hello world" test-tool trace2 001return 0 &&
209 + perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
210 + sed -e "s/^|//" >expect <<-EOF &&
211 + |VAR1 = {
212 + | "_SID0_":{
213 + | "argv":[
214 + | "_EXE_",
215 + | "trace2",
216 + | "001return",
217 + | "0"
218 + | ],
219 + | "exit_code":0,
220 + | "hierarchy":"trace2",
221 + | "name":"trace2",
222 + | "params":[
223 + | {
224 + | "param":"A_VAR",
225 + | "value":"1"
226 + | },
227 + | {
228 + | "param":"OTHER_VAR",
229 + | "value":"hello world"
230 + | }
231 + | ],
232 + | "version":"$V"
233 + | }
234 + |};
235 + EOF
236 + test_cmp expect actual
237 +'
238 +
239 test_expect_success JSON_PP 'basic trace2_data' '
240 test_when_finished "rm trace.event actual expect" &&
241 GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool trace2 006data test_category k1 v1 test_category k2 v2 &&
trace2.c
+9
@@ -121,6 +121,7 @@ static void tr2main_atexit_handler(void)
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;
@@ -311,6 +312,14 @@ void trace2_cmd_list_config_fl(const char *file, int line)
312 tr2_cfg_list_config_fl(file, line);
313 }
314
315 +void trace2_cmd_list_env_vars_fl(const char *file, int line)
316 +{
317 + if (!trace2_enabled)
318 + return;
319 +
320 + tr2_list_env_vars_fl(file, line);
321 +}
322 +
323 void trace2_cmd_set_config_fl(const char *file, int line, const char *key,
324 const char *value)
325 {
trace2.h
+13
@@ -182,6 +182,19 @@ void trace2_cmd_list_config_fl(const char *file, int line);
182
183 #define trace2_cmd_list_config() trace2_cmd_list_config_fl(__FILE__, __LINE__)
184
185 +/*
186 + * Emit one or more 'def_param' events for "important" environment variables.
187 + *
188 + * Use the TR2_SYSENV_ENV_VARS setting to register a comma-separated list of
189 + * environment variables considered important. For example:
190 + * git config --system trace2.envVars 'GIT_HTTP_USER_AGENT,GIT_CONFIG'
191 + * or:
192 + * GIT_TRACE2_ENV_VARS="GIT_HTTP_USER_AGENT,GIT_CONFIG"
193 + */
194 +void trace2_cmd_list_env_vars_fl(const char *file, int line);
195 +
196 +#define trace2_cmd_list_env_vars() trace2_cmd_list_env_vars_fl(__FILE__, __LINE__)
197 +
198 /*
199 * Emit a "def_param" event for the given config key/value pair IF
200 * we consider the key to be "important".
trace2/tr2_cfg.c
+58
@@ -7,6 +7,10 @@ static struct strbuf **tr2_cfg_patterns;
7 static int tr2_cfg_count_patterns;
8 static int tr2_cfg_loaded;
9
10 +static struct strbuf **tr2_cfg_env_vars;
11 +static int tr2_cfg_env_vars_count;
12 +static int tr2_cfg_env_vars_loaded;
13 +
14 /*
15 * Parse a string containing a comma-delimited list of config keys
16 * or wildcard patterns into a list of strbufs.
@@ -46,6 +50,45 @@ void tr2_cfg_free_patterns(void)
50 tr2_cfg_loaded = 0;
51 }
52
53 +/*
54 + * Parse a string containing a comma-delimited list of environment variable
55 + * names into a list of strbufs.
56 + */
57 +static int tr2_load_env_vars(void)
58 +{
59 + struct strbuf **s;
60 + const char *varlist;
61 +
62 + if (tr2_cfg_env_vars_loaded)
63 + return tr2_cfg_env_vars_count;
64 + tr2_cfg_env_vars_loaded = 1;
65 +
66 + varlist = tr2_sysenv_get(TR2_SYSENV_ENV_VARS);
67 + if (!varlist || !*varlist)
68 + return tr2_cfg_env_vars_count;
69 +
70 + tr2_cfg_env_vars = strbuf_split_buf(varlist, strlen(varlist), ',', -1);
71 + for (s = tr2_cfg_env_vars; *s; s++) {
72 + struct strbuf *buf = *s;
73 +
74 + if (buf->len && buf->buf[buf->len - 1] == ',')
75 + strbuf_setlen(buf, buf->len - 1);
76 + strbuf_trim_trailing_newline(*s);
77 + strbuf_trim(*s);
78 + }
79 +
80 + tr2_cfg_env_vars_count = s - tr2_cfg_env_vars;
81 + return tr2_cfg_env_vars_count;
82 +}
83 +
84 +void tr2_cfg_free_env_vars(void)
85 +{
86 + if (tr2_cfg_env_vars)
87 + strbuf_list_free(tr2_cfg_env_vars);
88 + tr2_cfg_env_vars_count = 0;
89 + tr2_cfg_env_vars_loaded = 0;
90 +}
91 +
92 struct tr2_cfg_data {
93 const char *file;
94 int line;
@@ -79,6 +122,21 @@ void tr2_cfg_list_config_fl(const char *file, int line)
122 read_early_config(tr2_cfg_cb, &data);
123 }
124
125 +void tr2_list_env_vars_fl(const char *file, int line)
126 +{
127 + struct strbuf **s;
128 +
129 + if (tr2_load_env_vars() <= 0)
130 + return;
131 +
132 + for (s = tr2_cfg_env_vars; *s; s++) {
133 + struct strbuf *buf = *s;
134 + const char *val = getenv(buf->buf);
135 + if (val && *val)
136 + trace2_def_param_fl(file, line, buf->buf, val);
137 + }
138 +}
139 +
140 void tr2_cfg_set_fl(const char *file, int line, const char *key,
141 const char *value)
142 {
trace2/tr2_cfg.h
+8
@@ -7,6 +7,12 @@
7 */
8 void tr2_cfg_list_config_fl(const char *file, int line);
9
10 +/*
11 + * Iterate over all "interesting" environment variables and emit 'def_param'
12 + * events for them to TRACE2.
13 + */
14 +void tr2_list_env_vars_fl(const char *file, int line);
15 +
16 /*
17 * Emit a "def_param" event for the given key/value pair IF we consider
18 * the key to be "interesting".
@@ -16,4 +22,6 @@ void tr2_cfg_set_fl(const char *file, int line, const char *key,
22
23 void tr2_cfg_free_patterns(void);
24
25 +void tr2_cfg_free_env_vars(void);
26 +
27 #endif /* TR2_CFG_H */
trace2/tr2_sysenv.c
+2
@@ -29,6 +29,8 @@ struct tr2_sysenv_entry {
29 static struct tr2_sysenv_entry tr2_sysenv_settings[] = {
30 [TR2_SYSENV_CFG_PARAM] = { "GIT_TRACE2_CONFIG_PARAMS",
31 "trace2.configparams" },
32 + [TR2_SYSENV_ENV_VARS] = { "GIT_TRACE2_ENV_VARS",
33 + "trace2.envvars" },
34
35 [TR2_SYSENV_DST_DEBUG] = { "GIT_TRACE2_DST_DEBUG",
36 "trace2.destinationdebug" },
trace2/tr2_sysenv.h
+1
@@ -11,6 +11,7 @@
11 */
12 enum tr2_sysenv_variable {
13 TR2_SYSENV_CFG_PARAM = 0,
14 + TR2_SYSENV_ENV_VARS,
15
16 TR2_SYSENV_DST_DEBUG,
17