Subject: [PATCH v2 0/7] trace2: load trace2 settings from system config

From: "Jeff Hostetler via GitGitGadget" <[email-masked]>
Date: Fri, 29 Mar 2019 10:04:24 -0700 (PDT)

Here is version 2. It addresses most the V1 comments WRT the system config
changes.

It also addresses the format and uniqueness of the SID as discussed in [1].
The SID now containes: the UTC date/time, part of SHA1 of the hostname, and
the PID and is formatted to make it safe for filenames.

It also contains (a somewhat unrelated platform-specific) commit to report
total process memory usage at exit. This is helpful when looking for
problematic commands that might have scaling problems.

[1] 
https://public-inbox.org/git/[email-masked]/T/#m6b4e6f2b0374d5ba88de8d0350ce6bf51b28d7da

----------------------------------------------------------------------------

Teach git to load default Trace2 settings from the system config (usually
"/etc/gitconfig"). The existing GIT_TR2_* environment variables can be used
to override the new system defaults. It also includes a little startup
refactoring.

Note: I found interactive testing of this feature to be awkward on some
platforms because of the use of prefix- or runtime-prefix-relative locations
for the system configuration. It was easy to accidentally use an officially
installed version of git to set a system config variable in the official
system config directory; and then when testing with the test version of git,
that value would not be seen because it was looking for the system config
file in a different directory.

Jeff Hostetler (7):
  trace2: refactor setting process starting time
  trace2: add absolute elapsed time to start event
  trace2: find exec-dir before trace2 initialization
  trace2: use system config for default trace2 settings
  trace2: report peak memory usage of the process
  trace2: clarify UTC datetime formatting
  trace2: make SIDs more unique

 Documentation/technical/api-trace2.txt   |  66 +++++++++---
 Makefile                                 |   1 +
 common-main.c                            |   8 +-
 compat/mingw.c                           |   2 +
 compat/win32/trace2_win32_process_info.c |  50 ++++++++-
 t/t0210-trace2-normal.sh                 |  41 +++++++-
 t/t0211-trace2-perf.sh                   |  53 ++++++++--
 t/t0212-trace2-event.sh                  |  52 ++++++++-
 trace2.c                                 |  21 +++-
 trace2.h                                 |  43 ++++++--
 trace2/tr2_cfg.c                         |   7 +-
 trace2/tr2_dst.c                         |  24 ++---
 trace2/tr2_dst.h                         |   3 +-
 trace2/tr2_sid.c                         |  39 ++++++-
 trace2/tr2_sysenv.c                      | 128 +++++++++++++++++++++++
 trace2/tr2_sysenv.h                      |  36 +++++++
 trace2/tr2_tbuf.c                        |  20 +++-
 trace2/tr2_tbuf.h                        |   5 +-
 trace2/tr2_tgt.h                         |   1 +
 trace2/tr2_tgt_event.c                   |  53 +++++-----
 trace2/tr2_tgt_normal.c                  |  19 ++--
 trace2/tr2_tgt_perf.c                    |  23 ++--
 trace2/tr2_tls.c                         |  38 ++++---
 trace2/tr2_tls.h                         |   8 +-
 24 files changed, 604 insertions(+), 137 deletions(-)
 create mode 100644 trace2/tr2_sysenv.c
 create mode 100644 trace2/tr2_sysenv.h

base-commit: 041f5ea1cf987a4068ef5f39ba0a09be85952064
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-169%2Fjeffhostetler%2Fcore-tr2-startup-and-sysenv-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-169/jeffhostetler/core-tr2-startup-and-sysenv-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/169

