Commit a4f9e8df authored by Stephen Hemminger's avatar Stephen Hemminger

lnstat: add json output format

parent ec3e625c
...@@ -41,7 +41,8 @@ ...@@ -41,7 +41,8 @@
static struct option opts[] = { static struct option opts[] = {
{ "version", 0, NULL, 'V' }, { "version", 0, NULL, 'V' },
{ "count", 1, NULL, 'c' }, { "count", 1, NULL, 'c' },
{ "dump", 1, NULL, 'd' }, { "dump", 0, NULL, 'd' },
{ "json", 0, NULL, 'j' },
{ "file", 1, NULL, 'f' }, { "file", 1, NULL, 'f' },
{ "help", 0, NULL, 'h' }, { "help", 0, NULL, 'h' },
{ "interval", 1, NULL, 'i' }, { "interval", 1, NULL, 'i' },
...@@ -63,6 +64,8 @@ static int usage(char *name, int exit_code) ...@@ -63,6 +64,8 @@ static int usage(char *name, int exit_code)
"Print <count> number of intervals\n"); "Print <count> number of intervals\n");
fprintf(stderr, "\t-d --dump\t\t" fprintf(stderr, "\t-d --dump\t\t"
"Dump list of available files/keys\n"); "Dump list of available files/keys\n");
fprintf(stderr, "\t-j --json\t\t"
"Display in JSON format\n");
fprintf(stderr, "\t-f --file <file>\tStatistics file to use\n"); fprintf(stderr, "\t-f --file <file>\tStatistics file to use\n");
fprintf(stderr, "\t-h --help\t\tThis help message\n"); fprintf(stderr, "\t-h --help\t\tThis help message\n");
fprintf(stderr, "\t-i --interval <intv>\t" fprintf(stderr, "\t-i --interval <intv>\t"
...@@ -94,7 +97,7 @@ static void print_line(FILE *of, const struct lnstat_file *lnstat_files, ...@@ -94,7 +97,7 @@ static void print_line(FILE *of, const struct lnstat_file *lnstat_files,
int i; int i;
for (i = 0; i < fp->num; i++) { for (i = 0; i < fp->num; i++) {
struct lnstat_field *lf = fp->params[i].lf; const struct lnstat_field *lf = fp->params[i].lf;
char formatbuf[255]; char formatbuf[255];
snprintf(formatbuf, sizeof(formatbuf)-1, "%%%ulu|", snprintf(formatbuf, sizeof(formatbuf)-1, "%%%ulu|",
...@@ -104,6 +107,30 @@ static void print_line(FILE *of, const struct lnstat_file *lnstat_files, ...@@ -104,6 +107,30 @@ static void print_line(FILE *of, const struct lnstat_file *lnstat_files,
fputc('\n', of); fputc('\n', of);
} }
static void print_json(FILE *of, const struct lnstat_file *lnstat_files,
const struct field_params *fp)
{
int i;
const char *sep;
const char *base = NULL;
fputs("{\n", of);
for (i = 0; i < fp->num; i++) {
const struct lnstat_field *lf = fp->params[i].lf;
if (!base || lf->file->basename != base) {
if (base) fputs("},\n", of);
base = lf->file->basename;
sep = "\n\t";
fprintf(of, " \"%s\":{", base);
}
fprintf(of, "%s\"%s\":%lu", sep,
lf->name, lf->result);
sep = ",\n\t";
}
fputs("}\n}\n", of);
}
/* find lnstat_field according to user specification */ /* find lnstat_field according to user specification */
static int map_field_params(struct lnstat_file *lnstat_files, static int map_field_params(struct lnstat_file *lnstat_files,
struct field_params *fps, int interval) struct field_params *fps, int interval)
...@@ -218,15 +245,16 @@ int main(int argc, char **argv) ...@@ -218,15 +245,16 @@ int main(int argc, char **argv)
{ {
struct lnstat_file *lnstat_files; struct lnstat_file *lnstat_files;
const char *basename; const char *basename;
int c; int i, c;
int interval = DEFAULT_INTERVAL; int interval = DEFAULT_INTERVAL;
int hdr = 2; int hdr = 2;
enum { enum {
MODE_DUMP, MODE_DUMP,
MODE_JSON,
MODE_NORMAL, MODE_NORMAL,
} mode = MODE_NORMAL; } mode = MODE_NORMAL;
unsigned long count = 1; unsigned long count = 1;
struct table_hdr *header;
static struct field_params fp; static struct field_params fp;
int num_req_files = 0; int num_req_files = 0;
char *req_files[LNSTAT_MAX_FILES]; char *req_files[LNSTAT_MAX_FILES];
...@@ -248,70 +276,73 @@ int main(int argc, char **argv) ...@@ -248,70 +276,73 @@ int main(int argc, char **argv)
num_req_files = 1; num_req_files = 1;
} }
while ((c = getopt_long(argc, argv,"Vc:df:h?i:k:s:w:", while ((c = getopt_long(argc, argv,"Vc:djf:h?i:k:s:w:",
opts, NULL)) != -1) { opts, NULL)) != -1) {
int i, len = 0; int len = 0;
char *tmp, *tok; char *tmp, *tok;
switch (c) { switch (c) {
case 'c': case 'c':
count = strtoul(optarg, NULL, 0); count = strtoul(optarg, NULL, 0);
break; break;
case 'd': case 'd':
mode = MODE_DUMP; mode = MODE_DUMP;
break; break;
case 'f': case 'j':
req_files[num_req_files++] = strdup(optarg); mode = MODE_JSON;
break;
case 'f':
req_files[num_req_files++] = strdup(optarg);
break;
case '?':
case 'h':
usage(argv[0], 0);
break;
case 'i':
sscanf(optarg, "%u", &interval);
break;
case 'k':
tmp = strdup(optarg);
if (!tmp)
break; break;
case '?': for (tok = strtok(tmp, ",");
case 'h': tok;
usage(argv[0], 0); tok = strtok(NULL, ",")) {
break; if (fp.num >= MAX_FIELDS) {
case 'i': fprintf(stderr,
sscanf(optarg, "%u", &interval); "WARN: too many keys"
break; " requested: (%d max)\n",
case 'k': MAX_FIELDS);
tmp = strdup(optarg);
if (!tmp)
break; break;
for (tok = strtok(tmp, ",");
tok;
tok = strtok(NULL, ",")) {
if (fp.num >= MAX_FIELDS) {
fprintf(stderr,
"WARN: too many keys"
" requested: (%d max)\n",
MAX_FIELDS);
break;
}
fp.params[fp.num++].name = tok;
} }
fp.params[fp.num++].name = tok;
}
break;
case 's':
sscanf(optarg, "%u", &hdr);
break;
case 'w':
tmp = strdup(optarg);
if (!tmp)
break; break;
case 's': i = 0;
sscanf(optarg, "%u", &hdr); for (tok = strtok(tmp, ",");
break; tok;
case 'w': tok = strtok(NULL, ",")) {
tmp = strdup(optarg); len = strtoul(tok, NULL, 0);
if (!tmp) if (len > FIELD_WIDTH_MAX)
break; len = FIELD_WIDTH_MAX;
i = 0; fp.params[i].print.width = len;
for (tok = strtok(tmp, ","); i++;
tok; }
tok = strtok(NULL, ",")) { if (i == 1) {
len = strtoul(tok, NULL, 0); for (i = 0; i < MAX_FIELDS; i++)
if (len > FIELD_WIDTH_MAX)
len = FIELD_WIDTH_MAX;
fp.params[i].print.width = len; fp.params[i].print.width = len;
i++; }
} break;
if (i == 1) { default:
for (i = 0; i < MAX_FIELDS; i++) usage(argv[0], 1);
fp.params[i].print.width = len; break;
}
break;
default:
usage(argv[0], 1);
break;
} }
} }
...@@ -319,13 +350,12 @@ int main(int argc, char **argv) ...@@ -319,13 +350,12 @@ int main(int argc, char **argv)
(const char **) req_files); (const char **) req_files);
switch (mode) { switch (mode) {
int i;
struct table_hdr *header;
case MODE_DUMP: case MODE_DUMP:
lnstat_dump(stderr, lnstat_files); lnstat_dump(stderr, lnstat_files);
break; break;
case MODE_NORMAL:
case MODE_NORMAL:
case MODE_JSON:
if (!map_field_params(lnstat_files, &fp, interval)) if (!map_field_params(lnstat_files, &fp, interval))
exit(1); exit(1);
...@@ -334,16 +364,23 @@ int main(int argc, char **argv) ...@@ -334,16 +364,23 @@ int main(int argc, char **argv)
exit(1); exit(1);
if (interval < 1 ) if (interval < 1 )
interval=1; interval = 1;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if ((hdr > 1 && (! (i % 20))) || (hdr == 1 && i == 0))
print_hdr(stdout, header);
lnstat_update(lnstat_files); lnstat_update(lnstat_files);
print_line(stdout, lnstat_files, &fp); if (mode == MODE_JSON)
print_json(stdout, lnstat_files, &fp);
else {
if ((hdr > 1 &&
(! (i % 20))) || (hdr == 1 && i == 0))
print_hdr(stdout, header);
print_line(stdout, lnstat_files, &fp);
}
fflush(stdout); fflush(stdout);
sleep(interval); if (i < count - 1)
sleep(interval);
} }
break;
} }
return 1; return 1;
......
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