summaryrefslogtreecommitdiff
path: root/misc/ifstat.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2013-09-24 11:55:13 -0700
committerStephen Hemminger <stephen@networkplumber.org>2013-09-24 11:55:13 -0700
commitec3e625c410feaad1b3da4c8e4b8e91069a862ba (patch)
treec325dc57a47ab83c25713eabe0620445de92762e /misc/ifstat.c
parent404582c8ebc99920bdfe8ba0fdef8ee4ee4d9783 (diff)
ifstat: add json output format
Diffstat (limited to 'misc/ifstat.c')
-rw-r--r--misc/ifstat.c131
1 files changed, 112 insertions, 19 deletions
diff --git a/misc/ifstat.c b/misc/ifstat.c
index 6d0ad8cc..a47c0461 100644
--- a/misc/ifstat.c
+++ b/misc/ifstat.c
@@ -38,6 +38,7 @@ int dump_zeros = 0;
int reset_history = 0;
int ignore_history = 0;
int no_output = 0;
+int json_output = 0;
int no_update = 0;
int scan_interval = 0;
int time_constant = 0;
@@ -61,6 +62,32 @@ struct ifstat_ent
__u32 ival[MAXS];
};
+static const char *stats[MAXS] = {
+ "rx_packets",
+ "tx_packets",
+ "rx_bytes",
+ "tx_bytes",
+ "rx_errors",
+ "tx_errors",
+ "rx_dropped",
+ "tx_dropped",
+ "multicast",
+ "collisions",
+ "rx_length_errors",
+ "rx_over_errors",
+ "rx_crc_errors",
+ "rx_frame_errors",
+ "rx_fifo_errors",
+ "rx_missed_errors",
+ "tx_aborted_errors",
+ "tx_carrier_errors",
+ "tx_fifo_errors",
+ "tx_heartbeat_errors",
+ "tx_window_errors",
+ "rx_compressed",
+ "tx_compressed"
+};
+
struct ifstat_ent *kern_db;
struct ifstat_ent *hist_db;
@@ -212,8 +239,13 @@ static void load_raw_table(FILE *fp)
static void dump_raw_db(FILE *fp, int to_hist)
{
struct ifstat_ent *n, *h;
+ const char *eol = "\n";
+
h = hist_db;
- fprintf(fp, "#%s\n", info_source);
+ if (json_output)
+ fprintf(fp, "{ \"%s\":{", info_source);
+ else
+ fprintf(fp, "#%s\n", info_source);
for (n=kern_db; n; n=n->next) {
int i;
@@ -232,10 +264,22 @@ static void dump_raw_db(FILE *fp, int to_hist)
}
}
}
- fprintf(fp, "%d %s ", n->ifindex, n->name);
- for (i=0; i<MAXS; i++)
- fprintf(fp, "%llu %u ", vals[i], (unsigned)rates[i]);
- fprintf(fp, "\n");
+
+ if (json_output) {
+ fprintf(fp, "%s \"%s\":{",
+ eol, n->name);
+ eol = ",\n";
+ for (i=0; i<MAXS && stats[i]; i++)
+ fprintf(fp, " \"%s\":%llu",
+ stats[i], vals[i]);
+ fprintf(fp, "}");
+ } else {
+ fprintf(fp, "%d %s ", n->ifindex, n->name);
+ for (i=0; i<MAXS; i++)
+ fprintf(fp, "%llu %u ", vals[i],
+ (unsigned)rates[i]);
+ fprintf(fp, "\n");
+ }
}
}
@@ -244,10 +288,11 @@ static const unsigned long long giga = 1000000000ull;
static const unsigned long long mega = 1000000;
static const unsigned long long kilo = 1000;
-static void format_rate(FILE *fp, unsigned long long *vals,
- double *rates, int i)
+static void format_rate(FILE *fp, const unsigned long long *vals,
+ const double *rates, int i)
{
char temp[64];
+
if (vals[i] > giga)
fprintf(fp, "%7lluM ", vals[i]/mega);
else if (vals[i] > mega)
@@ -265,7 +310,7 @@ static void format_rate(FILE *fp, unsigned long long *vals,
fprintf(fp, "%-6u ", (unsigned)rates[i]);
}
-static void format_pair(FILE *fp, unsigned long long *vals, int i, int k)
+static void format_pair(FILE *fp, const unsigned long long *vals, int i, int k)
{
char temp[64];
if (vals[i] > giga)
@@ -328,10 +373,27 @@ static void print_head(FILE *fp)
}
}
-static void print_one_if(FILE *fp, struct ifstat_ent *n,
- unsigned long long *vals)
+static void print_one_json(FILE *fp, const struct ifstat_ent *n,
+ const unsigned long long *vals)
+{
+ int i, m;
+ const char *sep = " ";
+
+ m = show_errors ? 20 : 10;
+ fprintf(fp, " \"%s\":{", n->name);
+ for (i=0; i < m && stats[i]; i++) {
+ fprintf(fp, "%s\"%s\":%llu",
+ sep, stats[i], vals[i]);
+ sep = ", ";
+ }
+ fprintf(fp, " }");
+}
+
+static void print_one_if(FILE *fp, const struct ifstat_ent *n,
+ const unsigned long long *vals)
{
int i;
+
fprintf(fp, "%-15s ", n->name);
for (i=0; i<4; i++)
format_rate(fp, vals, n->rate, i);
@@ -375,27 +437,42 @@ static void print_one_if(FILE *fp, struct ifstat_ent *n,
}
}
-
static void dump_kern_db(FILE *fp)
{
struct ifstat_ent *n;
+ const char *eol = "\n";
- print_head(fp);
+ if (json_output)
+ fprintf(fp, "{ \"%s\": {", info_source);
+ else
+ print_head(fp);
for (n=kern_db; n; n=n->next) {
if (!match(n->name))
continue;
- print_one_if(fp, n, n->val);
+
+ if (json_output) {
+ fprintf(fp, "%s", eol);
+ eol = ",\n";
+ print_one_json(fp, n, n->val);
+ } else
+ print_one_if(fp, n, n->val);
}
+ if (json_output)
+ fprintf(fp, "\n} }\n");
}
static void dump_incr_db(FILE *fp)
{
struct ifstat_ent *n, *h;
- h = hist_db;
+ const char *eol = "\n";
- print_head(fp);
+ h = hist_db;
+ if (json_output)
+ fprintf(fp, "{ \"%s\":{", info_source);
+ else
+ print_head(fp);
for (n=kern_db; n; n=n->next) {
int i;
@@ -414,8 +491,16 @@ static void dump_incr_db(FILE *fp)
}
if (!match(n->name))
continue;
- print_one_if(fp, n, vals);
+
+ if (json_output) {
+ fprintf(fp, "%s", eol);
+ eol = ",\n";
+ print_one_json(fp, n, n->val);
+ } else
+ print_one_if(fp, n, vals);
}
+ if (json_output)
+ fprintf(fp, "\n} }\n");
}
@@ -559,9 +644,10 @@ static void usage(void)
" -a, --ignore ignore history\n"
" -d, --scan=SECS sample every statistics every SECS\n"
" -e, --errors show errors\n"
+" -j, --json format output in JSON\n"
" -n, --nooutput do history only\n"
" -r, --reset reset history\n"
-" -s, --noupdate don;t update history\n"
+" -s, --noupdate don\'t update history\n"
" -t, --interval=SECS report average over the last SECS\n"
" -V, --version output version information\n"
" -z, --zeros show entries with zero activity\n");
@@ -575,6 +661,7 @@ static const struct option longopts[] = {
{ "scan", 1, 0, 'd'},
{ "errors", 0, 0, 'e' },
{ "nooutput", 0, 0, 'n' },
+ { "json", 0, 0, 'j' },
{ "reset", 0, 0, 'r' },
{ "noupdate", 0, 0, 's' },
{ "interval", 1, 0, 't' },
@@ -591,7 +678,7 @@ int main(int argc, char *argv[])
int ch;
int fd;
- while ((ch = getopt_long(argc, argv, "hvVzrnasd:t:eK",
+ while ((ch = getopt_long(argc, argv, "hjvVzrnasd:t:e",
longopts, NULL)) != EOF) {
switch(ch) {
case 'z':
@@ -612,6 +699,9 @@ int main(int argc, char *argv[])
case 'e':
show_errors = 1;
break;
+ case 'j':
+ json_output = 1;
+ break;
case 'd':
scan_interval = atoi(optarg) * 1000;
if (scan_interval <= 0) {
@@ -759,11 +849,14 @@ int main(int argc, char *argv[])
else
dump_incr_db(stdout);
}
+
if (!no_update) {
ftruncate(fileno(hist_fp), 0);
rewind(hist_fp);
+
+ json_output = 0;
dump_raw_db(hist_fp, 1);
- fflush(hist_fp);
+ fclose(hist_fp);
}
exit(0);
}