]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ifstat: add json output format
authorStephen Hemminger <stephen@networkplumber.org>
Tue, 24 Sep 2013 18:55:13 +0000 (11:55 -0700)
committerStephen Hemminger <stephen@networkplumber.org>
Tue, 24 Sep 2013 18:55:13 +0000 (11:55 -0700)
misc/ifstat.c

index 6d0ad8cc78a8f91a378d9e6a5442313479f83ba3..a47c046127093971b590ce1feb7b61f6b4ed6f54 100644 (file)
@@ -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);
 }