From 9b20b0e97840946991d1919e43abacba152645c8 Mon Sep 17 00:00:00 2001 From: Teemu Toivola Date: Sun, 10 Dec 2023 23:49:58 +0200 Subject: [PATCH] add 95th percentile option to --json --- src/dbjson.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/dbjson.h | 1 + src/dbshow.c | 1 - src/percentile.c | 1 + src/percentile.h | 2 +- src/vnstat_func.c | 5 ++-- 6 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/dbjson.c b/src/dbjson.c index 49fa6c66..61bde187 100644 --- a/src/dbjson.c +++ b/src/dbjson.c @@ -1,5 +1,6 @@ #include "common.h" #include "dbsql.h" +#include "percentile.h" #include "dbjson.h" void showjson(const char *interface, const int ifcount, const char mode, const char *databegin, const char *dataend) @@ -30,6 +31,13 @@ void showjson(const char *interface, const int ifcount, const char mode, const c jsondate(&info.updated, 2); printf("},"); + if (mode == 'p') { + jsonpercentile(&info); + printf("}"); + timeused_debug(__func__, 0); + return; + } + printf("\"traffic\":"); printf("{\"total\":{\"rx\":%" PRIu64 ",\"tx\":%" PRIu64 "},", info.rxtotal, info.txtotal); @@ -112,6 +120,57 @@ void jsondump(const interfaceinfo *interface, const char *tablename, const int d printf("]"); } +void jsonpercentile(const interfaceinfo *interface) +{ + percentiledata pdata; + + if (!getpercentiledata(&pdata, interface->name)) { + exit(EXIT_FAILURE); + } + + printf("\"bandwidth\":{"); + + printf("\"month\":{"); + jsondate(&pdata.monthbegin, 1); + printf("},"); + + printf("\"data_begin\":{"); + jsondate(&pdata.databegin, 2); + printf("},"); + + printf("\"data_end\":{"); + jsondate(&pdata.dataend, 2); + printf("},"); + + printf("\"entries\":{\"seen\":%" PRIu32 ",\"expected\":%" PRIu32 ",\"missing\":%" PRIu32 "},", pdata.count, pdata.countexpectation, pdata.countexpectation-pdata.count); + + printf("\"minimum\":{"); + printf("\"rx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.minrx / (double)300)); + printf("\"tx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.mintx / (double)300)); + printf("\"total_bytes_per_second\":%" PRIu64 "", (uint64_t)(pdata.min / (double)300)); + printf("},"); + + printf("\"average\":{"); + printf("\"rx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.sumrx / (double)(pdata.count * 300))); + printf("\"tx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.sumtx / (double)(pdata.count * 300))); + printf("\"total_bytes_per_second\":%" PRIu64 "", (uint64_t)(pdata.sumrx + pdata.sumtx / (double)(pdata.count * 300))); + printf("},"); + + printf("\"maximum\":{"); + printf("\"rx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.maxrx / (double)300)); + printf("\"tx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.maxtx / (double)300)); + printf("\"total_bytes_per_second\":%" PRIu64 "", (uint64_t)(pdata.max / (double)300)); + printf("},"); + + printf("\"95th_percentile\":{"); + printf("\"rx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.rxpercentile / (double)300)); + printf("\"tx_bytes_per_second\":%" PRIu64 ",", (uint64_t)(pdata.txpercentile / (double)300)); + printf("\"total_bytes_per_second\":%" PRIu64 "", (uint64_t)(pdata.sumpercentile / (double)300)); + printf("}"); + + printf("}"); +} + void jsondate(const time_t *date, const int type) { struct tm *d; diff --git a/src/dbjson.h b/src/dbjson.h index 273acf6a..18117b84 100644 --- a/src/dbjson.h +++ b/src/dbjson.h @@ -3,6 +3,7 @@ void showjson(const char *interface, const int ifcount, const char mode, const char *databegin, const char *dataend); void jsondump(const interfaceinfo *interface, const char *tablename, const int datetype, const char *databegin, const char *dataend); +void jsonpercentile(const interfaceinfo *interface); void jsondate(const time_t *date, const int type); void jsonheader(void); void jsonfooter(void); diff --git a/src/dbshow.c b/src/dbshow.c index 0af5256e..d1b04134 100644 --- a/src/dbshow.c +++ b/src/dbshow.c @@ -869,7 +869,6 @@ void showhours(const interfaceinfo *interface) timeused_debug(__func__, 0); } -// TODO: json? needs new function due to different format // TODO: xml? needs new function due to different format // TODO: alert needs new function due to different format // TODO: image? output below doesn't have much graphics potential, line in 5 minute graph could be one alternative diff --git a/src/percentile.c b/src/percentile.c index 885bfa01..dcc60634 100644 --- a/src/percentile.c +++ b/src/percentile.c @@ -38,6 +38,7 @@ int getpercentiledata(percentiledata *pdata, const char *iface) return 0; } + pdata->databegin = datainfo.mintime; pdata->dataend = datainfo.maxtime; pdata->count = datainfo.count; pdata->countexpectation = (uint32_t)((pdata->dataend - pdata->monthbegin) / 300 + 1); diff --git a/src/percentile.h b/src/percentile.h index d5c3ad64..f7a7954a 100644 --- a/src/percentile.h +++ b/src/percentile.h @@ -2,7 +2,7 @@ #define PERCENTILE_H typedef struct percentiledata { - time_t monthbegin, dataend; + time_t monthbegin, databegin, dataend; uint32_t count, countexpectation; uint64_t minrx, mintx; uint64_t maxrx, maxtx; diff --git a/src/vnstat_func.c b/src/vnstat_func.c index 131d2517..8d4ed5b9 100644 --- a/src/vnstat_func.c +++ b/src/vnstat_func.c @@ -378,11 +378,11 @@ void parseargs(PARAMS *p, const int argc, char **argv) cfg.qmode = 10; if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) { p->jsonmode = argv[currentarg + 1][0]; - if (strlen(argv[currentarg + 1]) != 1 || strchr("asfhdmyt", p->jsonmode) == NULL) { + if (strlen(argv[currentarg + 1]) != 1 || strchr("asfhdmytp", p->jsonmode) == NULL) { if (!ishelprequest(argv[currentarg + 1])) printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]); printf(" Valid parameters for --json:\n"); - printf(" a - all (default)\n"); + printf(" a - all except 95th percentile (default)\n"); printf(" s - summary\n"); printf(" f - only 5 minutes\n"); printf(" h - only hours\n"); @@ -390,6 +390,7 @@ void parseargs(PARAMS *p, const int argc, char **argv) printf(" m - only months\n"); printf(" y - only years\n"); printf(" t - only top\n"); + printf(" p - 95th percentile\n"); // TODO: documentation exit(EXIT_FAILURE); } if (p->jsonmode == 's') {