trace2 / tr2_tgt_normal.con commit trace2: write to directory targets (a4d3a28)
   1#include "cache.h"
   2#include "config.h"
   3#include "run-command.h"
   4#include "quote.h"
   5#include "version.h"
   6#include "trace2/tr2_dst.h"
   7#include "trace2/tr2_tbuf.h"
   8#include "trace2/tr2_tgt.h"
   9#include "trace2/tr2_tls.h"
  10
  11static struct tr2_dst tr2dst_normal = { "GIT_TR2", 0, 0, 0 };
  12
  13/*
  14 * Set this environment variable to true to omit the "<time> <file>:<line>"
  15 * fields from each line written to the builtin normal target.
  16 *
  17 * Unit tests may want to use this to help with testing.
  18 */
  19#define TR2_ENVVAR_NORMAL_BRIEF "GIT_TR2_BRIEF"
  20static int tr2env_normal_brief;
  21
  22#define TR2FMT_NORMAL_FL_WIDTH (50)
  23
  24static int fn_init(void)
  25{
  26        int want = tr2_dst_trace_want(&tr2dst_normal);
  27        int want_brief;
  28        char *brief;
  29
  30        if (!want)
  31                return want;
  32
  33        brief = getenv(TR2_ENVVAR_NORMAL_BRIEF);
  34        if (brief && *brief &&
  35            ((want_brief = git_parse_maybe_bool(brief)) != -1))
  36                tr2env_normal_brief = want_brief;
  37
  38        return want;
  39}
  40
  41static void fn_term(void)
  42{
  43        tr2_dst_trace_disable(&tr2dst_normal);
  44}
  45
  46static void normal_fmt_prepare(const char *file, int line, struct strbuf *buf)
  47{
  48        strbuf_setlen(buf, 0);
  49
  50        if (!tr2env_normal_brief) {
  51                struct tr2_tbuf tb_now;
  52
  53                tr2_tbuf_local_time(&tb_now);
  54                strbuf_addstr(buf, tb_now.buf);
  55                strbuf_addch(buf, ' ');
  56
  57                if (file && *file)
  58                        strbuf_addf(buf, "%s:%d ", file, line);
  59                while (buf->len < TR2FMT_NORMAL_FL_WIDTH)
  60                        strbuf_addch(buf, ' ');
  61        }
  62}
  63
  64static void normal_io_write_fl(const char *file, int line,
  65                               const struct strbuf *buf_payload)
  66{
  67        struct strbuf buf_line = STRBUF_INIT;
  68
  69        normal_fmt_prepare(file, line, &buf_line);
  70        strbuf_addbuf(&buf_line, buf_payload);
  71        tr2_dst_write_line(&tr2dst_normal, &buf_line);
  72        strbuf_release(&buf_line);
  73}
  74
  75static void fn_version_fl(const char *file, int line)
  76{
  77        struct strbuf buf_payload = STRBUF_INIT;
  78
  79        strbuf_addf(&buf_payload, "version %s", git_version_string);
  80        normal_io_write_fl(file, line, &buf_payload);
  81        strbuf_release(&buf_payload);
  82}
  83
  84static void fn_start_fl(const char *file, int line, const char **argv)
  85{
  86        struct strbuf buf_payload = STRBUF_INIT;
  87
  88        strbuf_addstr(&buf_payload, "start ");
  89        sq_quote_argv_pretty(&buf_payload, argv);
  90        normal_io_write_fl(file, line, &buf_payload);
  91        strbuf_release(&buf_payload);
  92}
  93
  94static void fn_exit_fl(const char *file, int line, uint64_t us_elapsed_absolute,
  95                       int code)
  96{
  97        struct strbuf buf_payload = STRBUF_INIT;
  98        double elapsed = (double)us_elapsed_absolute / 1000000.0;
  99
 100        strbuf_addf(&buf_payload, "exit elapsed:%.6f code:%d", elapsed, code);
 101        normal_io_write_fl(file, line, &buf_payload);
 102        strbuf_release(&buf_payload);
 103}
 104
 105static void fn_signal(uint64_t us_elapsed_absolute, int signo)
 106{
 107        struct strbuf buf_payload = STRBUF_INIT;
 108        double elapsed = (double)us_elapsed_absolute / 1000000.0;
 109
 110        strbuf_addf(&buf_payload, "signal elapsed:%.6f code:%d", elapsed,
 111                    signo);
 112        normal_io_write_fl(__FILE__, __LINE__, &buf_payload);
 113        strbuf_release(&buf_payload);
 114}
 115
 116static void fn_atexit(uint64_t us_elapsed_absolute, int code)
 117{
 118        struct strbuf buf_payload = STRBUF_INIT;
 119        double elapsed = (double)us_elapsed_absolute / 1000000.0;
 120
 121        strbuf_addf(&buf_payload, "atexit elapsed:%.6f code:%d", elapsed, code);
 122        normal_io_write_fl(__FILE__, __LINE__, &buf_payload);
 123        strbuf_release(&buf_payload);
 124}
 125
 126static void maybe_append_string_va(struct strbuf *buf, const char *fmt,
 127                                   va_list ap)
 128{
 129        if (fmt && *fmt && ap) {
 130                va_list copy_ap;
 131
 132                va_copy(copy_ap, ap);
 133                strbuf_vaddf(buf, fmt, copy_ap);
 134                va_end(copy_ap);
 135                return;
 136        }
 137
 138        if (fmt && *fmt) {
 139                strbuf_addstr(buf, fmt);
 140                return;
 141        }
 142}
 143
 144static void fn_error_va_fl(const char *file, int line, const char *fmt,
 145                           va_list ap)
 146{
 147        struct strbuf buf_payload = STRBUF_INIT;
 148
 149        strbuf_addstr(&buf_payload, "error ");
 150        maybe_append_string_va(&buf_payload, fmt, ap);
 151        normal_io_write_fl(file, line, &buf_payload);
 152        strbuf_release(&buf_payload);
 153}
 154
 155static void fn_command_path_fl(const char *file, int line, const char *pathname)
 156{
 157        struct strbuf buf_payload = STRBUF_INIT;
 158
 159        strbuf_addf(&buf_payload, "cmd_path %s", pathname);
 160        normal_io_write_fl(file, line, &buf_payload);
 161        strbuf_release(&buf_payload);
 162}
 163
 164static void fn_command_name_fl(const char *file, int line, const char *name,
 165                               const char *hierarchy)
 166{
 167        struct strbuf buf_payload = STRBUF_INIT;
 168
 169        strbuf_addf(&buf_payload, "cmd_name %s", name);
 170        if (hierarchy && *hierarchy)
 171                strbuf_addf(&buf_payload, " (%s)", hierarchy);
 172        normal_io_write_fl(file, line, &buf_payload);
 173        strbuf_release(&buf_payload);
 174}
 175
 176static void fn_command_mode_fl(const char *file, int line, const char *mode)
 177{
 178        struct strbuf buf_payload = STRBUF_INIT;
 179
 180        strbuf_addf(&buf_payload, "cmd_mode %s", mode);
 181        normal_io_write_fl(file, line, &buf_payload);
 182        strbuf_release(&buf_payload);
 183}
 184
 185static void fn_alias_fl(const char *file, int line, const char *alias,
 186                        const char **argv)
 187{
 188        struct strbuf buf_payload = STRBUF_INIT;
 189
 190        strbuf_addf(&buf_payload, "alias %s ->", alias);
 191        sq_quote_argv_pretty(&buf_payload, argv);
 192        normal_io_write_fl(file, line, &buf_payload);
 193        strbuf_release(&buf_payload);
 194}
 195
 196static void fn_child_start_fl(const char *file, int line,
 197                              uint64_t us_elapsed_absolute,
 198                              const struct child_process *cmd)
 199{
 200        struct strbuf buf_payload = STRBUF_INIT;
 201
 202        strbuf_addf(&buf_payload, "child_start[%d] ", cmd->trace2_child_id);
 203
 204        if (cmd->dir) {
 205                strbuf_addstr(&buf_payload, " cd");
 206                sq_quote_buf_pretty(&buf_payload, cmd->dir);
 207                strbuf_addstr(&buf_payload, "; ");
 208        }
 209
 210        /*
 211         * TODO if (cmd->env) { Consider dumping changes to environment. }
 212         * See trace_add_env() in run-command.c as used by original trace.c
 213         */
 214
 215        if (cmd->git_cmd)
 216                strbuf_addstr(&buf_payload, "git");
 217        sq_quote_argv_pretty(&buf_payload, cmd->argv);
 218
 219        normal_io_write_fl(file, line, &buf_payload);
 220        strbuf_release(&buf_payload);
 221}
 222
 223static void fn_child_exit_fl(const char *file, int line,
 224                             uint64_t us_elapsed_absolute, int cid, int pid,
 225                             int code, uint64_t us_elapsed_child)
 226{
 227        struct strbuf buf_payload = STRBUF_INIT;
 228        double elapsed = (double)us_elapsed_child / 1000000.0;
 229
 230        strbuf_addf(&buf_payload, "child_exit[%d] pid:%d code:%d elapsed:%.6f",
 231                    cid, pid, code, elapsed);
 232        normal_io_write_fl(file, line, &buf_payload);
 233        strbuf_release(&buf_payload);
 234}
 235
 236static void fn_exec_fl(const char *file, int line, uint64_t us_elapsed_absolute,
 237                       int exec_id, const char *exe, const char **argv)
 238{
 239        struct strbuf buf_payload = STRBUF_INIT;
 240
 241        strbuf_addf(&buf_payload, "exec[%d] ", exec_id);
 242        if (exe)
 243                strbuf_addstr(&buf_payload, exe);
 244        sq_quote_argv_pretty(&buf_payload, argv);
 245        normal_io_write_fl(file, line, &buf_payload);
 246        strbuf_release(&buf_payload);
 247}
 248
 249static void fn_exec_result_fl(const char *file, int line,
 250                              uint64_t us_elapsed_absolute, int exec_id,
 251                              int code)
 252{
 253        struct strbuf buf_payload = STRBUF_INIT;
 254
 255        strbuf_addf(&buf_payload, "exec_result[%d] code:%d", exec_id, code);
 256        if (code > 0)
 257                strbuf_addf(&buf_payload, " err:%s", strerror(code));
 258        normal_io_write_fl(file, line, &buf_payload);
 259        strbuf_release(&buf_payload);
 260}
 261
 262static void fn_param_fl(const char *file, int line, const char *param,
 263                        const char *value)
 264{
 265        struct strbuf buf_payload = STRBUF_INIT;
 266
 267        strbuf_addf(&buf_payload, "def_param %s=%s", param, value);
 268        normal_io_write_fl(file, line, &buf_payload);
 269        strbuf_release(&buf_payload);
 270}
 271
 272static void fn_repo_fl(const char *file, int line,
 273                       const struct repository *repo)
 274{
 275        struct strbuf buf_payload = STRBUF_INIT;
 276
 277        strbuf_addstr(&buf_payload, "worktree ");
 278        sq_quote_buf_pretty(&buf_payload, repo->worktree);
 279        normal_io_write_fl(file, line, &buf_payload);
 280        strbuf_release(&buf_payload);
 281}
 282
 283static void fn_printf_va_fl(const char *file, int line,
 284                            uint64_t us_elapsed_absolute, const char *fmt,
 285                            va_list ap)
 286{
 287        struct strbuf buf_payload = STRBUF_INIT;
 288
 289        maybe_append_string_va(&buf_payload, fmt, ap);
 290        normal_io_write_fl(file, line, &buf_payload);
 291        strbuf_release(&buf_payload);
 292}
 293
 294struct tr2_tgt tr2_tgt_normal = {
 295        &tr2dst_normal,
 296
 297        fn_init,
 298        fn_term,
 299
 300        fn_version_fl,
 301        fn_start_fl,
 302        fn_exit_fl,
 303        fn_signal,
 304        fn_atexit,
 305        fn_error_va_fl,
 306        fn_command_path_fl,
 307        fn_command_name_fl,
 308        fn_command_mode_fl,
 309        fn_alias_fl,
 310        fn_child_start_fl,
 311        fn_child_exit_fl,
 312        NULL, /* thread_start */
 313        NULL, /* thread_exit */
 314        fn_exec_fl,
 315        fn_exec_result_fl,
 316        fn_param_fl,
 317        fn_repo_fl,
 318        NULL, /* region_enter */
 319        NULL, /* region_leave */
 320        NULL, /* data */
 321        NULL, /* data_json */
 322        fn_printf_va_fl,
 323};