Git fork

trace2: write discard message to sentinel files

Add a new "discard" event type for trace2 event destinations. When the
trace2 file count check creates a sentinel file, it will include the
normal trace2 output in the sentinel, along with this new discard
event.

Writing this message into the sentinel file is useful for tracking how
often the file count check triggers in practice.

Bump up the event format version since we've added a new event type.

Signed-off-by: Josh Steadmon <steadmon@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Josh Steadmon and committed by
Junio C Hamano
87db61a4 83e57b04

+70 -33
+14 -2
Documentation/technical/api-trace2.txt
··· 128 128 129 129 ------------ 130 130 $ cat ~/log.event 131 - {"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"} 131 + {"event":"version","sid":"sid":"20190408T191610.507018Z-H9b68c35f-P000059a8","thread":"main","time":"2019-01-16T17:28:42.620713Z","file":"common-main.c","line":38,"evt":"2","exe":"2.20.1.155.g426c96fcdb"} 132 132 {"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"]} 133 133 {"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"} 134 134 {"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} ··· 616 616 { 617 617 "event":"version", 618 618 ... 619 - "evt":"1", # EVENT format version 619 + "evt":"2", # EVENT format version 620 620 "exe":"2.20.1.155.g426c96fcdb" # git version 621 + } 622 + ------------ 623 + 624 + `"discard"`:: 625 + This event is written to the git-trace2-discard sentinel file if there 626 + are too many files in the target trace directory (see the 627 + trace2.maxFiles config option). 628 + + 629 + ------------ 630 + { 631 + "event":"discard", 632 + ... 621 633 } 622 634 ------------ 623 635
+3 -1
t/t0212-trace2-event.sh
··· 279 279 ) && 280 280 echo git-trace2-discard >>expected_filenames.txt && 281 281 ls trace_target_dir >ls_output.txt && 282 - test_cmp expected_filenames.txt ls_output.txt 282 + test_cmp expected_filenames.txt ls_output.txt && 283 + head -n1 trace_target_dir/git-trace2-discard | grep \"event\":\"version\" && 284 + head -n2 trace_target_dir/git-trace2-discard | tail -n1 | grep \"event\":\"too_many_files\" 283 285 ' 284 286 285 287 test_done
+26 -21
trace2/tr2_dst.c
··· 48 48 /* 49 49 * Check to make sure we're not overloading the target directory with too many 50 50 * files. First get the threshold (if present) from the config or envvar. If 51 - * it's zero or unset, disable this check. Next check for the presence of a 52 - * sentinel file, then check file count. If we are overloaded, create the 53 - * sentinel file if it doesn't already exist. 51 + * it's zero or unset, disable this check. Next check for the presence of a 52 + * sentinel file, then check file count. 53 + * 54 + * Returns 0 if tracing should proceed as normal. Returns 1 if the sentinel file 55 + * already exists, which means tracing should be disabled. Returns -1 if there 56 + * are too many files but there was no sentinel file, which means we have 57 + * created and should write traces to the sentinel file. 54 58 * 55 59 * We expect that some trace processing system is gradually collecting files 56 60 * from the target directory; after it removes the sentinel file we'll start 57 61 * writing traces again. 58 62 */ 59 - static int tr2_dst_too_many_files(const char *tgt_prefix) 63 + static int tr2_dst_too_many_files(struct tr2_dst *dst, const char *tgt_prefix) 60 64 { 61 65 int file_count = 0, max_files = 0, ret = 0; 62 66 const char *max_files_var; ··· 95 99 closedir(dirp); 96 100 97 101 if (file_count >= tr2env_max_files) { 98 - creat(sentinel_path.buf, 0666); 99 - ret = 1; 102 + dst->too_many_files = 1; 103 + dst->fd = open(sentinel_path.buf, O_WRONLY | O_CREAT | O_EXCL, 0666); 104 + ret = -1; 100 105 goto cleanup; 101 106 } 102 107 ··· 108 113 109 114 static int tr2_dst_try_auto_path(struct tr2_dst *dst, const char *tgt_prefix) 110 115 { 111 - int fd; 116 + int too_many_files; 112 117 const char *last_slash, *sid = tr2_sid_get(); 113 118 struct strbuf path = STRBUF_INIT; 114 119 size_t base_path_len; ··· 124 129 strbuf_addstr(&path, sid); 125 130 base_path_len = path.len; 126 131 127 - if (tr2_dst_too_many_files(tgt_prefix)) { 132 + too_many_files = tr2_dst_too_many_files(dst, tgt_prefix); 133 + if (!too_many_files) { 134 + for (attempt_count = 0; attempt_count < MAX_AUTO_ATTEMPTS; attempt_count++) { 135 + if (attempt_count > 0) { 136 + strbuf_setlen(&path, base_path_len); 137 + strbuf_addf(&path, ".%d", attempt_count); 138 + } 139 + 140 + dst->fd = open(path.buf, O_WRONLY | O_CREAT | O_EXCL, 0666); 141 + if (dst->fd != -1) 142 + break; 143 + } 144 + } else if (too_many_files == 1) { 128 145 strbuf_release(&path); 129 146 if (tr2_dst_want_warning()) 130 147 warning("trace2: not opening %s trace file due to too " ··· 134 151 return 0; 135 152 } 136 153 137 - for (attempt_count = 0; attempt_count < MAX_AUTO_ATTEMPTS; attempt_count++) { 138 - if (attempt_count > 0) { 139 - strbuf_setlen(&path, base_path_len); 140 - strbuf_addf(&path, ".%d", attempt_count); 141 - } 142 - 143 - fd = open(path.buf, O_WRONLY | O_CREAT | O_EXCL, 0666); 144 - if (fd != -1) 145 - break; 146 - } 147 - 148 - if (fd == -1) { 154 + if (dst->fd == -1) { 149 155 if (tr2_dst_want_warning()) 150 156 warning("trace2: could not open '%.*s' for '%s' tracing: %s", 151 157 (int) base_path_len, path.buf, ··· 159 165 160 166 strbuf_release(&path); 161 167 162 - dst->fd = fd; 163 168 dst->need_close = 1; 164 169 dst->initialized = 1; 165 170
+1
trace2/tr2_dst.h
··· 9 9 int fd; 10 10 unsigned int initialized : 1; 11 11 unsigned int need_close : 1; 12 + unsigned int too_many_files : 1; 12 13 }; 13 14 14 15 /*
+24 -7
trace2/tr2_tgt_event.c
··· 10 10 #include "trace2/tr2_tgt.h" 11 11 #include "trace2/tr2_tls.h" 12 12 13 - static struct tr2_dst tr2dst_event = { TR2_SYSENV_EVENT, 0, 0, 0 }; 13 + static struct tr2_dst tr2dst_event = { TR2_SYSENV_EVENT, 0, 0, 0, 0 }; 14 14 15 15 /* 16 - * The version number of the JSON data generated by the EVENT target 17 - * in this source file. Update this if you make a significant change 18 - * to the JSON fields or message structure. You probably do not need 19 - * to update this if you just add another call to one of the existing 20 - * TRACE2 API methods. 16 + * The version number of the JSON data generated by the EVENT target in this 17 + * source file. The version should be incremented if new event types are added, 18 + * if existing fields are removed, or if there are significant changes in 19 + * interpretation of existing events or fields. Smaller changes, such as adding 20 + * a new field to an existing event, do not require an increment to the EVENT 21 + * format version. 21 22 */ 22 - #define TR2_EVENT_VERSION "1" 23 + #define TR2_EVENT_VERSION "2" 23 24 24 25 /* 25 26 * Region nesting limit for messages written to the event target. ··· 107 108 jw_object_intmax(jw, "repo", repo->trace2_repo_id); 108 109 } 109 110 111 + static void fn_too_many_files_fl(const char *file, int line) 112 + { 113 + const char *event_name = "too_many_files"; 114 + struct json_writer jw = JSON_WRITER_INIT; 115 + 116 + jw_object_begin(&jw, 0); 117 + event_fmt_prepare(event_name, file, line, NULL, &jw); 118 + jw_end(&jw); 119 + 120 + tr2_dst_write_line(&tr2dst_event, &jw.json); 121 + jw_release(&jw); 122 + } 123 + 110 124 static void fn_version_fl(const char *file, int line) 111 125 { 112 126 const char *event_name = "version"; ··· 120 134 121 135 tr2_dst_write_line(&tr2dst_event, &jw.json); 122 136 jw_release(&jw); 137 + 138 + if (tr2dst_event.too_many_files) 139 + fn_too_many_files_fl(file, line); 123 140 } 124 141 125 142 static void fn_start_fl(const char *file, int line,
+1 -1
trace2/tr2_tgt_normal.c
··· 9 9 #include "trace2/tr2_tgt.h" 10 10 #include "trace2/tr2_tls.h" 11 11 12 - static struct tr2_dst tr2dst_normal = { TR2_SYSENV_NORMAL, 0, 0, 0 }; 12 + static struct tr2_dst tr2dst_normal = { TR2_SYSENV_NORMAL, 0, 0, 0, 0 }; 13 13 14 14 /* 15 15 * Use the TR2_SYSENV_NORMAL_BRIEF setting to omit the "<time> <file>:<line>"
+1 -1
trace2/tr2_tgt_perf.c
··· 11 11 #include "trace2/tr2_tgt.h" 12 12 #include "trace2/tr2_tls.h" 13 13 14 - static struct tr2_dst tr2dst_perf = { TR2_SYSENV_PERF, 0, 0, 0 }; 14 + static struct tr2_dst tr2dst_perf = { TR2_SYSENV_PERF, 0, 0, 0, 0 }; 15 15 16 16 /* 17 17 * Use TR2_SYSENV_PERF_BRIEF to omit the "<time> <file>:<line>"