All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Steadmon <steadmon@google.com>
To: git@vger.kernel.org, git@jeffhostetler.com
Subject: [PATCH 2/2] trace2: randomize/timestamp trace2 targets
Date: Wed, 13 Mar 2019 16:33:29 -0700	[thread overview]
Message-ID: <17ec237ba7498251a3ff64eec259d6f61c8f5ccc.1552519463.git.steadmon@google.com> (raw)
In-Reply-To: <cover.1552519463.git.steadmon@google.com>

When the value of a trace2 environment variable contains instances of
the string "%ISO8601%", expand them into the current UTC timestamp in
ISO 8601 format.

When the value of a trace2 environment variable is an absolute path
referring to an existing directory, write output to randomly-named
files under the given directory. If the value is an absolute path
referring to a non-existent file and ends with a dash, use the value as
a prefix for randomly named files.

The random filenames will consist of the value of the environment
variable (after potential timestamp expansion), followed by a 6
character random string such as would be produced by mkstemp(3).

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 <steadmon@google.com>
---
 Documentation/technical/api-trace2.txt | 10 +++
 t/t0210-trace2-normal.sh               | 93 ++++++++++++++++++++++++++
 trace2/tr2_dst.c                       | 86 +++++++++++++++++++++++-
 3 files changed, 187 insertions(+), 2 deletions(-)

diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt
index 2de565fa3d..1362bf7d0b 100644
--- a/Documentation/technical/api-trace2.txt
+++ b/Documentation/technical/api-trace2.txt
@@ -109,6 +109,16 @@ values are recognized.
 
 	Enables the target, opens and writes to the file in append mode.
 
+	If the path includes any instances of the string "%ISO8601%", they will
+	be replaced with the current UTC timestamp in ISO 8601 format with
+	dashes and colons removed, e.g., "20190315T143059Z".
+
+	If (after potential timestamp expansion) the path already exists and is
+	a directory, the traces will write to randomly-named files (one per
+	process) under the given directory. If the pathname does not already
+	exist and ends with a dash, it will be used as a prefix for
+	randomly-named files (one per process).
+
 `af_unix:[<socket_type>:]<absolute-pathname>`::
 
 	Enables the target, opens and writes to a Unix Domain Socket
diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh
index 03a0aedb1d..1b992c3e61 100755
--- a/t/t0210-trace2-normal.sh
+++ b/t/t0210-trace2-normal.sh
@@ -80,6 +80,99 @@ test_expect_success 'normal stream, return code 1' '
 	test_cmp expect actual
 '
 
+test_expect_success 'randomized filename' '
+	test_when_finished "rm -r traces actual expect" &&
+	mkdir traces &&
+	GIT_TR2="$(pwd)/traces" test-tool trace2 001return 0 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/??????)" >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_name trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'randomized filename with prefix' '
+	test_when_finished "rm -r traces actual expect" &&
+	mkdir traces &&
+	GIT_TR2="$(pwd)/traces/trace-" test-tool trace2 001return 0 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/trace-??????)" >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_name trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'timestamped filename' '
+	test_when_finished "rm -r traces actual expect" &&
+	mkdir traces &&
+	GIT_TEST_DATE_NOW=1552658399 GIT_TR2="$(pwd)/traces/trace.%ISO8601%" \
+		test-tool trace2 001return 0 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <traces/trace.20190315T135959Z >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_name trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'multiple timestamps' '
+	test_when_finished "rm -r traces actual expect" &&
+	mkdir -p traces/20190315T135959Z &&
+	GIT_TEST_DATE_NOW=1552658399 GIT_TR2="$(pwd)/traces/%ISO8601%/trace.%ISO8601%" \
+		test-tool trace2 001return 0 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <traces/20190315T135959Z/trace.20190315T135959Z >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_name trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'timestamp plus randomization' '
+	test_when_finished "rm -r traces actual expect" &&
+	mkdir traces &&
+	GIT_TEST_DATE_NOW=1552658399 GIT_TR2="$(pwd)/traces/trace-%ISO8601%-" test-tool trace2 001return 0 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/trace-20190315T135959Z-??????)" >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_name trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+test_expect_success 'no randomization if target exists' '
+	test_when_finished "rm -r traces actual expect" &&
+	mkdir traces &&
+	touch traces/trace- &&
+	GIT_TR2="$(pwd)/traces/trace-" test-tool trace2 001return 0 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <traces/trace- >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_name trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+
 # Verb 002exit
 #
 # Explicit exit(code) from within cmd_<verb> propagates <code>.
