Skip to content

Commit

Permalink
trace2: teach Git to log environment variables
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Jeff Hostetler <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
steadmon authored and gitster committed Mar 23, 2020
1 parent 98cedd0 commit 3d3adaa
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Documentation/config/trace2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ trace2.configParams::
May be overridden by the `GIT_TRACE2_CONFIG_PARAMS` environment
variable. Unset by default.

trace2.envVars::
A comma-separated list of "important" environment variables that should
be recorded in the trace2 output. For example,
`GIT_HTTP_USER_AGENT,GIT_CONFIG` would cause the trace2 output to
contain events listing the overrides for HTTP user agent and the
location of the Git configuration file (assuming any are set). May be
overriden by the `GIT_TRACE2_ENV_VARS` environment variable. Unset by
default.

trace2.destinationDebug::
Boolean. When true Git will print error messages when a
trace target destination cannot be opened for writing.
Expand Down
3 changes: 2 additions & 1 deletion Documentation/technical/api-trace2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,8 @@ The "exec_id" field is a command-unique id and is only useful if the
------------

`"def_param"`::
This event is generated to log a global parameter.
This event is generated to log a global parameter, such as a config
setting, command-line flag, or environment variable.
+
------------
{
Expand Down
3 changes: 3 additions & 0 deletions git.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ static int handle_alias(int *argcp, const char ***argv)

trace2_cmd_alias(alias_command, child.args.argv);
trace2_cmd_list_config();
trace2_cmd_list_env_vars();
trace2_cmd_name("_run_shell_alias_");

ret = run_command(&child);
Expand Down Expand Up @@ -388,6 +389,7 @@ static int handle_alias(int *argcp, const char ***argv)

trace2_cmd_alias(alias_command, new_argv);
trace2_cmd_list_config();
trace2_cmd_list_env_vars();

*argv = new_argv;
*argcp += count - 1;
Expand Down Expand Up @@ -439,6 +441,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
trace_argv_printf(argv, "trace: built-in: git");
trace2_cmd_name(p->cmd);
trace2_cmd_list_config();
trace2_cmd_list_env_vars();

validate_cache_entries(the_repository->index);
status = p->fn(argc, argv, prefix);
Expand Down
1 change: 1 addition & 0 deletions t/helper/test-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ int cmd_main(int argc, const char **argv)
argc--;
trace2_cmd_name(cmds[i].name);
trace2_cmd_list_config();
trace2_cmd_list_env_vars();
return cmds[i].fn(argc, argv);
}
}
Expand Down
37 changes: 37 additions & 0 deletions t/t0212-trace2-event.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,43 @@ test_expect_success JSON_PP 'event stream, list config' '
test_cmp expect actual
'

# Test listing of all "interesting" environment variables.

test_expect_success JSON_PP 'event stream, list env vars' '
test_when_finished "rm trace.event actual expect" &&
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
GIT_TRACE2_ENV_VARS="A_VAR,OTHER_VAR,MISSING" \
A_VAR=1 OTHER_VAR="hello world" test-tool trace2 001return 0 &&
perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
sed -e "s/^|//" >expect <<-EOF &&
|VAR1 = {
| "_SID0_":{
| "argv":[
| "_EXE_",
| "trace2",
| "001return",
| "0"
| ],
| "exit_code":0,
| "hierarchy":"trace2",
| "name":"trace2",
| "params":[
| {
| "param":"A_VAR",
| "value":"1"
| },
| {
| "param":"OTHER_VAR",
| "value":"hello world"
| }
| ],
| "version":"$V"
| }
|};
EOF
test_cmp expect actual
'

test_expect_success JSON_PP 'basic trace2_data' '
test_when_finished "rm trace.event actual expect" &&
GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool trace2 006data test_category k1 v1 test_category k2 v2 &&
Expand Down
9 changes: 9 additions & 0 deletions trace2.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ static void tr2main_atexit_handler(void)
tr2_sid_release();
tr2_cmd_name_release();
tr2_cfg_free_patterns();
tr2_cfg_free_env_vars();
tr2_sysenv_release();

trace2_enabled = 0;
Expand Down Expand Up @@ -311,6 +312,14 @@ void trace2_cmd_list_config_fl(const char *file, int line)
tr2_cfg_list_config_fl(file, line);
}

void trace2_cmd_list_env_vars_fl(const char *file, int line)
{
if (!trace2_enabled)
return;

tr2_list_env_vars_fl(file, line);
}

