diff --git a/Makefile b/Makefile
index 93664d6714..19f5189c6f 100644
--- a/Makefile
+++ b/Makefile
@@ -855,6 +855,7 @@ LIB_OBJS += commit-graph.o
 LIB_OBJS += commit-reach.o
 LIB_OBJS += commit.o
 LIB_OBJS += compat/obstack.o
+LIB_OBJS += compat/procinfo.o
 LIB_OBJS += compat/terminal.o
 LIB_OBJS += config.o
 LIB_OBJS += connect.o
diff --git a/compat/procinfo.c b/compat/procinfo.c
new file mode 100644
index 0000000000..7f4c8dd284
--- /dev/null
+++ b/compat/procinfo.c
@@ -0,0 +1,19 @@
+#include "git-compat-util.h"
+
+#include "strbuf.h"
+
+char *get_process_name(int pid)
+{
+	struct strbuf procfs_path = STRBUF_INIT;
+	struct strbuf out = STRBUF_INIT;
+	/* try to use procfs if it's present. */
+	strbuf_addf(&procfs_path, "/proc/%d/cmdline", pid);
+	if (strbuf_read_file(&out, procfs_path.buf, 0) > 0)
+	{
+		strbuf_release(&procfs_path);
+		return strbuf_detach(&out, NULL);
+	}
+
+	/* NEEDSWORK: add non-procfs implementations here. */
+	return NULL;
+}
diff --git a/git-compat-util.h b/git-compat-util.h
index a508dbe5a3..cc7d5d8a2a 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1382,4 +1382,10 @@ static inline void *container_of_or_null_offset(void *ptr, size_t offset)
 
 void sleep_millisec(int millisec);
 
+/*
+ * Convert PID to process name (as would show in top/task manager). Returns
+ * NULL if unimplemented - be sure to check for NULL at callsite.
+ */
+char *get_process_name(int pid);
+
 #endif
diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh
index 1529155cf0..3a2a8a5b5f 100755
--- a/t/t0212-trace2-event.sh
+++ b/t/t0212-trace2-event.sh
@@ -61,6 +61,7 @@ test_expect_success JSON_PP 'event stream, error event' '
 	|    "exit_code":0,
 	|    "hierarchy":"trace2",
 	|    "name":"trace2",
+	|    "parent_name":"/bin/sh",
 	|    "version":"$V"
 	|  }
 	|};
@@ -115,6 +116,7 @@ test_expect_success JSON_PP 'event stream, return code 0' '
 	|    "exit_code":0,
 	|    "hierarchy":"trace2",
 	|    "name":"trace2",
+	|    "parent_name":"/bin/sh",
 	|    "version":"$V"
 	|  },
 	|  "_SID0_/_SID1_":{
@@ -143,6 +145,7 @@ test_expect_success JSON_PP 'event stream, return code 0' '
 	|    "exit_code":0,
 	|    "hierarchy":"trace2/trace2",
 	|    "name":"trace2",
+	|    "parent_name":"test-tool",
 	|    "version":"$V"
 	|  },
 	|  "_SID0_/_SID1_/_SID2_":{
@@ -155,6 +158,7 @@ test_expect_success JSON_PP 'event stream, return code 0' '
 	|    "exit_code":0,
 	|    "hierarchy":"trace2/trace2/trace2",
 	|    "name":"trace2",
+	|    "parent_name":"$TEST_DIRECTORY/../t/helper//test-tool",
 	|    "version":"$V"
 	|  }
 	|};
@@ -192,6 +196,7 @@ test_expect_success JSON_PP 'event stream, list config' '
 	|        "value":"hello world"
 	|      }
 	|    ],
+	|    "parent_name":"/bin/sh",
 	|    "version":"$V"
 	|  }
 	|};
@@ -229,6 +234,7 @@ test_expect_success JSON_PP 'event stream, list env vars' '
 	|        "value":"hello world"
 	|      }
 	|    ],
+	|    "parent_name":"/bin/sh",
 	|    "version":"$V"
 	|  }
 	|};
@@ -263,6 +269,7 @@ test_expect_success JSON_PP 'basic trace2_data' '
 	|    "exit_code":0,
 	|    "hierarchy":"trace2",
 	|    "name":"trace2",
+	|    "parent_name":"/bin/sh",
 	|    "version":"$V"
 	|  }
 	|};
@@ -295,6 +302,7 @@ test_expect_success JSON_PP 'using global config, event stream, error event' '
 	|    "exit_code":0,
 	|    "hierarchy":"trace2",
 	|    "name":"trace2",
+	|    "parent_name":"/bin/sh",
 	|    "version":"$V"
 	|  }
 	|};
diff --git a/t/t0212/parse_events.perl b/t/t0212/parse_events.perl
index 6584bb5634..dd8b1be844 100644
--- a/t/t0212/parse_events.perl
+++ b/t/t0212/parse_events.perl
@@ -99,6 +99,7 @@
     }
 
     elsif ($event eq 'start') {
+	$processes->{$sid}->{'parent_name'} = $line->{'parent_name'};
 	$processes->{$sid}->{'argv'} = $line->{'argv'};
 	$processes->{$sid}->{'argv'}[0] = "_EXE_";
     }
diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c
index 6353e8ad91..d258d5807c 100644
--- a/trace2/tr2_tgt_event.c
+++ b/trace2/tr2_tgt_event.c
@@ -145,10 +145,12 @@ static void fn_start_fl(const char *file, int line,
 	const char *event_name = "start";
 	struct json_writer jw = JSON_WRITER_INIT;
 	double t_abs = (double)us_elapsed_absolute / 1000000.0;
+	char *parent_name = get_process_name(getppid());
 
 	jw_object_begin(&jw, 0);
 	event_fmt_prepare(event_name, file, line, NULL, &jw);
 	jw_object_double(&jw, "t_abs", 6, t_abs);
+	jw_object_string(&jw, "parent_name", parent_name ? parent_name : NULL );
 	jw_object_inline_begin_array(&jw, "argv");
 	jw_array_argv(&jw, argv);
 	jw_end(&jw);
@@ -156,6 +158,7 @@ static void fn_start_fl(const char *file, int line,
 
 	tr2_dst_write_line(&tr2dst_event, &jw.json);
 	jw_release(&jw);
+	free(parent_name);
 }
 
 static void fn_exit_fl(const char *file, int line, uint64_t us_elapsed_absolute,