diff --git a/trace2/tr2_dst.c b/trace2/tr2_dst.c
index fd490a43ad..27405a92b4 100644
--- a/trace2/tr2_dst.c
+++ b/trace2/tr2_dst.c
@@ -12,6 +12,11 @@
  */
 #define TR2_ENVVAR_DST_DEBUG "GIT_TR2_DST_DEBUG"
 
+/* Constant string used for timestamp replacement in output destination
+ * filenames. See tr2_replace_timestamp_templates() below.
+ */
+static const char *iso_timestamp_tmpl = "%ISO8601%";
+
 static int tr2_dst_want_warning(void)
 {
 	static int tr2env_dst_debug = -1;
@@ -55,6 +60,64 @@ static int tr2_dst_try_path(struct tr2_dst *dst, const char *tgt_value)
 	return dst->fd;
 }
 
+static void tr2_replace_timestamp_templates(const char *path,
+					    struct strbuf *modified_path)
+{
+	char *iso_ptr;
+
+	strbuf_addstr(modified_path, path);
+
+	iso_ptr = strstr(modified_path->buf, iso_timestamp_tmpl);
+	if (iso_ptr) {
+		struct timeval tv;
+		struct tm tm;
+		size_t iso_len = strlen(iso_timestamp_tmpl);
+		struct strbuf timestamp = STRBUF_INIT;
+
+		get_time(&tv);
+		gmtime_r(&tv.tv_sec, &tm);
+		strbuf_addftime(&timestamp, "%Y%m%dT%H%M%SZ", &tm, 0, 0);
+
+		while (iso_ptr) {
+			strbuf_splice(modified_path,
+				      iso_ptr - modified_path->buf, iso_len,
+				      timestamp.buf, timestamp.len);
+
+			iso_ptr = strstr(modified_path->buf,
+					 iso_timestamp_tmpl);
+		}
+
+		strbuf_release(&timestamp);
+	}
+}
+
+static int tr2_dst_try_random_path(struct tr2_dst *dst, struct strbuf *path)
+{
+	int fd;
+	char last_path_char;
+
+	last_path_char = path->buf[path->len - 1];
+	if (!is_dir_sep(last_path_char) && last_path_char != '-')
+		strbuf_addch(path, '/');
+
+	strbuf_addstr(path, "XXXXXX");
+
+	fd = mkstemp(path->buf);
+	if (fd == -1) {
+		if (tr2_dst_want_warning())
+			warning("trace2: could not open '%s' for '%s' tracing: %s",
+				path->buf, dst->env_var_name, strerror(errno));
+		tr2_dst_trace_disable(dst);
+		return 0;
+	}
+
+	dst->fd = fd;
+	dst->need_close = 1;
+	dst->initialized = 1;
+
+	return dst->fd;
+}
+
 #ifndef NO_UNIX_SOCKETS
 #define PREFIX_AF_UNIX "af_unix:"
 #define PREFIX_AF_UNIX_STREAM "af_unix:stream:"