void trace2_cmd_set_config_fl(const char *file, int line, const char *key,
const char *value)
{
Expand Down
13 changes: 13 additions & 0 deletions trace2.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,19 @@ void trace2_cmd_list_config_fl(const char *file, int line);

#define trace2_cmd_list_config() trace2_cmd_list_config_fl(__FILE__, __LINE__)

/*
* Emit one or more 'def_param' events for "important" environment variables.
*
* Use the TR2_SYSENV_ENV_VARS setting to register a comma-separated list of
* environment variables considered important. For example:
* git config --system trace2.envVars 'GIT_HTTP_USER_AGENT,GIT_CONFIG'
* or:
* GIT_TRACE2_ENV_VARS="GIT_HTTP_USER_AGENT,GIT_CONFIG"
*/
void trace2_cmd_list_env_vars_fl(const char *file, int line);

#define trace2_cmd_list_env_vars() trace2_cmd_list_env_vars_fl(__FILE__, __LINE__)

/*
* Emit a "def_param" event for the given config key/value pair IF
* we consider the key to be "important".
Expand Down
58 changes: 58 additions & 0 deletions trace2/tr2_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ static struct strbuf **tr2_cfg_patterns;
static int tr2_cfg_count_patterns;
static int tr2_cfg_loaded;

static struct strbuf **tr2_cfg_env_vars;
static int tr2_cfg_env_vars_count;
static int tr2_cfg_env_vars_loaded;

/*
* Parse a string containing a comma-delimited list of config keys
* or wildcard patterns into a list of strbufs.
Expand Down Expand Up @@ -46,6 +50,45 @@ void tr2_cfg_free_patterns(void)
tr2_cfg_loaded = 0;
}

/*
* Parse a string containing a comma-delimited list of environment variable
* names into a list of strbufs.
*/
static int tr2_load_env_vars(void)
{
struct strbuf **s;
const char *varlist;

if (tr2_cfg_env_vars_loaded)
return tr2_cfg_env_vars_count;
tr2_cfg_env_vars_loaded = 1;

varlist = tr2_sysenv_get(TR2_SYSENV_ENV_VARS);
if (!varlist || !*varlist)
return tr2_cfg_env_vars_count;

tr2_cfg_env_vars = strbuf_split_buf(varlist, strlen(varlist), ',', -1);
for (s = tr2_cfg_env_vars; *s; s++) {
struct strbuf *buf = *s;

if (buf->len && buf->buf[buf->len - 1] == ',')
strbuf_setlen(buf, buf->len - 1);
strbuf_trim_trailing_newline(*s);
strbuf_trim(*s);
}

tr2_cfg_env_vars_count = s - tr2_cfg_env_vars;
return tr2_cfg_env_vars_count;
}

void tr2_cfg_free_env_vars(void)
{
if (tr2_cfg_env_vars)
strbuf_list_free(tr2_cfg_env_vars);
tr2_cfg_env_vars_count = 0;
tr2_cfg_env_vars_loaded = 0;
}

struct tr2_cfg_data {
const char *file;
int line;
Expand Down Expand Up @@ -79,6 +122,21 @@ void tr2_cfg_list_config_fl(const char *file, int line)
read_early_config(tr2_cfg_cb, &data);
}

void tr2_list_env_vars_fl(const char *file, int line)
{
struct strbuf **s;

if (tr2_load_env_vars() <= 0)
return;

for (s = tr2_cfg_env_vars; *s; s++) {
struct strbuf *buf = *s;
const char *val = getenv(buf->buf);
if (val && *val)
trace2_def_param_fl(file, line, buf->buf, val);
}
}

void tr2_cfg_set_fl(const char *file, int line, const char *key,
const char *value)
{
Expand Down
8 changes: 8 additions & 0 deletions trace2/tr2_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
*/
void tr2_cfg_list_config_fl(const char *file, int line);

/*
* Iterate over all "interesting" environment variables and emit 'def_param'
* events for them to TRACE2.
*/
void tr2_list_env_vars_fl(const char *file, int line);

/*
* Emit a "def_param" event for the given key/value pair IF we consider
* the key to be "interesting".
Expand All @@ -16,4 +22,6 @@ void tr2_cfg_set_fl(const char *file, int line, const char *key,

void tr2_cfg_free_patterns(void);

void tr2_cfg_free_env_vars(void);

#endif /* TR2_CFG_H */
2 changes: 2 additions & 0 deletions trace2/tr2_sysenv.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct tr2_sysenv_entry {
static struct tr2_sysenv_entry tr2_sysenv_settings[] = {
[TR2_SYSENV_CFG_PARAM] = { "GIT_TRACE2_CONFIG_PARAMS",
"trace2.configparams" },
[TR2_SYSENV_ENV_VARS] = { "GIT_TRACE2_ENV_VARS",
"trace2.envvars" },

[TR2_SYSENV_DST_DEBUG] = { "GIT_TRACE2_DST_DEBUG",
"trace2.destinationdebug" },
Expand Down
1 change: 1 addition & 0 deletions trace2/tr2_sysenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
enum tr2_sysenv_variable {
TR2_SYSENV_CFG_PARAM = 0,
TR2_SYSENV_ENV_VARS,

TR2_SYSENV_DST_DEBUG,

Expand Down

0 comments on commit 3d3adaa

Please sign in to comment.