Polishing of the new trace2 facility continues. The system-level
configuration can specify site-wide trace2 settings, which can be
overridden with per-user configuration and environment variables.
* jh/trace2-sid-fix:
trace2: fixup access problem on /etc/gitconfig in read_very_early_config
trace2: update docs to describe system/global config settings
trace2: make SIDs more unique
trace2: clarify UTC datetime formatting
trace2: report peak memory usage of the process
trace2: use system/global config for default trace2 settings
config: add read_very_early_config()
trace2: find exec-dir before trace2 initialization
trace2: add absolute elapsed time to start event
trace2: refactor setting process starting time
config: initialize opts structure in repo_read_config()
formats in the future. This might be used to define a binary format,
for example.
+ Trace2 is controlled using `trace2.*` config values in the system and
+ global config files and `GIT_TR2*` environment variables. Trace2 does
+ not read from repo local or worktree config files or respect `-c`
+ command line config settings.
+
== Trace2 Targets
Trace2 defines the following set of Trace2 Targets.
Format details are given in a later section.
- `GIT_TR2` (NORMAL)::
+ === The Normal Format Target
+
+ The normal format target is a tradition printf format and similar
+ to GIT_TRACE format. This format is enabled with the `GIT_TR`
+ environment variable or the `trace2.normalTarget` system or global
+ config setting.
+
+ For example
- a simple printf format like GIT_TRACE.
- +
------------
$ export GIT_TR2=~/log.normal
$ git version
git version 2.20.1.155.g426c96fcdb
------------
- +
+
+ or
+
+ ------------
+ $ git config --global trace2.normalTarget ~/log.normal
+ $ git version
+ git version 2.20.1.155.g426c96fcdb
+ ------------
+
+ yields
+
------------
$ cat ~/log.normal
12:28:42.620009 common-main.c:38 version 2.20.1.155.g426c96fcdb
12:28:42.621250 trace2/tr2_tgt_normal.c:124 atexit elapsed:0.001265 code:0
------------
- `GIT_TR2_PERF` (PERF)::
+ === The Performance Format Target
+
+ The performance format target (PERF) is a column-based format to
+ replace GIT_TRACE_PERFORMANCE and is suitable for development and
+ testing, possibly to complement tools like gprof. This format is
+ enabled with the `GIT_TR2_PERF` environment variable or the
+ `trace2.perfTarget` system or global config setting.
+
+ For example
- a column-based format to replace GIT_TRACE_PERFORMANCE suitable for
- development and testing, possibly to complement tools like gprof.
- +
------------
$ export GIT_TR2_PERF=~/log.perf
$ git version
git version 2.20.1.155.g426c96fcdb
------------
- +
+
+ or
+
+ ------------
+ $ git config --global trace2.perfTarget ~/log.perf
+ $ git version
+ git version 2.20.1.155.g426c96fcdb
+ ------------
+
+ yields
+
------------
$ cat ~/log.perf
12:28:42.620675 common-main.c:38 | d0 | main | version | | | | | 2.20.1.155.g426c96fcdb
- 12:28:42.621001 common-main.c:39 | d0 | main | start | | | | | git version
+ 12:28:42.621001 common-main.c:39 | d0 | main | start | | 0.001173 | | | git version
12:28:42.621111 git.c:432 | d0 | main | cmd_name | | | | | version (version)
12:28:42.621225 git.c:662 | d0 | main | exit | | 0.001227 | | | code:0
12:28:42.621259 trace2/tr2_tgt_perf.c:211 | d0 | main | atexit | | 0.001265 | | | code:0
------------
- `GIT_TR2_EVENT` (EVENT)::
+ === The Event Format Target
+
+ The event format target is a JSON-based format of event data suitable
+ for telemetry analysis. This format is enabled with the `GIT_TR2_EVENT`
+ environment variable or the `trace2.eventTarget` system or global config
+ setting.
+
+ For example
- a JSON-based format of event data suitable for telemetry analysis.
- +
------------
$ export GIT_TR2_EVENT=~/log.event
$ git version
git version 2.20.1.155.g426c96fcdb
------------
- +
- ------------
- $ cat ~/log.event
- {"event":"version","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.620713","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"}
- {"event":"start","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621027","file":"common-main.c","line":39,"argv":["git","version"]}
- {"event":"cmd_name","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621122","file":"git.c","line":432,"name":"version","hierarchy":"version"}
- {"event":"exit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621236","file":"git.c","line":662,"t_abs":0.001227,"code":0}
- {"event":"atexit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621268","file":"trace2/tr2_tgt_event.c","line":163,"t_abs":0.001265,"code":0}
- ------------
-
- == Enabling a Target
- A Trace2 Target is enabled when the corresponding environment variable
- (`GIT_TR2`, `GIT_TR2_PERF`, or `GIT_TR2_EVENT`) is set. The following
- values are recognized.
+ or
- `0`::
- `false`::
-
- Disables the target.
-
- `1`::
- `true`::
-
- Enables the target and writes stream to `STDERR`.
-
- `[2-9]`::
+ ------------
+ $ git config --global trace2.eventTarget ~/log.event
+ $ git version
+ git version 2.20.1.155.g426c96fcdb
+ ------------
- Enables the target and writes to the already opened file descriptor.
+ yields
- `<absolute-pathname>`::
+ ------------
+ $ cat ~/log.event
+ {"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"}
+ {"event":"start","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621027Z","file":"common-main.c","line":39,"t_abs":0.001173,"argv":["git","version"]}
+ {"event":"cmd_name","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621122Z","file":"git.c","line":432,"name":"version","hierarchy":"version"}
+ {"event":"exit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621236Z","file":"git.c","line":662,"t_abs":0.001227,"code":0}
+ {"event":"atexit","sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.621268Z","file":"trace2/tr2_tgt_event.c","line":163,"t_abs":0.001265,"code":0}
+ ------------
- Enables the target, opens and writes to the file in append mode.
+ === Enabling a Target
- If the target already exists and is a directory, the traces will be
- written to files (one per process) underneath the given directory. They
- will be named according to the last component of the SID (optionally
- followed by a counter to avoid filename collisions).
+ To enable a target, set the corresponding environment variable or
+ system or global config value to one of the following:
- `af_unix:[<socket_type>:]<absolute-pathname>`::
+ include::../trace2-target-values.txt[]
- Enables the target, opens and writes to a Unix Domain Socket
- (on platforms that support them).
- +
- Socket type can be either `stream` or `dgram`. If the socket type is
- omitted, Git will try both.
++If the target already exists and is a directory, the traces will be
++written to files (one per process) underneath the given directory. They
++will be named according to the last component of the SID (optionally
++followed by a counter to avoid filename collisions).
+
== Trace2 API
All public Trace2 functions and macros are defined in `trace2.h` and
These are concerned with the lifetime of the overall git process.
+ `void trace2_initialize_clock()`::
+
+ Initialize the Trace2 start clock and nothing else. This should
+ be called at the very top of main() to capture the process start
+ time and reduce startup order dependencies.
+
`void trace2_initialize()`::
Determines if any Trace2 Targets should be enabled and
- initializes the Trace2 facility. This includes starting the
- elapsed time clocks and thread local storage (TLS).
+ initializes the Trace2 facility. This includes setting up the
+ Trace2 thread local storage (TLS).
+
This function emits a "version" message containing the version of git
and the Trace2 protocol.
+
This function should be called from `main()` as early as possible in
- the life of the process.
+ the life of the process after essential process initialization.
`int trace2_is_enabled()`::
Emits a "def_param" messages for "important" configuration
settings.
+
- The environment variable `GIT_TR2_CONFIG_PARAMS` can be set to a
+ The environment variable `GIT_TR2_CONFIG_PARAMS` or the `trace2.configParams`
+ config value can be set to a
list of patterns of important configuration settings, for example:
`core.*,remote.*.url`. This function will iterate over all config
settings and emit a "def_param" message for each match.
`void trace2_cmd_set_config(const char *key, const char *value)`::
- Emits a "def_param" message for a specific configuration
- setting IFF it matches the `GIT_TR2_CONFIG_PARAMS` pattern.
+ Emits a "def_param" message for a new or updated key/value
+ pair IF `key` is considered important.
+
This is used to hook into `git_config_set()` and catch any
configuration changes and update a value previously reported by
=== NORMAL Format
- NORMAL format is enabled when the `GIT_TR2` environment variable is
- set.
-
Events are written as lines of the form:
------------
Note that this may contain embedded LF or CRLF characters that are
not escaped, so the event may spill across multiple lines.
- If `GIT_TR2_BRIEF` is true, the `time`, `filename`, and `line` fields
- are omitted.
+ If `GIT_TR2_BRIEF` or `trace2.normalBrief` is true, the `time`, `filename`,
+ and `line` fields are omitted.
This target is intended to be more of a summary (like GIT_TRACE) and
less detailed than the other targets. It ignores thread, region, and
=== PERF Format
- PERF format is enabled when the `GIT_TR2_PERF` environment variable
- is set.
-
Events are written as lines of the form:
------------
15:33:33.532712 wt-status.c:2331 | d0 | main | region_leave | r1 | 0.127568 | 0.001504 | status | label:print
------------
- If `GIT_TR2_PERF_BRIEF` is true, the `time`, `file`, and `line`
- fields are omitted.
+ If `GIT_TR2_PERF_BRIEF` or `trace2.perfBrief` is true, the `time`, `file`,
+ and `line` fields are omitted.
------------
d0 | main | region_leave | r1 | 0.011717 | 0.009122 | index | label:preload
=== EVENT Format
- EVENT format is enabled when the `GIT_TR2_EVENT` environment
- variable is set.
-
Each event is a JSON-object containing multiple key/value pairs
written as a single line and followed by a LF.
------------
{
"event":"version",
- "sid":"1547659722619736-11614",
+ "sid":"20190408T191827.272759Z-H9b68c35f-P00003510",
"thread":"main",
- "time":"2019-01-16 17:28:42.620713",
+ "time":"2019-04-08T19:18:27.282761Z",
"file":"common-main.c",
- "line":38,
+ "line":42,
...
}
------------
`"repo":<repo-id>`::
when present, is the integer repo-id as described previously.
- If `GIT_TR2_EVENT_BRIEF` is true, the `file` and `line` fields are omitted
- from all events and the `time` field is only present on the "start" and
- "atexit" events.
+ If `GIT_TR2_EVENT_BRIEF` or `trace2.eventBrief` is true, the `file`
+ and `line` fields are omitted from all events and the `time` field is
+ only present on the "start" and "atexit" events.
==== Event-Specific Key/Value Pairs
{
"event":"start",
...
+ "t_abs":0.001227, # elapsed time in seconds
"argv":["git","version"]
}
------------
The `category` field may be used in a future enhancement to
do category-based filtering.
+
- The `GIT_TR2_EVENT_NESTING` environment variable can be used to
+ `GIT_TR2_EVENT_NESTING` or `trace2.eventNesting` can be used to
filter deeply nested regions and data events. It defaults to "2".
`"region_leave"`::
$ cat ~/log.perf
d0 | main | version | | | | | 2.20.1.160.g5676107ecd.dirty
- d0 | main | start | | | | | git status
+ d0 | main | start | | 0.001173 | | | git status
d0 | main | def_repo | r1 | | | | worktree:/Users/jeffhost/work/gfw
d0 | main | cmd_name | | | | | status (status)
...
...
$ cat ~/log.perf
d0 | main | version | | | | | 2.20.1.162.gb4ccea44db.dirty
- d0 | main | start | | | | | git status
+ d0 | main | start | | 0.001173 | | | git status
d0 | main | def_repo | r1 | | | | worktree:/Users/jeffhost/work/gfw
d0 | main | cmd_name | | | | | status (status)
...
...
$ cat ~/log.perf
d0 | main | version | | | | | 2.20.1.156.gf9916ae094.dirty
- d0 | main | start | | | | | git status
+ d0 | main | start | | 0.001173 | | | git status
d0 | main | def_repo | r1 | | | | worktree:/Users/jeffhost/work/gfw
d0 | main | cmd_name | | | | | status (status)
d0 | main | region_enter | r1 | 0.001791 | | index | label:do_read_index .git/index
LIB_OBJS =
PROGRAM_OBJS =
PROGRAMS =
+EXCLUDED_PROGRAMS =
SCRIPT_PERL =
SCRIPT_PYTHON =
SCRIPT_SH =
SCRIPT_SH += git-merge-resolve.sh
SCRIPT_SH += git-mergetool.sh
SCRIPT_SH += git-quiltimport.sh
-SCRIPT_SH += git-legacy-rebase.sh
-SCRIPT_SH += git-remote-testgit.sh
+SCRIPT_SH += git-legacy-stash.sh
SCRIPT_SH += git-request-pull.sh
-SCRIPT_SH += git-stash.sh
SCRIPT_SH += git-submodule.sh
SCRIPT_SH += git-web--browse.sh
SCRIPT_PYTHON += git-p4.py
-NO_INSTALL += git-remote-testgit
-
# Generated files for scripts
SCRIPT_SH_GEN = $(patsubst %.sh,%,$(SCRIPT_SH))
SCRIPT_PERL_GEN = $(patsubst %.perl,%,$(SCRIPT_PERL))
SCRIPT_PYTHON_GEN = $(patsubst %.py,%,$(SCRIPT_PYTHON))
-SCRIPT_SH_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_SH_GEN))
-SCRIPT_PERL_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PERL_GEN))
-SCRIPT_PYTHON_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PYTHON_GEN))
-
# Individual rules to allow e.g.
# "make -C ../.. SCRIPT_PERL=contrib/foo/bar.perl build-perl-script"
# from subdirectories like contrib/*/
build-python-script: $(SCRIPT_PYTHON_GEN)
.PHONY: install-perl-script install-sh-script install-python-script
-install-sh-script: $(SCRIPT_SH_INS)
+install-sh-script: $(SCRIPT_SH_GEN)
$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
-install-perl-script: $(SCRIPT_PERL_INS)
+install-perl-script: $(SCRIPT_PERL_GEN)
$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
-install-python-script: $(SCRIPT_PYTHON_INS)
+install-python-script: $(SCRIPT_PYTHON_GEN)
$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
.PHONY: clean-perl-script clean-sh-script clean-python-script
clean-python-script:
$(RM) $(SCRIPT_PYTHON_GEN)
-SCRIPTS = $(SCRIPT_SH_INS) \
- $(SCRIPT_PERL_INS) \
- $(SCRIPT_PYTHON_INS) \
+SCRIPTS = $(SCRIPT_SH_GEN) \
+ $(SCRIPT_PERL_GEN) \
+ $(SCRIPT_PYTHON_GEN) \
git-instaweb
ETAGS_TARGET = TAGS
TEST_BUILTINS_OBJS += test-revision-walking.o
TEST_BUILTINS_OBJS += test-run-command.o
TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
+TEST_BUILTINS_OBJS += test-serve-v2.o
TEST_BUILTINS_OBJS += test-sha1.o
TEST_BUILTINS_OBJS += test-sha1-array.o
TEST_BUILTINS_OBJS += test-sha256.o
LIB_OBJS += trace2/tr2_cmd_name.o
LIB_OBJS += trace2/tr2_dst.o
LIB_OBJS += trace2/tr2_sid.o
+ LIB_OBJS += trace2/tr2_sysenv.o
LIB_OBJS += trace2/tr2_tbuf.o
LIB_OBJS += trace2/tr2_tgt_event.o
LIB_OBJS += trace2/tr2_tgt_normal.o
BUILTIN_OBJS += builtin/revert.o
BUILTIN_OBJS += builtin/rm.o
BUILTIN_OBJS += builtin/send-pack.o
-BUILTIN_OBJS += builtin/serve.o
BUILTIN_OBJS += builtin/shortlog.o
BUILTIN_OBJS += builtin/show-branch.o
BUILTIN_OBJS += builtin/show-index.o
BUILTIN_OBJS += builtin/show-ref.o
+BUILTIN_OBJS += builtin/stash.o
BUILTIN_OBJS += builtin/stripspace.o
BUILTIN_OBJS += builtin/submodule--helper.o
BUILTIN_OBJS += builtin/symbolic-ref.o
BASIC_CFLAGS += -fno-omit-frame-pointer
ifneq ($(filter undefined,$(SANITIZERS)),)
BASIC_CFLAGS += -DNO_UNALIGNED_LOADS
+BASIC_CFLAGS += -DSHA1DC_FORCE_ALIGNED_ACCESS
endif
ifneq ($(filter leak,$(SANITIZERS)),)
BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
REMOTE_CURL_PRIMARY =
REMOTE_CURL_ALIASES =
REMOTE_CURL_NAMES =
+ EXCLUDED_PROGRAMS += git-http-fetch git-http-push
else
ifdef CURLDIR
# Try "-Wl,-rpath=$(CURLDIR)/$(lib)" in such a case.
ifeq "$(curl_check)" "070908"
ifndef NO_EXPAT
PROGRAM_OBJS += http-push.o
+ else
+ EXCLUDED_PROGRAMS += git-http-push
endif
+ else
+ EXCLUDED_PROGRAMS += git-http-push
endif
curl_check := $(shell (echo 072200; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "072200"
endif
ifdef NO_UNIX_SOCKETS
BASIC_CFLAGS += -DNO_UNIX_SOCKETS
+ EXCLUDED_PROGRAMS += git-credential-cache git-credential-cache--daemon
else
LIB_OBJS += unix-socket.o
PROGRAM_OBJS += credential-cache.o
command-list.h: generate-cmdlist.sh command-list.txt
command-list.h: $(wildcard Documentation/git*.txt) Documentation/*config.txt Documentation/config/*.txt
- $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
+ $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \
+ $(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
+ command-list.txt >$@+ && mv $@+ $@
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
export DEFAULT_EDITOR DEFAULT_PAGER
+Documentation/GIT-EXCLUDED-PROGRAMS: FORCE
+ @EXCLUDED='EXCLUDED_PROGRAMS := $(EXCLUDED_PROGRAMS)'; \
+ if test x"$$EXCLUDED" != \
+ x"`cat Documentation/GIT-EXCLUDED-PROGRAMS 2>/dev/null`" ; then \
+ echo >&2 " * new documentation flags"; \
+ echo "$$EXCLUDED" >Documentation/GIT-EXCLUDED-PROGRAMS; \
+ fi
+
.PHONY: doc man man-perl html info pdf
doc: man-perl
$(MAKE) -C Documentation all
test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
all:: $(TEST_PROGRAMS) $(test_bindir_programs)
-all:: $(NO_INSTALL)
bin-wrappers/%: wrap-for-bin.sh
@mkdir -p bin-wrappers
artifacts-tar:: $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) \
GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
- $(NO_INSTALL) $(MOFILES)
+ $(MOFILES)
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \
SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
test -n "$(ARTIFACTS_DIRECTORY)"
$(RM) $(OBJECTS)
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
- $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
+ $(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS)
$(RM) -r bin-wrappers $(dep_dirs)
$(RM) -r po/build/
$(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
$(RM) $(htmldocs).tar.gz $(manpages).tar.gz
$(MAKE) -C Documentation/ clean
+ $(RM) Documentation/GIT-EXCLUDED-PROGRAMS
ifndef NO_PERL
$(MAKE) -C gitweb clean
$(RM) -r perl/build/
.PHONY: check-docs
check-docs::
$(MAKE) -C Documentation lint-docs
- @(for v in $(ALL_COMMANDS); \
+ @(for v in $(patsubst %$X,%,$(ALL_COMMANDS)); \
do \
case "$$v" in \
git-merge-octopus | git-merge-ours | git-merge-recursive | \
git-merge-resolve | git-merge-subtree | \
git-fsck-objects | git-init-db | \
- git-remote-* | git-stage | \
+ git-remote-* | git-stage | git-legacy-* | \
git-?*--?* ) continue ;; \
esac ; \
test -f "Documentation/$$v.txt" || \
( \
sed -e '1,/^### command list/d' \
-e '/^#/d' \
+ -e '/guide$$/d' \
-e 's/[ ].*//' \
-e 's/^/listed /' command-list.txt; \
$(MAKE) -C Documentation print-man1 | \
grep '\.txt$$' | \
- sed -e 's|Documentation/|documented |' \
+ sed -e 's|^|documented |' \
-e 's/\.txt//'; \
) | while read how cmd; \
do \
- case " $(ALL_COMMANDS) " in \
+ case " $(patsubst %$X,%,$(ALL_COMMANDS) $(EXCLUDED_PROGRAMS)) " in \
*" $$cmd "*) ;; \
*) echo "removed but $$how: $$cmd" ;; \
esac; \
}
ret = !wildmatch(pattern.buf + prefix, text.buf + prefix,
- icase ? WM_CASEFOLD : 0);
+ WM_PATHNAME | (icase ? WM_CASEFOLD : 0));
if (!ret && !already_tried_absolute) {
/*
repo_config = NULL;
current_parsing_scope = CONFIG_SCOPE_SYSTEM;
- if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0))
+ if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK,
+ opts->system_gently ?
+ ACCESS_EACCES_OK : 0))
ret += git_config_from_file(fn, git_etc_gitconfig(),
data);
ret += git_config_from_file(fn, user_config, data);
current_parsing_scope = CONFIG_SCOPE_REPO;
- if (repo_config && !access_or_die(repo_config, R_OK, 0))
+ if (!opts->ignore_repo && repo_config &&
+ !access_or_die(repo_config, R_OK, 0))
ret += git_config_from_file(fn, repo_config, data);
/*
* Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
* But let's not complicate things before it's actually needed.
*/
- if (repository_format_worktree_config) {
+ if (!opts->ignore_worktree && repository_format_worktree_config) {
char *path = git_pathdup("config.worktree");
if (!access_or_die(path, R_OK, 0))
ret += git_config_from_file(fn, path, data);
}
current_parsing_scope = CONFIG_SCOPE_CMDLINE;
- if (git_config_from_parameters(fn, data) < 0)
+ if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
die(_("unable to parse command-line config"));
current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
strbuf_release(&gitdir);
}
+ /*
+ * Read config but only enumerate system and global settings.
+ * Omit any repo-local, worktree-local, or command-line settings.
+ */
+ void read_very_early_config(config_fn_t cb, void *data)
+ {
+ struct config_options opts = { 0 };
+
+ opts.respect_includes = 1;
+ opts.ignore_repo = 1;
+ opts.ignore_worktree = 1;
+ opts.ignore_cmdline = 1;
+ opts.system_gently = 1;
+
+ config_with_options(cb, data, NULL, &opts);
+ }
+
static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
{
struct config_set_element k;
/* Functions use to read configuration from a repository */
static void repo_read_config(struct repository *repo)
{
- struct config_options opts;
+ struct config_options opts = { 0 };
opts.respect_includes = 1;
opts.commondir = repo->commondir;
test_description='test trace2 facility (normal target)'
. ./test-lib.sh
+ # Turn off any inherited trace2 settings for this test.
+ sane_unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+ sane_unset GIT_TR2_BRIEF
+ sane_unset GIT_TR2_CONFIG_PARAMS
+
# Add t/helper directory to PATH so that we can use a relative
# path to run nested instances of test-tool.exe (see 004child).
# This helps with HEREDOC comparisons later.
# Warning: So you may see extra lines in artifact files when
# Warning: interactively debugging.
- # Turn off any inherited trace2 settings for this test.
- unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
- unset GIT_TR2_BRIEF
- unset GIT_TR2_CONFIG_PARAMS
-
V=$(git version | sed -e 's/^git version //') && export V
# There are multiple trace2 targets: normal, perf, and event.
test_cmp expect actual
'
+test_expect_success 'automatic filename' '
+ test_when_finished "rm -r traces actual expect" &&
+ mkdir traces &&
+ GIT_TR2="$(pwd)/traces" test-tool trace2 001return 0 &&
+ perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/*)" >actual &&
+ cat >expect <<-EOF &&
+ version $V
+ start _EXE_ trace2 001return 0
+ cmd_name trace2 (trace2)
+ exit elapsed:_TIME_ code:0
+ atexit elapsed:_TIME_ code:0
+ EOF
+ test_cmp expect actual
+'
+
# Verb 002exit
#
# Explicit exit(code) from within cmd_<verb> propagates <code>.
test_cmp expect actual
'
+ sane_unset GIT_TR2_BRIEF
+
+ # Now test without environment variables and get all Trace2 settings
+ # from the global config.
+
+ test_expect_success 'using global config, normal stream, return code 0' '
+ test_when_finished "rm trace.normal actual expect" &&
+ test_config_global trace2.normalBrief 1 &&
+ test_config_global trace2.normalTarget "$(pwd)/trace.normal" &&
+ test-tool trace2 001return 0 &&
+ perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+ cat >expect <<-EOF &&
+ version $V
+ start _EXE_ trace2 001return 0
+ cmd_name trace2 (trace2)
+ exit elapsed:_TIME_ code:0
+ atexit elapsed:_TIME_ code:0
+ EOF
+ test_cmp expect actual
+ '
+
+ test_expect_success 'using global config with include' '
+ test_when_finished "rm trace.normal actual expect real.gitconfig" &&
+ test_config_global trace2.normalBrief 1 &&
+ test_config_global trace2.normalTarget "$(pwd)/trace.normal" &&
+ mv "$(pwd)/.gitconfig" "$(pwd)/real.gitconfig" &&
+ test_config_global include.path "$(pwd)/real.gitconfig" &&
+ test-tool trace2 001return 0 &&
+ perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+ cat >expect <<-EOF &&
+ version $V
+ start _EXE_ trace2 001return 0
+ cmd_name trace2 (trace2)
+ exit elapsed:_TIME_ code:0
+ atexit elapsed:_TIME_ code:0
+ EOF
+ test_cmp expect actual
+ '
+
test_done
#include "trace2/tr2_cmd_name.h"
#include "trace2/tr2_dst.h"
#include "trace2/tr2_sid.h"
+ #include "trace2/tr2_sysenv.h"
#include "trace2/tr2_tgt.h"
#include "trace2/tr2_tls.h"
tr2_sid_release();
tr2_cmd_name_release();
tr2_cfg_free_patterns();
+ tr2_sysenv_release();
trace2_enabled = 0;
}
raise(signo);
}
+ void trace2_initialize_clock(void)
+ {
+ tr2tls_start_process_clock();
+ }
+
void trace2_initialize_fl(const char *file, int line)
{
struct tr2_tgt *tgt_j;
if (trace2_enabled)
return;
+ tr2_sysenv_load();
+
if (!tr2_tgt_want_builtins())
return;
trace2_enabled = 1;
{
struct tr2_tgt *tgt_j;
int j;
+ uint64_t us_now;
+ uint64_t us_elapsed_absolute;
if (!trace2_enabled)
return;
+ us_now = getnanotime() / 1000;
+ us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
+
for_each_wanted_builtin (j, tgt_j)
if (tgt_j->pfn_start_fl)
- tgt_j->pfn_start_fl(file, line, argv);
+ tgt_j->pfn_start_fl(file, line, us_elapsed_absolute,
+ argv);
}
int trace2_cmd_exit_fl(const char *file, int line, int code)
if (!trace2_enabled)
return code;
+ trace2_collect_process_info(TRACE2_PROCESS_INFO_EXIT);
+
tr2main_exit_code = code;
us_now = getnanotime() / 1000;
us_now = getnanotime() / 1000;
us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
- tr2tls_create_self(thread_name);
+ tr2tls_create_self(thread_name, us_now);
for_each_wanted_builtin (j, tgt_j)
if (tgt_j->pfn_thread_start_fl)
}
void trace2_region_enter_fl(const char *file, int line, const char *category,
- const char *label, const struct repository *repo)
+ const char *label, const struct repository *repo, ...)
{
+ va_list ap;
+ va_start(ap, repo);
trace2_region_enter_printf_va_fl(file, line, category, label, repo,
- NULL, NULL);
+ NULL, ap);
+ va_end(ap);
+
}
void trace2_region_enter_printf_fl(const char *file, int line,
}
void trace2_region_leave_fl(const char *file, int line, const char *category,
- const char *label, const struct repository *repo)
+ const char *label, const struct repository *repo, ...)
{
+ va_list ap;
+ va_start(ap, repo);
trace2_region_leave_printf_va_fl(file, line, category, label, repo,
- NULL, NULL);
+ NULL, ap);
+ va_end(ap);
}
void trace2_region_leave_printf_fl(const char *file, int line,
* [] trace2_printf* -- legacy trace[1] messages.
*/
+ /*
+ * Initialize the TRACE2 clock and do nothing else, in particular
+ * no mallocs, no system inspection, and no environment inspection.
+ *
+ * This should be called at the very top of main() to capture the
+ * process start time. This is intended to reduce chicken-n-egg
+ * bootstrap pressure.
+ *
+ * It is safe to call this more than once. This allows capturing
+ * absolute startup costs on Windows which uses a little trickery
+ * to do setup work before common-main.c:main() is called.
+ *
+ * The main trace2_initialize_fl() may be called a little later
+ * after more infrastructure is established.
+ */
+ void trace2_initialize_clock(void);
+
/*
* Initialize TRACE2 tracing facility if any of the builtin TRACE2
- * targets are enabled in the environment. Emits a 'version' event.
+ * targets are enabled in the system config or the environment.
+ * Emits a 'version' event.
*
* Cleanup/Termination is handled automatically by a registered
* atexit() routine.
* Emit one or more 'def_param' events for "interesting" configuration
* settings.
*
- * The environment variable "GIT_TR2_CONFIG_PARAMS" can be set to a
- * list of patterns considered important. For example:
- *
- * 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
* on this thread.
*/
void trace2_region_enter_fl(const char *file, int line, const char *category,
- const char *label, const struct repository *repo);
+ const char *label, const struct repository *repo, ...);
#define trace2_region_enter(category, label, repo) \
trace2_region_enter_fl(__FILE__, __LINE__, (category), (label), (repo))
* in this nesting level.
*/
void trace2_region_leave_fl(const char *file, int line, const char *category,
- const char *label, const struct repository *repo);
+ const char *label, const struct repository *repo, ...);
#define trace2_region_leave(category, label, repo) \
trace2_region_leave_fl(__FILE__, __LINE__, (category), (label), (repo))
* Optional platform-specific code to dump information about the
* current and any parent process(es). This is intended to allow
* post-processors to know who spawned this git instance and anything
- * else the platform may be able to tell us about the current process.
+ * else that the platform may be able to tell us about the current process.
*/
+
+ enum trace2_process_info_reason {
+ TRACE2_PROCESS_INFO_STARTUP,
+ TRACE2_PROCESS_INFO_EXIT,
+ };
+
#if defined(GIT_WINDOWS_NATIVE)
- void trace2_collect_process_info(void);
+ void trace2_collect_process_info(enum trace2_process_info_reason reason);
#else
- #define trace2_collect_process_info() \
- do { \
+ #define trace2_collect_process_info(reason) \
+ do { \
} while (0)
#endif
#include "cache.h"
#include "trace2/tr2_dst.h"
-
- /*
- * If a Trace2 target cannot be opened for writing, we should issue a
- * warning to stderr, but this is very annoying if the target is a pipe
- * or socket and beyond the user's control -- especially since every
- * git command (and sub-command) will print the message. So we silently
- * eat these warnings and just discard the trace data.
- *
- * Enable the following environment variable to see these warnings.
- */
- #define TR2_ENVVAR_DST_DEBUG "GIT_TR2_DST_DEBUG"
+#include "trace2/tr2_sid.h"
+ #include "trace2/tr2_sysenv.h"
/*
- * If a Trace2 target cannot be opened for writing, we should issue a
- * warning to stderr, but this is very annoying if the target is a pipe
- * or socket and beyond the user's control -- especially since every
- * git command (and sub-command) will print the message. So we silently
- * eat these warnings and just discard the trace data.
+ * How many attempts we will make at creating an automatically-named trace file.
*/
+#define MAX_AUTO_ATTEMPTS 10
+
static int tr2_dst_want_warning(void)
{
static int tr2env_dst_debug = -1;
if (tr2env_dst_debug == -1) {
- const char *env_value = getenv(TR2_ENVVAR_DST_DEBUG);
+ const char *env_value = tr2_sysenv_get(TR2_SYSENV_DST_DEBUG);
if (!env_value || !*env_value)
tr2env_dst_debug = 0;
else
dst->need_close = 0;
}
- dst->env_var_name, strerror(errno));
+static int tr2_dst_try_auto_path(struct tr2_dst *dst, const char *tgt_prefix)
+{
+ int fd;
+ const char *last_slash, *sid = tr2_sid_get();
+ struct strbuf path = STRBUF_INIT;
+ size_t base_path_len;
+ unsigned attempt_count;
+
+ last_slash = strrchr(sid, '/');
+ if (last_slash)
+ sid = last_slash + 1;
+
+ strbuf_addstr(&path, tgt_prefix);
+ if (!is_dir_sep(path.buf[path.len - 1]))
+ strbuf_addch(&path, '/');
+ strbuf_addstr(&path, sid);
+ base_path_len = path.len;
+
+ for (attempt_count = 0; attempt_count < MAX_AUTO_ATTEMPTS; attempt_count++) {
+ if (attempt_count > 0) {
+ strbuf_setlen(&path, base_path_len);
+ strbuf_addf(&path, ".%d", attempt_count);
+ }
+
+ fd = open(path.buf, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ if (fd != -1)
+ break;
+ }
+
+ if (fd == -1) {
+ if (tr2_dst_want_warning())
+ warning("trace2: could not open '%.*s' for '%s' tracing: %s",
+ (int) base_path_len, path.buf,
++ tr2_sysenv_display_name(dst->sysenv_var),
++ strerror(errno));
+
+ tr2_dst_trace_disable(dst);
+ strbuf_release(&path);
+ return 0;
+ }
+
+ strbuf_release(&path);
+
+ dst->fd = fd;
+ dst->need_close = 1;
+ dst->initialized = 1;
+
+ return dst->fd;
+}
+
static int tr2_dst_try_path(struct tr2_dst *dst, const char *tgt_value)
{
int fd = open(tgt_value, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd == -1) {
if (tr2_dst_want_warning())
warning("trace2: could not open '%s' for '%s' tracing: %s",
- tgt_value, dst->env_var_name, strerror(errno));
+ tgt_value,
+ tr2_sysenv_display_name(dst->sysenv_var),
+ strerror(errno));
tr2_dst_trace_disable(dst);
return 0;
if (!path || !*path) {
if (tr2_dst_want_warning())
warning("trace2: invalid AF_UNIX value '%s' for '%s' tracing",
- tgt_value, dst->env_var_name);
+ tgt_value,
+ tr2_sysenv_display_name(dst->sysenv_var));
tr2_dst_trace_disable(dst);
return 0;
strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
if (tr2_dst_want_warning())
warning("trace2: invalid AF_UNIX path '%s' for '%s' tracing",
- path, dst->env_var_name);
+ path, tr2_sysenv_display_name(dst->sysenv_var));
tr2_dst_trace_disable(dst);
return 0;
error:
if (tr2_dst_want_warning())
warning("trace2: could not connect to socket '%s' for '%s' tracing: %s",
- path, dst->env_var_name, strerror(e));
+ path, tr2_sysenv_display_name(dst->sysenv_var),
+ strerror(e));
tr2_dst_trace_disable(dst);
return 0;
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "trace2: unknown value for '%s': '%s'",
- dst->env_var_name, tgt_value);
+ tr2_sysenv_display_name(dst->sysenv_var), tgt_value);
warning("%s", buf.buf);
strbuf_release(&buf);
dst->initialized = 1;
- tgt_value = getenv(dst->env_var_name);
+ tgt_value = tr2_sysenv_get(dst->sysenv_var);
if (!tgt_value || !strcmp(tgt_value, "") || !strcmp(tgt_value, "0") ||
!strcasecmp(tgt_value, "false")) {
return dst->fd;
}
- if (is_absolute_path(tgt_value))
- return tr2_dst_try_path(dst, tgt_value);
+ if (is_absolute_path(tgt_value)) {
+ if (is_directory(tgt_value))
+ return tr2_dst_try_auto_path(dst, tgt_value);
+ else
+ return tr2_dst_try_path(dst, tgt_value);
+ }
#ifndef NO_UNIX_SOCKETS
if (starts_with(tgt_value, PREFIX_AF_UNIX))
return;
if (tr2_dst_want_warning())
- warning("unable to write trace to '%s': %s", dst->env_var_name,
+ warning("unable to write trace to '%s': %s",
+ tr2_sysenv_display_name(dst->sysenv_var),
strerror(errno));
tr2_dst_trace_disable(dst);
}
#include "trace2/tr2_dst.h"
#include "trace2/tr2_tbuf.h"
#include "trace2/tr2_sid.h"
+ #include "trace2/tr2_sysenv.h"
#include "trace2/tr2_tgt.h"
#include "trace2/tr2_tls.h"
- static struct tr2_dst tr2dst_event = { "GIT_TR2_EVENT", 0, 0, 0 };
+ static struct tr2_dst tr2dst_event = { TR2_SYSENV_EVENT, 0, 0, 0 };
/*
* The version number of the JSON data generated by the EVENT target
* are primarily intended for the performance target during debugging.
*
* Some of the outer-most messages, however, may be of interest to the
- * event target. Set this environment variable to a larger integer for
- * more detail in the event target.
+ * event target. Use the TR2_SYSENV_EVENT_NESTING setting to increase
+ * 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_max_nesting_levels = 2;
/*
- * Set this environment variable to true to omit the <time>, <file>, and
+ * Use the TR2_SYSENV_EVENT_BRIEF to omit the <time>, <file>, and
* <line> fields from most events.
*/
- #define TR2_ENVVAR_EVENT_BRIEF "GIT_TR2_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 max_nesting;
int want_brief;
- char *nesting;
- char *brief;
+ const char *nesting;
+ const char *brief;
if (!want)
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 && *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 && *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);
+ tr2_tbuf_utc_datetime_extended(&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);
}
jw_release(&jw);
}
- static void fn_start_fl(const char *file, int line, const char **argv)
+ static void fn_start_fl(const char *file, int line,
+ uint64_t us_elapsed_absolute, const char **argv)
{
const char *event_name = "start";
struct json_writer jw = JSON_WRITER_INIT;
+ double t_abs = (double)us_elapsed_absolute / 1000000.0;
jw_object_begin(&jw, 0);
event_fmt_prepare(event_name, file, line, NULL, &jw);
+ jw_object_double(&jw, "t_abs", 6, t_abs);
jw_object_inline_begin_array(&jw, "argv");
jw_array_argv(&jw, argv);
jw_end(&jw);
static void maybe_add_string_va(struct json_writer *jw, const char *field_name,
const char *fmt, va_list ap)
{
- if (fmt && *fmt && ap) {
+ if (fmt && *fmt) {
va_list copy_ap;
struct strbuf buf = STRBUF_INIT;
{
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;
#include "quote.h"
#include "version.h"
#include "trace2/tr2_dst.h"
+ #include "trace2/tr2_sysenv.h"
#include "trace2/tr2_tbuf.h"
#include "trace2/tr2_tgt.h"
#include "trace2/tr2_tls.h"
- static struct tr2_dst tr2dst_normal = { "GIT_TR2", 0, 0, 0 };
+ static struct tr2_dst tr2dst_normal = { TR2_SYSENV_NORMAL, 0, 0, 0 };
/*
- * Set this environment variable to true to omit the "<time> <file>:<line>"
+ * Use the TR2_SYSENV_NORMAL_BRIEF setting to omit the "<time> <file>:<line>"
* fields from each line written to the builtin normal target.
*
* 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_be_brief;
#define TR2FMT_NORMAL_FL_WIDTH (50)
{
int want = tr2_dst_trace_want(&tr2dst_normal);
int want_brief;
- char *brief;
+ const char *brief;
if (!want)
return want;
- brief = getenv(TR2_ENVVAR_NORMAL_BRIEF);
+ 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_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);
strbuf_release(&buf_payload);
}
- static void fn_start_fl(const char *file, int line, const char **argv)
+ static void fn_start_fl(const char *file, int line,
+ uint64_t us_elapsed_absolute, const char **argv)
{
struct strbuf buf_payload = STRBUF_INIT;
static void maybe_append_string_va(struct strbuf *buf, const char *fmt,
va_list ap)
{
- if (fmt && *fmt && ap) {
+ if (fmt && *fmt) {
va_list copy_ap;
va_copy(copy_ap, ap);
#include "json-writer.h"
#include "trace2/tr2_dst.h"
#include "trace2/tr2_sid.h"
+ #include "trace2/tr2_sysenv.h"
#include "trace2/tr2_tbuf.h"
#include "trace2/tr2_tgt.h"
#include "trace2/tr2_tls.h"
- static struct tr2_dst tr2dst_perf = { "GIT_TR2_PERF", 0, 0, 0 };
+ static struct tr2_dst tr2dst_perf = { TR2_SYSENV_PERF, 0, 0, 0 };
/*
- * Set this environment variable to true to omit the "<time> <file>:<line>"
+ * Use TR2_SYSENV_PERF_BRIEF to omit the "<time> <file>:<line>"
* fields from each line written to the builtin performance target.
*
* 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_be_brief;
#define TR2FMT_PERF_FL_WIDTH (50)
#define TR2FMT_PERF_MAX_EVENT_NAME (12)
{
int want = tr2_dst_trace_want(&tr2dst_perf);
int want_brief;
- char *brief;
+ const char *brief;
if (!want)
return want;
strbuf_addchars(&dots, '.', TR2_DOTS_BUFFER_SIZE);
- brief = getenv(TR2_ENVVAR_PERF_BRIEF);
+ 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_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);
strbuf_release(&buf_payload);
}
- static void fn_start_fl(const char *file, int line, const char **argv)
+ static void fn_start_fl(const char *file, int line,
+ uint64_t us_elapsed_absolute, const char **argv)
{
const char *event_name = "start";
struct strbuf buf_payload = STRBUF_INIT;
sq_quote_argv_pretty(&buf_payload, argv);
- perf_io_write_fl(file, line, event_name, NULL, NULL, NULL, NULL,
- &buf_payload);
+ perf_io_write_fl(file, line, event_name, NULL, &us_elapsed_absolute,
+ NULL, NULL, &buf_payload);
strbuf_release(&buf_payload);
}
static void maybe_append_string_va(struct strbuf *buf, const char *fmt,
va_list ap)
{
- if (fmt && *fmt && ap) {
+ if (fmt && *fmt) {
va_list copy_ap;
va_copy(copy_ap, ap);