Commit ec3e625c authored by Stephen Hemminger's avatar Stephen Hemminger

ifstat: add json output format

parent 404582c8
......@@ -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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment