[IGT,2/2] tools/intel_gpu_top: Add file output capability
diff mbox series

Message ID 20190211114523.22844-2-tvrtko.ursulin@linux.intel.com
State New
Headers show
Series
  • [IGT,1/2] tools/intel_gpu_top: Add support for stdout logging
Related show

Commit Message

Tvrtko Ursulin Feb. 11, 2019, 11:45 a.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

A new -o command switch enables logging to a file.

v2:
 * Support "-o -" for explicit stdout selection. (Chris Wilson)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=108689
Cc: Eero Tamminen <eero.t.tamminen@intel.com>
Cc: 3.14pi@ukr.net
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 man/intel_gpu_top.rst | 19 ++++++++-----
 tools/intel_gpu_top.c | 63 ++++++++++++++++++++++++++++---------------
 2 files changed, 53 insertions(+), 29 deletions(-)

Patch
diff mbox series

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index d5bda093c8e8..d487baca0c63 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -28,16 +28,21 @@  The tool gathers data using perf performance counters (PMU) exposed by i915 and
 OPTIONS
 =======
 
--s <ms>
-    Refresh period in milliseconds.
+-h
+    Show help text.
+
+-J
+    Output JSON formatted data.
 
 -l
-    List text data to standard out.
+    List plain text data.
 
--J
-    Output JSON formatted data to standard output.
--h
-    Show help text.
+-o <file path | ->
+    Output to the specified file instead of standard output.
+    '-' can also be specified to explicitly select standard output.
+
+-s <ms>
+    Refresh period in milliseconds.
 
 LIMITATIONS
 ===========
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 900979eea7a1..60505a606bfc 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -690,10 +690,11 @@  usage(const char *appname)
 		"Usage: %s [parameters]\n"
 		"\n"
 		"\tThe following parameters are optional:\n\n"
-		"\t[-s <ms>]       Refresh period in milliseconds (default %ums).\n"
-		"\t[-l]            List data to standard out.\n"
-		"\t[-J]            JSON data to standard out.\n"
 		"\t[-h]            Show this help text.\n"
+		"\t[-J]            Output JSON formatted data.\n"
+		"\t[-l]            List plain text data.\n"
+		"\t[-o <file|->]   Output to specified file or '-' for standard out.\n"
+		"\t[-s <ms>]       Refresh period in milliseconds (default %ums).\n"
 		"\n",
 		appname, DEFAULT_PERIOD_MS);
 }
@@ -740,6 +741,8 @@  static const char *json_indent[] = {
 static unsigned int json_prev_struct_members;
 static unsigned int json_struct_members;
 
+FILE *out;
+
 static void
 json_open_struct(const char *name)
 {
@@ -749,14 +752,14 @@  json_open_struct(const char *name)
 	json_struct_members = 0;
 
 	if (name)
-		printf("%s%s\"%s\": {\n",
-		       json_prev_struct_members ? ",\n" : "",
-		       json_indent[json_indent_level],
-		       name);
+		fprintf(out, "%s%s\"%s\": {\n",
+			json_prev_struct_members ? ",\n" : "",
+			json_indent[json_indent_level],
+			name);
 	else
-		printf("%s\n%s{\n",
-		       json_prev_struct_members ? "," : "",
-		       json_indent[json_indent_level]);
+		fprintf(out, "%s\n%s{\n",
+			json_prev_struct_members ? "," : "",
+			json_indent[json_indent_level]);
 
 	json_indent_level++;
 }
@@ -766,7 +769,7 @@  json_close_struct(void)
 {
 	assert(json_indent_level > 0);
 
-	printf("\n%s}", json_indent[--json_indent_level]);
+	fprintf(out, "\n%s}", json_indent[--json_indent_level]);
 
 	if (json_indent_level == 0)
 		fflush(stdout);
@@ -778,17 +781,17 @@  json_add_member(const struct cnt_group *parent, struct cnt_item *item,
 {
 	assert(json_indent_level < ARRAY_SIZE(json_indent));
 
-	printf("%s%s\"%s\": ",
+	fprintf(out, "%s%s\"%s\": ",
 		json_struct_members ? ",\n" : "",
 		json_indent[json_indent_level], item->name);
 
 	json_struct_members++;
 
 	if (!strcmp(item->name, "unit"))
-		printf("\"%s\"", item->unit);
+		fprintf(out, "\"%s\"", item->unit);
 	else
-		printf("%f",
-		       pmu_calc(&item->pmu->val, item->d, item->t, item->s));
+		fprintf(out, "%f",
+			pmu_calc(&item->pmu->val, item->d, item->t, item->s));
 
 	return 1;
 }
@@ -811,8 +814,8 @@  stdout_close_struct(void)
 	assert(stdout_level > 0);
 	if (--stdout_level == 0) {
 		stdout_lines++;
-		printf("\n");
-		fflush(stdout);
+		fputs("\n", out);
+		fflush(out);
 	}
 }
 
@@ -844,10 +847,10 @@  stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
 			grp_tot += 1 + it->fmt_d + (it->fmt_dd ? 1 : 0);
 		}
 
-		printf("%*s ", grp_tot - 1, parent->display_name);
+		fprintf(out, "%*s ", grp_tot - 1, parent->display_name);
 		return 0;
 	} else if (headers == 2) {
-		printf("%*s ", fmt_tot, item->unit ?: item->name);
+		fprintf(out, "%*s ", fmt_tot, item->unit ?: item->name);
 		return 0;
 	}
 
@@ -857,7 +860,7 @@  stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
 	if (len < 0 || len == sizeof(buf))
 		fill_str(buf, sizeof(buf), 'X', fmt_tot);
 
-	len = printf("%s ", buf);
+	len = fprintf(out, "%s ", buf);
 
 	return len > 0 ? len : 0;
 }
@@ -1248,13 +1251,17 @@  int main(int argc, char **argv)
 {
 	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
 	int con_w = -1, con_h = -1;
+	char *output_path = NULL;
 	struct engines *engines;
 	unsigned int i;
 	int ret, ch;
 
 	/* Parse options */
-	while ((ch = getopt(argc, argv, "s:Jlh")) != -1) {
+	while ((ch = getopt(argc, argv, "o:s:Jlh")) != -1) {
 		switch (ch) {
+		case 'o':
+			output_path = optarg;
+			break;
 		case 's':
 			period_us = atoi(optarg) * 1000;
 			break;
@@ -1274,9 +1281,21 @@  int main(int argc, char **argv)
 		}
 	}
 
-	if (output_mode == INTERACTIVE && isatty(1) != 1)
+	if (output_mode == INTERACTIVE && (output_path || isatty(1) != 1))
 		output_mode = STDOUT;
 
+	if (output_path && strcmp(output_path, "-")) {
+		out = fopen(output_path, "w");
+
+		if (!out) {
+			fprintf(stderr, "Failed to open output file - '%s'!\n",
+				strerror(errno));
+			exit(1);
+		}
+	} else {
+		out = stdout;
+	}
+
 	if (output_mode != INTERACTIVE) {
 		sighandler_t sig = signal(SIGINT, sigint_handler);