Skip to content

Commit a4d3a28

Browse files
steadmongitster
authored andcommitted
trace2: write to directory targets
When the value of a trace2 environment variable is an absolute path referring to an existing directory, write output to files (one per process) underneath the given directory. Files will be named according to the final component of the trace2 SID, followed by a counter to avoid potential collisions. This makes it more convenient to collect traces for every git invocation by unconditionally setting the relevant trace2 envvar to a constant directory name. Signed-off-by: Josh Steadmon <[email protected]> Reviewed-by: Jeff Hostetler <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 041f5ea commit a4d3a28

File tree

3 files changed

+81
-2
lines changed

3 files changed

+81
-2
lines changed

Documentation/technical/api-trace2.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ values are recognized.
109109

110110
Enables the target, opens and writes to the file in append mode.
111111

112+
If the target already exists and is a directory, the traces will be
113+
written to files (one per process) underneath the given directory. They
114+
will be named according to the last component of the SID (optionally
115+
followed by a counter to avoid filename collisions).
116+
112117
`af_unix:[<socket_type>:]<absolute-pathname>`::
113118

114119
Enables the target, opens and writes to a Unix Domain Socket

t/t0210-trace2-normal.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ test_expect_success 'normal stream, return code 1' '
8080
test_cmp expect actual
8181
'
8282

83+
test_expect_success 'automatic filename' '
84+
test_when_finished "rm -r traces actual expect" &&
85+
mkdir traces &&
86+
GIT_TR2="$(pwd)/traces" test-tool trace2 001return 0 &&
87+
perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/*)" >actual &&
88+
cat >expect <<-EOF &&
89+
version $V
90+
start _EXE_ trace2 001return 0
91+
cmd_name trace2 (trace2)
92+
exit elapsed:_TIME_ code:0
93+
atexit elapsed:_TIME_ code:0
94+
EOF
95+
test_cmp expect actual
96+
'
97+
8398
# Verb 002exit
8499
#
85100
# Explicit exit(code) from within cmd_<verb> propagates <code>.

trace2/tr2_dst.c

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cache.h"
22
#include "trace2/tr2_dst.h"
3+
#include "trace2/tr2_sid.h"
34

45
/*
56
* If a Trace2 target cannot be opened for writing, we should issue a
@@ -12,6 +13,11 @@
1213
*/
1314
#define TR2_ENVVAR_DST_DEBUG "GIT_TR2_DST_DEBUG"
1415

16+
/*
17+
* How many attempts we will make at creating an automatically-named trace file.
18+
*/
19+
#define MAX_AUTO_ATTEMPTS 10
20+
1521
static int tr2_dst_want_warning(void)
1622
{
1723
static int tr2env_dst_debug = -1;
@@ -36,6 +42,55 @@ void tr2_dst_trace_disable(struct tr2_dst *dst)
3642
dst->need_close = 0;
3743
}
3844

45+
static int tr2_dst_try_auto_path(struct tr2_dst *dst, const char *tgt_prefix)
46+
{
47+
int fd;
48+
const char *last_slash, *sid = tr2_sid_get();
49+
struct strbuf path = STRBUF_INIT;
50+
size_t base_path_len;
51+
unsigned attempt_count;
52+
53+
last_slash = strrchr(sid, '/');
54+
if (last_slash)
55+
sid = last_slash + 1;
56+
57+
strbuf_addstr(&path, tgt_prefix);
58+
if (!is_dir_sep(path.buf[path.len - 1]))
59+
strbuf_addch(&path, '/');
60+
strbuf_addstr(&path, sid);
61+
base_path_len = path.len;
62+
63+
for (attempt_count = 0; attempt_count < MAX_AUTO_ATTEMPTS; attempt_count++) {
64+
if (attempt_count > 0) {
65+
strbuf_setlen(&path, base_path_len);
66+
strbuf_addf(&path, ".%d", attempt_count);
67+
}
68+
69+
fd = open(path.buf, O_WRONLY | O_CREAT | O_EXCL, 0666);
70+
if (fd != -1)
71+
break;
72+
}
73+
74+
if (fd == -1) {
75+
if (tr2_dst_want_warning())
76+
warning("trace2: could not open '%.*s' for '%s' tracing: %s",
77+
(int) base_path_len, path.buf,
78+
dst->env_var_name, strerror(errno));
79+
80+
tr2_dst_trace_disable(dst);
81+
strbuf_release(&path);
82+
return 0;
83+
}
84+
85+
strbuf_release(&path);
86+
87+
dst->fd = fd;
88+
dst->need_close = 1;
89+
dst->initialized = 1;
90+
91+
return dst->fd;
92+
}
93+
3994
static int tr2_dst_try_path(struct tr2_dst *dst, const char *tgt_value)
4095
{
4196
int fd = open(tgt_value, O_WRONLY | O_APPEND | O_CREAT, 0666);
@@ -202,8 +257,12 @@ int tr2_dst_get_trace_fd(struct tr2_dst *dst)
202257
return dst->fd;
203258
}
204259

205-
if (is_absolute_path(tgt_value))
206-
return tr2_dst_try_path(dst, tgt_value);
260+
if (is_absolute_path(tgt_value)) {
261+
if (is_directory(tgt_value))
262+
return tr2_dst_try_auto_path(dst, tgt_value);
263+
else
264+
return tr2_dst_try_path(dst, tgt_value);
265+
}
207266

208267
#ifndef NO_UNIX_SOCKETS
209268
if (starts_with(tgt_value, PREFIX_AF_UNIX))

0 commit comments

Comments
 (0)