= Trace2 API The Trace2 API can be used to print debug, performance, and telemetry information to stderr or a file. The Trace2 feature is inactive unless explicitly enabled by enabling one or more Trace2 Targets. The Trace2 API is intended to replace the existing (Trace1) printf-style tracing provided by the existing `GIT_TRACE` and `GIT_TRACE_PERFORMANCE` facilities. During initial implementation, Trace2 and Trace1 may operate in parallel. The Trace2 API defines a set of high-level messages with known fields, such as (`start`: `argv`) and (`exit`: {`exit-code`, `elapsed-time`}). Trace2 instrumentation throughout the Git code base sends Trace2 messages to the enabled Trace2 Targets. Targets transform these messages content into purpose-specific formats and write events to their data streams. In this manner, the Trace2 API can drive many different types of analysis. Targets are defined using a VTable allowing easy extension to other 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_TRACE2*` 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. === 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_TRACE2` environment variable or the `trace2.normalTarget` system or global config setting. For example ------------ $ export GIT_TRACE2=~/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.620989 common-main.c:39 start git version 12:28:42.621101 git.c:432 cmd_name version (version) 12:28:42.621215 git.c:662 exit elapsed:0.001227 code:0 12:28:42.621250 trace2/tr2_tgt_normal.c:124 atexit elapsed:0.001265 code:0 ------------ === 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_TRACE2_PERF` environment variable or the `trace2.perfTarget` system or global config setting. For example ------------ $ export GIT_TRACE2_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 | | 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 ------------ === 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_TRACE2_EVENT` environment variable or the `trace2.eventTarget` system or global config setting. For example ------------ $ export GIT_TRACE2_EVENT=~/log.event $ git version git version 2.20.1.155.g426c96fcdb ------------ or ------------ $ git config --global trace2.eventTarget ~/log.event $ git version git version 2.20.1.155.g426c96fcdb ------------ yields ------------ $ 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} ------------ === Enabling a Target To enable a target, set the corresponding environment variable or system or global config value to one of the following: include::../trace2-target-values.txt[] 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 `trace2.c`. All public symbols are prefixed with `trace2_`. There are no public Trace2 data structures. The Trace2 code also defines a set of private functions and data types in the `trace2/` directory. These symbols are prefixed with `tr2_` and should only be used by functions in `trace2.c`. == Conventions for Public Functions and Macros The functions defined by the Trace2 API are declared and documented in `trace2.h`. It defines the API functions and wrapper macros for Trace2. Some functions have a `_fl()` suffix to indicate that they take `file` and `line-number` arguments. Some functions have a `_va_fl()` suffix to indicate that they also take a `va_list` argument. Some functions have a `_printf_fl()` suffix to indicate that they also take a varargs argument. There are CPP wrapper macros and ifdefs to hide most of these details. See `trace2.h` for more details. The following discussion will only describe the simplified forms. == Public API All Trace2 API functions send a messsage to all of the active Trace2 Targets. This section describes the set of available messages. It helps to divide these functions into groups for discussion purposes. === Basic Command Messages 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 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 after essential process initialization. `int trace2_is_enabled()`:: Returns 1 if Trace2 is enabled (at least one target is active). `void trace2_cmd_start(int argc, const char **argv)`:: Emits a "start" message containing the process command line arguments. `int trace2_cmd_exit(int exit_code)`:: Emits an "exit" message containing the process exit-code and elapsed time. + Returns the exit-code. `void trace2_cmd_error(const char *fmt, va_list ap)`:: Emits an "error" message containing a formatted error message. `void trace2_cmd_path(const char *pathname)`:: Emits a "cmd_path" message with the full pathname of the current process. === Command Detail Messages These are concerned with describing the specific Git command after the command line, config, and environment are inspected. `void trace2_cmd_name(const char *name)`:: Emits a "cmd_name" message with the canonical name of the command, for example "status" or "checkout". `void trace2_cmd_mode(const char *mode)`:: Emits a "cmd_mode" message with a qualifier name to further describe the current git command. + This message is intended to be used with git commands having multiple major modes. For example, a "checkout" command can checkout a new branch or it can checkout a single file, so the checkout code could emit a cmd_mode message of "branch" or "file". `void trace2_cmd_alias(const char *alias, const char **argv_expansion)`:: Emits an "alias" message containing the alias used and the argument expansion. `void trace2_def_param(const char *parameter, const char *value)`:: Emits a "def_param" message containing a key/value pair. + This message is intended to report some global aspect of the current command, such as a configuration setting or command line switch that significantly affects program performance or behavior, such as `core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`. `void trace2_cmd_list_config()`:: Emits a "def_param" messages for "important" configuration settings. + The environment variable `GIT_TRACE2_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 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 `trace2_cmd_list_config()`. `void trace2_def_repo(struct repository *repo)`:: Registers a repository with the Trace2 layer. Assigns a unique "repo-id" to `repo->trace2_repo_id`. + Emits a "worktree" messages containing the repo-id and the worktree pathname. + Region and data messages (described later) may refer to this repo-id. + The main/top-level repository will have repo-id value 1 (aka "r1"). + The repo-id field is in anticipation of future in-proc submodule repositories. === Child Process Messages These are concerned with the various spawned child processes, including shell scripts, git commands, editors, pagers, and hooks. `void trace2_child_start(struct child_process *cmd)`:: Emits a "child_start" message containing the "child-id", "child-argv", and "child-classification". + Before calling this, set `cmd->trace2_child_class` to a name describing the type of child process, for example "editor". + This function assigns a unique "child-id" to `cmd->trace2_child_id`. This field is used later during the "child_exit" message to associate it with the "child_start" message. + This function should be called before spawning the child process. `void trace2_child_exit(struct child_proess *cmd, int child_exit_code)`:: Emits a "child_exit" message containing the "child-id", the child's elapsed time and exit-code. + The reported elapsed time includes the process creation overhead and time spend waiting for it to exit, so it may be slightly longer than the time reported by the child itself. + This function should be called after reaping the child process. `int trace2_exec(const char *exe, const char **argv)`:: Emits a "exec" message containing the "exec-id" and the argv of the new process. + This function should be called before calling one of the `exec()` variants, such as `execvp()`. + This function returns a unique "exec-id". This value is used later if the exec() fails and a "exec-result" message is necessary. `void trace2_exec_result(int exec_id, int error_code)`:: Emits a "exec_result" message containing the "exec-id" and the error code. + On Unix-based systems, `exec()` does not return if successful. This message is used to indicate that the `exec()` failed and that the current program is continuing. === Git Thread Messages These messages are concerned with Git thread usage. `void trace2_thread_start(const char *thread_name)`:: Emits a "thread_start" message. + The `thread_name` field should be a descriptive name, such as the unique name of the thread-proc. A unique "thread-id" will be added to the name to uniquely identify thread instances. + Region and data messages (described later) may refer to this thread name. + This function must be called by the thread-proc of the new thread (so that TLS data is properly initialized) and not by the caller of `pthread_create()`. `void trace2_thread_exit()`:: Emits a "thread_exit" message containing the thread name and the thread elapsed time. + This function must be called by the thread-proc before it returns (so that the coorect TLS data is used and cleaned up. It should not be called by the caller of `pthread_join()`. === Region and Data Messages These are concerned with recording performance data over regions or spans of code. `void trace2_region_enter(const char *category, const char *label, const struct repository *repo)`:: `void trace2_region_enter_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`:: `void trace2_region_enter_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`:: Emits a thread-relative "region_enter" message with optional printf string. + This function pushes a new region nesting stack level on the current thread and starts a clock for the new stack frame. + The `category` field is an arbitrary category name used to classify regions by feature area, such as "status" or "index". At this time it is only just printed along with the rest of the message. It may be used in the future to filter messages. + The `label` field is an arbitrary label used to describe the activity being started, such as "read_recursive" or "do_read_index". + The `repo` field, if set, will be used to get the "repo-id", so that recursive oerations can be attributed to the correct repository. `void trace2_region_leave(const char *category, const char *label, const struct repository *repo)`:: `void trace2_region_leave_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`:: `void trace2_region_leave_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`:: Emits a thread-relative "region_leave" message with optional printf string. + This function pops the region nesting stack on the current thread and reports the elapsed time of the stack frame. + The `category`, `label`, and `repo` fields are the same as above. The `category` and `label` do not need to match the correpsonding "region_enter" message, but it makes the data stream easier to understand. `void trace2_data_string(const char *category, const struct repository *repo, const char *key, const char * value)`:: `void trace2_data_intmax(const char *category, const struct repository *repo, const char *key, intmax value)`:: `void trace2_data_json(const char *category, const struct repository *repo, const char *key, const struct json_writer *jw)`:: Emits a region- and thread-relative "data" or "data_json" message. + This is a key/value pair message containing information about the current thread, region stack, and repository. This could be used to print the number of files in a directory during a multi-threaded recursive tree walk. `void trace2_printf(const char *fmt, ...)`:: `void trace2_printf_va(const char *fmt, va_list ap)`:: Emits a region- and thread-relative "printf" message. == Trace2 Target Formats === NORMAL Format Events are written as lines of the form: ------------ [