ifstat: add json output format
This commit is contained in:
parent
404582c8eb
commit
ec3e625c41
131
misc/ifstat.c
131
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue