trace: add infrastructure to augment trace output with additional info

To be able to add a common prefix or suffix to all trace output (e.g.
a timestamp or file:line of the caller), factor out common setup and
cleanup tasks of the trace* functions.

When adding a common prefix, it makes sense that the output of each trace
call starts on a new line. Add '\n' in case the caller forgot.

Note that this explicitly limits trace output to line-by-line, it is no
longer possible to trace-print just part of a line. Until now, this was
just an implicit assumption (trace-printing part of a line worked, but
messed up the trace file if multiple threads or processes were involved).

Thread-safety / inter-process-safety is also the reason why we need to do
the prefixing and suffixing in memory rather than issuing multiple write()
calls. Write_or_whine_pipe() / xwrite() is atomic unless the size exceeds
MAX_IO_SIZE (8MB, see wrapper.c). In case of trace_strbuf, this costs an
additional string copy (which should be irrelevant for performance in light
of actual file IO).

While we're at it, rename trace_strbuf's 'buf' argument, which suggests
that the function is modifying the buffer. Trace_strbuf() currently is the
only trace API that can print arbitrary binary data (without barfing on
'%' or stopping at '\0'), so 'data' seems more appropriate.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Karsten Blees 2014-07-12 02:02:18 +02:00 коммит произвёл Junio C Hamano
Родитель 67dc598ec4
Коммит c69dfd24db
2 изменённых файлов: 34 добавлений и 15 удалений

47
trace.c
Просмотреть файл

@ -85,17 +85,37 @@ void trace_disable(struct trace_key *key)
static const char err_msg[] = "Could not trace into fd given by "
"GIT_TRACE environment variable";
static int prepare_trace_line(struct trace_key *key, struct strbuf *buf)
{
if (!trace_want(key))
return 0;
set_try_to_free_routine(NULL); /* is never reset */
/* add line prefix here */
return 1;
}
static void print_trace_line(struct trace_key *key, struct strbuf *buf)
{
/* append newline if missing */
if (buf->len && buf->buf[buf->len - 1] != '\n')
strbuf_addch(buf, '\n');
write_or_whine_pipe(get_trace_fd(key), buf->buf, buf->len, err_msg);
strbuf_release(buf);
}
static void trace_vprintf(struct trace_key *key, const char *format, va_list ap)
{
struct strbuf buf = STRBUF_INIT;
if (!trace_want(key))
if (!prepare_trace_line(key, &buf))
return;
set_try_to_free_routine(NULL); /* is never reset */
strbuf_vaddf(&buf, format, ap);
trace_strbuf(key, &buf);
strbuf_release(&buf);
print_trace_line(key, &buf);
}
void trace_printf_key(struct trace_key *key, const char *format, ...)
@ -114,32 +134,31 @@ void trace_printf(const char *format, ...)
va_end(ap);
}
void trace_strbuf(struct trace_key *key, const struct strbuf *buf)
void trace_strbuf(struct trace_key *key, const struct strbuf *data)
{
int fd = get_trace_fd(key);
if (!fd)
struct strbuf buf = STRBUF_INIT;
if (!prepare_trace_line(key, &buf))
return;
write_or_whine_pipe(fd, buf->buf, buf->len, err_msg);
strbuf_addbuf(&buf, data);
print_trace_line(key, &buf);
}
void trace_argv_printf(const char **argv, const char *format, ...)
{
struct strbuf buf = STRBUF_INIT;
va_list ap;
int fd = get_trace_fd(NULL);
if (!fd)
if (!prepare_trace_line(NULL, &buf))
return;
set_try_to_free_routine(NULL); /* is never reset */
va_start(ap, format);
strbuf_vaddf(&buf, format, ap);
va_end(ap);
sq_quote_argv(&buf, argv, 0);
strbuf_addch(&buf, '\n');
write_or_whine_pipe(fd, buf.buf, buf.len, err_msg);
strbuf_release(&buf);
print_trace_line(NULL, &buf);
}
static const char *quote_crnl(const char *path)

Просмотреть файл

@ -22,6 +22,6 @@ extern int trace_want(struct trace_key *key);
extern void trace_disable(struct trace_key *key);
__attribute__((format (printf, 2, 3)))
extern void trace_printf_key(struct trace_key *key, const char *format, ...);
extern void trace_strbuf(struct trace_key *key, const struct strbuf *buf);
extern void trace_strbuf(struct trace_key *key, const struct strbuf *data);
#endif /* TRACE_H */