From owner-svn-src-head@freebsd.org Tue Aug 21 11:22:50 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 78998106DE1A; Tue, 21 Aug 2018 11:22:50 +0000 (UTC) (envelope-from araujo@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 2C8E17F05B; Tue, 21 Aug 2018 11:22:50 +0000 (UTC) (envelope-from araujo@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 0CC4823529; Tue, 21 Aug 2018 11:22:50 +0000 (UTC) (envelope-from araujo@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w7LBMnDP070237; Tue, 21 Aug 2018 11:22:49 GMT (envelope-from araujo@FreeBSD.org) Received: (from araujo@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w7LBMnOY070234; Tue, 21 Aug 2018 11:22:49 GMT (envelope-from araujo@FreeBSD.org) Message-Id: <201808211122.w7LBMnOY070234@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: araujo set sender to araujo@FreeBSD.org using -f From: Marcelo Araujo Date: Tue, 21 Aug 2018 11:22:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r338133 - head/usr.sbin/gstat X-SVN-Group: head X-SVN-Commit-Author: araujo X-SVN-Commit-Paths: head/usr.sbin/gstat X-SVN-Commit-Revision: 338133 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Aug 2018 11:22:50 -0000 Author: araujo Date: Tue Aug 21 11:22:49 2018 New Revision: 338133 URL: https://svnweb.freebsd.org/changeset/base/338133 Log: - Add CSV output to gstat via -C flag. Add a -C option, similar to -B, that allows gstat to produce basic CSV output with absolute timestamps (ISO 8601, nearly.) Multiple devices are handled by way of a single-pivot CSV table with duplicated timestamps for each object output. Submitted by: Nick Principe Reviewed by: myself, imp@, asomers (earlier verison), bcr (manpages) Sponsored by: iXsystems Inc. Differential Revision: https://reviews.freebsd.org/D16151 Modified: head/usr.sbin/gstat/gstat.8 head/usr.sbin/gstat/gstat.c Modified: head/usr.sbin/gstat/gstat.8 ============================================================================== --- head/usr.sbin/gstat/gstat.8 Tue Aug 21 11:17:25 2018 (r338132) +++ head/usr.sbin/gstat/gstat.8 Tue Aug 21 11:22:49 2018 (r338133) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 10, 2016 +.Dd August 21, 2018 .Dt GSTAT 8 .Os .Sh NAME @@ -61,6 +61,10 @@ consumers too. The default is to show statistics only for .Xr geom 4 producers. +.It Fl C +CSV output mode. +Implies endless batch mode, but output is in the form of comma-separated +values, with ISO 8601-like timestamps. .It Fl d Enable display of statistics for delete .Pq Dv BIO_DELETE Modified: head/usr.sbin/gstat/gstat.c ============================================================================== --- head/usr.sbin/gstat/gstat.c Tue Aug 21 11:17:25 2018 (r338132) +++ head/usr.sbin/gstat/gstat.c Tue Aug 21 11:22:49 2018 (r338133) @@ -53,9 +53,12 @@ #include #include -static int flag_a, flag_b, flag_B, flag_c, flag_d, flag_o, flag_p, flag_s; +static int flag_a, flag_b, flag_B, flag_c, flag_C, flag_d, flag_o, flag_p, + flag_s; static int flag_I = 1000000; +#define HIGH_PCT_BUSY_THRESH 80 +#define MEDIUM_PCT_BUSY_THRESH 50 #define PRINTMSG(...) do { \ if ((flag_b && !loop) || (flag_B)) \ printf(__VA_ARGS__); \ @@ -76,7 +79,7 @@ int main(int argc, char **argv) { int error, i, quit; - int curx, cury, maxx, maxy, line_len, loop, max_flen; + int curx, cury, maxx, maxy, line_len, loop, max_flen, head_printed; struct devstat *gsp, *gsq; void *sp, *sq; double dt; @@ -89,6 +92,7 @@ main(int argc, char **argv) short cf, cb; char *p; char f_s[100], pf_s[100], tmp_f_s[100]; + char ts[100], g_name[4096]; const char *line; long double ld[16]; uint64_t u64; @@ -106,7 +110,7 @@ main(int argc, char **argv) flag_b = 1; f_s[0] = '\0'; - while ((i = getopt(argc, argv, "abBdcf:I:ops")) != -1) { + while ((i = getopt(argc, argv, "abBdcCf:I:ops")) != -1) { switch (i) { case 'a': flag_a = 1; @@ -121,6 +125,13 @@ main(int argc, char **argv) case 'c': flag_c = 1; break; + case 'C': + flag_C = 1; + /* csv out implies repeating batch mode */ + flag_b = 1; + flag_B = 1; + head_printed = 0; + break; case 'd': flag_d = 1; break; @@ -214,13 +225,21 @@ main(int argc, char **argv) dt = tp.tv_sec - tq.tv_sec; dt += (tp.tv_nsec - tq.tv_nsec) * 1e-9; tq = tp; + if (flag_C) { /* set timestamp string */ + (void)strftime(ts,sizeof(ts), + "%F %T",localtime(&tq.tv_sec)); + (void)snprintf(ts,sizeof(ts), + "%s.%.9ld",ts,tq.tv_nsec); + } geom_stats_snapshot_reset(sp); geom_stats_snapshot_reset(sq); if (!flag_b) move(0,0); - PRINTMSG("dT: %5.3fs w: %.3fs", dt, (float)flag_I / 1000000); - if (f_s[0] != '\0') { + if (!flag_C) + PRINTMSG("dT: %5.3fs w: %.3fs", dt, + (float)flag_I / 1000000); + if (!flag_C && f_s[0] != '\0') { PRINTMSG(" filter: "); if (!flag_b) { getyx(stdscr, cury, curx); @@ -239,25 +258,52 @@ main(int argc, char **argv) } PRINTMSG("%s", pf_s); } - PRINTMSG("\n"); - PRINTMSG(" L(q) ops/s "); - if (flag_s) { - PRINTMSG(" r/s kB kBps ms/r "); - PRINTMSG(" w/s kB kBps ms/w "); + if (!flag_C) { + PRINTMSG("\n"); + PRINTMSG(" L(q) ops/s "); + if (flag_s) { + PRINTMSG(" r/s kB kBps ms/r "); + PRINTMSG(" w/s kB kBps ms/w "); + } + else { + PRINTMSG(" r/s kBps ms/r "); + PRINTMSG(" w/s kBps ms/w "); + } + if (flag_d) { + if (flag_s) { + PRINTMSG(" d/s kB kBps"); + PRINTMSG(" ms/d "); + } else + PRINTMSG(" d/s kBps ms/d "); + } + if (flag_o) + PRINTMSG(" o/s ms/o "); + PRINTMSG("%%busy Name\n"); + } else if (flag_C && !head_printed) { + PRINTMSG("timestamp,name,q-depth,total_ops/s"); + if (flag_s) { + PRINTMSG(",read/s,read_sz-KiB"); + PRINTMSG(",read-KiB/s,ms/read"); + PRINTMSG(",write/s,write_sz-KiB"); + PRINTMSG(",write-KiB/s,ms/write"); + } else { + PRINTMSG(",read/s,read-KiB/s,ms/read"); + PRINTMSG(",write/s,write-KiB/s,ms/write"); + } + if (flag_d) { + if (flag_s) { + PRINTMSG(",delete/s,delete-sz-KiB"); + PRINTMSG(",delete-KiB/s,ms/delete"); + } else { + PRINTMSG(",delete/s,delete-KiB/s"); + PRINTMSG(",ms/delete"); + } + } + if (flag_o) + PRINTMSG(",other/s,ms/other"); + PRINTMSG(",%%busy\n"); + head_printed = 1; } - else { - PRINTMSG(" r/s kBps ms/r "); - PRINTMSG(" w/s kBps ms/w "); - } - if (flag_d) { - if (flag_s) - PRINTMSG(" d/s kB kBps ms/d "); - else - PRINTMSG(" d/s kBps ms/d "); - } - if (flag_o) - PRINTMSG(" o/s ms/o "); - PRINTMSG("%%busy Name\n"); for (;;) { gsp = geom_stats_snapshot_next(sp); gsq = geom_stats_snapshot_next(sq); @@ -278,7 +324,8 @@ main(int argc, char **argv) if (gid->lg_what == ISCONSUMER && !flag_c) continue; if (flag_p && gid->lg_what == ISPROVIDER && - ((struct gprovider *)(gid->lg_ptr))->lg_geom->lg_rank != 1) + ((struct gprovider *) + (gid->lg_ptr))->lg_geom->lg_rank != 1) continue; /* Do not print past end of window */ if (!flag_b) { @@ -294,7 +341,12 @@ main(int argc, char **argv) continue; } if (gsp->sequence0 != gsp->sequence1) { - PRINTMSG("*\n"); + /* + * it is ok to skip entire line silently + * for CSV output + */ + if (!flag_C) + PRINTMSG("*\n"); continue; } devstat_compute_statistics(gsp, gsq, dt, @@ -329,72 +381,131 @@ main(int argc, char **argv) continue; } - PRINTMSG(" %4ju", (uintmax_t)u64); - PRINTMSG(" %6.0f", (double)ld[0]); - PRINTMSG(" %6.0f", (double)ld[1]); - if (flag_s) - PRINTMSG(" %6.0f", (double)ld[13]); - PRINTMSG(" %6.0f", (double)ld[2] * 1024); - if (ld[3] > 1e3) - PRINTMSG(" %6.0f", (double)ld[3]); - else - PRINTMSG(" %6.1f", (double)ld[3]); - PRINTMSG(" %6.0f", (double)ld[4]); - if (flag_s) - PRINTMSG(" %6.0f", (double)ld[14]); - PRINTMSG(" %6.0f", (double)ld[5] * 1024); - if (ld[6] > 1e3) - PRINTMSG(" %6.0f", (double)ld[6]); - else - PRINTMSG(" %6.1f", (double)ld[6]); - - if (flag_d) { - PRINTMSG(" %6.0f", (double)ld[8]); - if (flag_s) - PRINTMSG(" %6.0f", (double)ld[15]); - PRINTMSG(" %6.0f", (double)ld[9] * 1024); - if (ld[10] > 1e3) - PRINTMSG(" %6.0f", (double)ld[10]); - else - PRINTMSG(" %6.1f", (double)ld[10]); - } - - if (flag_o) { - PRINTMSG(" %6.0f", (double)ld[11]); - if (ld[12] > 1e3) - PRINTMSG(" %6.0f", (double)ld[12]); - else - PRINTMSG(" %6.1f", (double)ld[12]); - } - - if (ld[7] > 80) - i = 3; - else if (ld[7] > 50) - i = 2; - else - i = 1; - if (!flag_b) - attron(COLOR_PAIR(i)); - PRINTMSG(" %6.1lf", (double)ld[7]); - if (!flag_b) { - attroff(COLOR_PAIR(i)); - PRINTMSG("|"); - } else - PRINTMSG(" "); + /* store name for geom device */ if (gid == NULL) { - PRINTMSG(" ??"); + (void)snprintf(g_name, sizeof(g_name), "??"); } else if (gid->lg_what == ISPROVIDER) { pp = gid->lg_ptr; - PRINTMSG(" %s", pp->lg_name); + (void)snprintf(g_name, sizeof(g_name), "%s", + pp->lg_name); } else if (gid->lg_what == ISCONSUMER) { cp = gid->lg_ptr; - PRINTMSG(" %s/%s/%s", - cp->lg_geom->lg_class->lg_name, - cp->lg_geom->lg_name, - cp->lg_provider->lg_name); + (void)snprintf(g_name, sizeof(g_name), + "%s/%s/%s", + cp->lg_geom->lg_class->lg_name, + cp->lg_geom->lg_name, + cp->lg_provider->lg_name); } - if (!flag_b) - clrtoeol(); + + if (flag_C) { + PRINTMSG("%s", ts); /* timestamp */ + PRINTMSG(",%s", g_name); /* print name */ + PRINTMSG(",%ju", (uintmax_t)u64); + PRINTMSG(",%.0f", (double)ld[0]); + PRINTMSG(",%.0f", (double)ld[1]); + if (flag_s) + PRINTMSG(",%.0f", (double)ld[13]); + PRINTMSG(",%.0f", (double)ld[2] * 1024); + if (ld[3] > 1e3) + PRINTMSG(",%.0f", (double)ld[3]); + else + PRINTMSG(",%.1f", (double)ld[3]); + PRINTMSG(",%.0f", (double)ld[4]); + if (flag_s) + PRINTMSG(",%.0f", (double)ld[14]); + PRINTMSG(",%.0f", (double)ld[5] * 1024); + if (ld[6] > 1e3) + PRINTMSG(",%.0f", (double)ld[6]); + else + PRINTMSG(",%.1f", (double)ld[6]); + + if (flag_d) { + PRINTMSG(",%.0f", (double)ld[8]); + if (flag_s) + PRINTMSG(",%.0f", + (double)ld[15]); + PRINTMSG(",%.0f", (double)ld[9] * 1024); + if (ld[10] > 1e3) + PRINTMSG(",%.0f", + (double)ld[10]); + else + PRINTMSG(",%.1f", + (double)ld[10]); + } + + if (flag_o) { + PRINTMSG(",%.0f", (double)ld[11]); + if (ld[12] > 1e3) + PRINTMSG(",%.0f", + (double)ld[12]); + else + PRINTMSG(",%.1f", + (double)ld[12]); + } + PRINTMSG(",%.1lf", (double)ld[7]); + } else { + PRINTMSG(" %4ju", (uintmax_t)u64); + PRINTMSG(" %6.0f", (double)ld[0]); + PRINTMSG(" %6.0f", (double)ld[1]); + if (flag_s) + PRINTMSG(" %6.0f", (double)ld[13]); + PRINTMSG(" %6.0f", (double)ld[2] * 1024); + if (ld[3] > 1e3) + PRINTMSG(" %6.0f", (double)ld[3]); + else + PRINTMSG(" %6.1f", (double)ld[3]); + PRINTMSG(" %6.0f", (double)ld[4]); + if (flag_s) + PRINTMSG(" %6.0f", (double)ld[14]); + PRINTMSG(" %6.0f", (double)ld[5] * 1024); + if (ld[6] > 1e3) + PRINTMSG(" %6.0f", (double)ld[6]); + else + PRINTMSG(" %6.1f", (double)ld[6]); + + if (flag_d) { + PRINTMSG(" %6.0f", (double)ld[8]); + if (flag_s) + PRINTMSG(" %6.0f", + (double)ld[15]); + PRINTMSG(" %6.0f", + (double)ld[9] * 1024); + if (ld[10] > 1e3) + PRINTMSG(" %6.0f", + (double)ld[10]); + else + PRINTMSG(" %6.1f", + (double)ld[10]); + } + + if (flag_o) { + PRINTMSG(" %6.0f", (double)ld[11]); + if (ld[12] > 1e3) + PRINTMSG(" %6.0f", + (double)ld[12]); + else + PRINTMSG(" %6.1f", + (double)ld[12]); + } + + if (ld[7] > HIGH_PCT_BUSY_THRESH) + i = 3; + else if (ld[7] > MEDIUM_PCT_BUSY_THRESH) + i = 2; + else + i = 1; + if (!flag_b) + attron(COLOR_PAIR(i)); + PRINTMSG(" %6.1lf", (double)ld[7]); + if (!flag_b) { + attroff(COLOR_PAIR(i)); + PRINTMSG("|"); + } else + PRINTMSG(" "); + PRINTMSG(" %s", g_name); + if (!flag_b) + clrtoeol(); + } PRINTMSG("\n"); *gsq = *gsp; } @@ -485,7 +596,7 @@ main(int argc, char **argv) static void usage(void) { - fprintf(stderr, "usage: gstat [-abBcdps] [-f filter] [-I interval]\n"); + fprintf(stderr, "usage: gstat [-abBcCdps] [-f filter] [-I interval]\n"); exit(EX_USAGE); /* NOTREACHED */ }