@@ -177,6 +240,7 @@ static void tr2_dst_malformed_warning(struct tr2_dst *dst,
 int tr2_dst_get_trace_fd(struct tr2_dst *dst)
 {
 	const char *tgt_value;
+	struct stat st;
 
 	/* don't open twice */
 	if (dst->initialized)
@@ -202,8 +266,26 @@ int tr2_dst_get_trace_fd(struct tr2_dst *dst)
 		return dst->fd;
 	}
 
-	if (is_absolute_path(tgt_value))
-		return tr2_dst_try_path(dst, tgt_value);
+	if (is_absolute_path(tgt_value)) {
+		int fd;
+		struct strbuf modified_path = STRBUF_INIT;
+
+		tr2_replace_timestamp_templates(tgt_value, &modified_path);
+
+		/*
+		 * Randomize the path if it is an existing directory, or if the
+		 * path does not exist and ends with '-'.
+		 */
+		if (is_directory(modified_path.buf) ||
+		    (stat(modified_path.buf, &st) == -1 && errno == ENOENT &&
+		     modified_path.buf[modified_path.len - 1] == '-'))
+			fd = tr2_dst_try_random_path(dst, &modified_path);
+		else
+			fd = tr2_dst_try_path(dst, modified_path.buf);
+
+		strbuf_release(&modified_path);
+		return fd;
+	}
 
 #ifndef NO_UNIX_SOCKETS
 	if (starts_with(tgt_value, PREFIX_AF_UNIX))
-- 
2.21.0.360.g471c308f928-goog


  parent reply	other threads:[~2019-03-13 23:33 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-13 23:33 [PATCH 0/2] Randomize / timestamp trace2 targets Josh Steadmon
2019-03-13 23:33 ` [PATCH 1/2] date: make get_time() public Josh Steadmon
2019-03-13 23:33 ` Josh Steadmon [this message]
2019-03-13 23:49   ` [PATCH 2/2] trace2: randomize/timestamp trace2 targets Ævar Arnfjörð Bjarmason
2019-03-15 18:39     ` Jeff Hostetler
2019-03-15 19:26       ` Ævar Arnfjörð Bjarmason
2019-03-15 20:14         ` Jeff Hostetler
2019-03-15 20:43     ` Josh Steadmon
2019-03-15 20:49       ` Josh Steadmon
2019-03-18  1:40         ` Junio C Hamano
2019-03-19  3:17           ` Jeff King
2019-03-14  0:16   ` Jeff King
2019-03-14  6:07     ` Junio C Hamano
2019-03-14 14:34 ` [PATCH 0/2] Randomize / timestamp " Johannes Schindelin
2019-03-15 20:37   ` Josh Steadmon
2019-03-15 19:18 ` Jeff Hostetler
2019-03-15 20:38   ` Josh Steadmon
2019-03-18 12:50     ` Jeff Hostetler
2019-03-21  0:16 ` [PATCH v2 0/1] Write trace2 output to directories Josh Steadmon
2019-03-21  0:16   ` [PATCH v2 1/1] trace2: write to directory targets Josh Steadmon
2019-03-21  2:04     ` Junio C Hamano
2019-03-21 17:43       ` Jeff Hostetler
2019-03-22  3:30         ` Junio C Hamano
2019-03-22 14:20           ` Jeff Hostetler
2019-03-21 21:09 ` [PATCH v3 0/1] Write trace2 output to directories Josh Steadmon
2019-03-21 21:09   ` [PATCH v3 1/1] trace2: write to directory targets Josh Steadmon
2019-03-23 20:44     ` Ævar Arnfjörð Bjarmason
2019-03-24 12:33       ` Junio C Hamano
2019-03-24 14:51         ` Ævar Arnfjörð Bjarmason
2019-03-25  2:21           ` Junio C Hamano
2019-03-25  8:21             ` Ævar Arnfjörð Bjarmason
2019-03-25 16:29       ` Jeff Hostetler
2019-03-21 21:16   ` [PATCH v3 0/1] Write trace2 output to directories Jeff Hostetler
2019-03-22  5:23     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=17ec237ba7498251a3ff64eec259d6f61c8f5ccc.1552519463.git.steadmon@google.com \
    --to=steadmon@google.com \
    --cc=git@jeffhostetler.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.