Range-diff vs v1:

 1:  7f1a347322 = 1:  7f1a347322 trace2: refactor setting process starting time
 2:  c15f783c26 = 2:  c15f783c26 trace2: add absolute elapsed time to start event
 3:  d4023acde7 = 3:  d4023acde7 trace2: find exec-dir before trace2 initialization
 4:  7e0d4e20fb ! 4:  d048f3ffb8 trace2: use system config for default trace2 settings
     @@ -332,11 +332,16 @@
        *
      - * The environment variable "GIT_TR2_CONFIG_PARAMS" can be set to a
      - * list of patterns considered important.  For example:
     -+ * Use the TR2_SYSENV_CFG_PARAM setting to register a list of patterns
     -+ * configured important.  For example:
     -  *
     -  *    GIT_TR2_CONFIG_PARAMS="core.*,remote.*.url"
     +- *
     +- *    GIT_TR2_CONFIG_PARAMS="core.*,remote.*.url"
     ++ * Use the TR2_SYSENV_CFG_PARAM setting to register a comma-separated
     ++ * list of patterns configured important.  For example:
     ++ *     git config --system trace2.configParams 'core.*,remote.*.url'
     ++ * or:
     ++ *     GIT_TR2_CONFIG_PARAMS=core.*,remote.*.url"
        *
     +  * Note: this routine does a read-only iteration on the config data
     +  * (using read_early_config()), so it must not be called until enough
      
       diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c
       --- a/trace2/tr2_cfg.c
     @@ -527,6 +532,9 @@
      +{
      +	int k;
      +
     ++	if (!starts_with(key, "trace2."))
     ++		return 0;
     ++
      +	for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++) {
      +		if (!strcmp(key, tr2_sysenv_settings[k].git_config_name)) {
      +			free(tr2_sysenv_settings[k].value);
     @@ -673,7 +681,8 @@
      + * region details in the event target.
        */
      -#define TR2_ENVVAR_EVENT_NESTING "GIT_TR2_EVENT_NESTING"
     - static int tr2env_event_nesting_wanted = 2;
     +-static int tr2env_event_nesting_wanted = 2;
     ++static int tr2env_event_max_nesting_levels = 2;
       
       /*
      - * Set this environment variable to true to omit the <time>, <file>, and
     @@ -681,12 +690,14 @@
        * <line> fields from most events.
        */
      -#define TR2_ENVVAR_EVENT_BRIEF "GIT_TR2_EVENT_BRIEF"
     - static int tr2env_event_brief;
     +-static int tr2env_event_brief;
     ++static int tr2env_event_be_brief;
       
       static int fn_init(void)
     -@@
     + {
       	int want = tr2_dst_trace_want(&tr2dst_event);
     - 	int want_nesting;
     +-	int want_nesting;
     ++	int max_nesting;
       	int want_brief;
      -	char *nesting;
      -	char *brief;
     @@ -697,15 +708,74 @@
       		return want;
       
      -	nesting = getenv(TR2_ENVVAR_EVENT_NESTING);
     +-	if (nesting && ((want_nesting = atoi(nesting)) > 0))
     +-		tr2env_event_nesting_wanted = want_nesting;
      +	nesting = tr2_sysenv_get(TR2_SYSENV_EVENT_NESTING);
     - 	if (nesting && ((want_nesting = atoi(nesting)) > 0))
     - 		tr2env_event_nesting_wanted = want_nesting;
     ++	if (nesting && *nesting && ((max_nesting = atoi(nesting)) > 0))
     ++		tr2env_event_max_nesting_levels = max_nesting;
       
      -	brief = getenv(TR2_ENVVAR_EVENT_BRIEF);
     +-	if (brief && ((want_brief = atoi(brief)) > 0))
     +-		tr2env_event_brief = want_brief;
      +	brief = tr2_sysenv_get(TR2_SYSENV_EVENT_BRIEF);
     - 	if (brief && ((want_brief = atoi(brief)) > 0))
     - 		tr2env_event_brief = want_brief;
     ++	if (brief && *brief &&
     ++	    ((want_brief = git_parse_maybe_bool(brief)) != -1))
     ++		tr2env_event_be_brief = want_brief;
       
     + 	return want;
     + }
     +@@
     + 	/*
     + 	 * In brief mode, only emit <time> on these 2 event types.
     + 	 */
     +-	if (!tr2env_event_brief || !strcmp(event_name, "version") ||
     ++	if (!tr2env_event_be_brief || !strcmp(event_name, "version") ||
     + 	    !strcmp(event_name, "atexit")) {
     + 		tr2_tbuf_utc_time(&tb_now);
     + 		jw_object_string(jw, "time", tb_now.buf);
     + 	}
     + 
     +-	if (!tr2env_event_brief && file && *file) {
     ++	if (!tr2env_event_be_brief && file && *file) {
     + 		jw_object_string(jw, "file", file);
     + 		jw_object_intmax(jw, "line", line);
     + 	}
     +@@
     + {
     + 	const char *event_name = "region_enter";
     + 	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
     +-	if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
     ++	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
     + 		struct json_writer jw = JSON_WRITER_INIT;
     + 
     + 		jw_object_begin(&jw, 0);
     +@@
     + {
     + 	const char *event_name = "region_leave";
     + 	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
     +-	if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
     ++	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
     + 		struct json_writer jw = JSON_WRITER_INIT;
     + 		double t_rel = (double)us_elapsed_region / 1000000.0;
     + 
     +@@
     + {
     + 	const char *event_name = "data";
     + 	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
     +-	if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
     ++	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
     + 		struct json_writer jw = JSON_WRITER_INIT;
     + 		double t_abs = (double)us_elapsed_absolute / 1000000.0;
     + 		double t_rel = (double)us_elapsed_region / 1000000.0;
     +@@
     + {
     + 	const char *event_name = "data_json";
     + 	struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
     +-	if (ctx->nr_open_regions <= tr2env_event_nesting_wanted) {
     ++	if (ctx->nr_open_regions <= tr2env_event_max_nesting_levels) {
     + 		struct json_writer jw = JSON_WRITER_INIT;
     + 		double t_abs = (double)us_elapsed_absolute / 1000000.0;
     + 		double t_rel = (double)us_elapsed_region / 1000000.0;
      
       diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c
       --- a/trace2/tr2_tgt_normal.c
     @@ -730,9 +800,11 @@
        * Unit tests may want to use this to help with testing.
        */
      -#define TR2_ENVVAR_NORMAL_BRIEF "GIT_TR2_BRIEF"
     - static int tr2env_normal_brief;
     +-static int tr2env_normal_brief;
     ++static int tr2env_normal_be_brief;
       
       #define TR2FMT_NORMAL_FL_WIDTH (50)
     + 
      @@
       {
       	int want = tr2_dst_trace_want(&tr2dst_normal);
     @@ -747,7 +819,20 @@
      +	brief = tr2_sysenv_get(TR2_SYSENV_NORMAL_BRIEF);
       	if (brief && *brief &&
       	    ((want_brief = git_parse_maybe_bool(brief)) != -1))
     - 		tr2env_normal_brief = want_brief;
     +-		tr2env_normal_brief = want_brief;
     ++		tr2env_normal_be_brief = want_brief;
     + 
     + 	return want;
     + }
     +@@
     + {
     + 	strbuf_setlen(buf, 0);
     + 
     +-	if (!tr2env_normal_brief) {
     ++	if (!tr2env_normal_be_brief) {
     + 		struct tr2_tbuf tb_now;
     + 
     + 		tr2_tbuf_local_time(&tb_now);
      
       diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c
       --- a/trace2/tr2_tgt_perf.c
     @@ -772,9 +857,11 @@
        * Unit tests may want to use this to help with testing.
        */
      -#define TR2_ENVVAR_PERF_BRIEF "GIT_TR2_PERF_BRIEF"
     - static int tr2env_perf_brief;
     +-static int tr2env_perf_brief;
     ++static int tr2env_perf_be_brief;
       
       #define TR2FMT_PERF_FL_WIDTH (50)
     + #define TR2FMT_PERF_MAX_EVENT_NAME (12)
      @@
       {
       	int want = tr2_dst_trace_want(&tr2dst_perf);
     @@ -791,4 +878,17 @@
      +	brief = tr2_sysenv_get(TR2_SYSENV_PERF_BRIEF);
       	if (brief && *brief &&
       	    ((want_brief = git_parse_maybe_bool(brief)) != -1))
     - 		tr2env_perf_brief = want_brief;
     +-		tr2env_perf_brief = want_brief;
     ++		tr2env_perf_be_brief = want_brief;
     + 
     + 	return want;
     + }
     +@@
     + 
     + 	strbuf_setlen(buf, 0);
     + 
     +-	if (!tr2env_perf_brief) {
     ++	if (!tr2env_perf_be_brief) {
     + 		struct tr2_tbuf tb_now;
     + 
     + 		tr2_tbuf_local_time(&tb_now);
 -:  ---------- > 5:  86d8fe28cf trace2: report peak memory usage of the process
 -:  ---------- > 6:  ae11cc4186 trace2: clarify UTC datetime formatting
 -:  ---------- > 7:  4352952677 trace2: make SIDs more unique

-- 
gitgitgadget