aboutsummaryrefslogtreecommitdiff
path: root/rrdtool/rrd_anomaly.c
diff options
context:
space:
mode:
Diffstat (limited to 'rrdtool/rrd_anomaly.c')
-rw-r--r--rrdtool/rrd_anomaly.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/rrdtool/rrd_anomaly.c b/rrdtool/rrd_anomaly.c
new file mode 100644
index 000000000..21f43d389
--- /dev/null
+++ b/rrdtool/rrd_anomaly.c
@@ -0,0 +1,159 @@
+/*
+ * ndpiReader.c
+ *
+ * Copyright (C) 2011-21 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <getopt.h>
+#include "rrd.h"
+#include "ndpi_api.h"
+
+#define DEFAULT_ALPHA 0.5
+#define DEFAULT_START "now-1d"
+#define DEFAULT_END "now"
+
+/* *************************************************** */
+
+static void help() {
+ printf("Usage: rrd_anomaly [-a <alpha>][-s <start>][-e <end>] -f <filename>\n"
+ "-a | Set alpha. Valid range >0 .. <1. Default %.2f\n"
+ "-s <start> | RRD start time. Default %s\n"
+ "-e <end> | RRD end time. Default %s\n"
+ "-f <rrd path> | Path of the RRD filename to analyze\n",
+ DEFAULT_ALPHA, DEFAULT_START, DEFAULT_END);
+
+ printf("\n\nExample: rrd_anomaly -s now-1d -e now -f hum.rrd\n");
+ exit(0);
+}
+
+/* *************************************************** */
+
+int main(int argc, char *argv[]) {
+ rrd_time_value_t start_tv, end_tv;
+ unsigned long step = 0, ds_cnt = 0;
+ rrd_value_t *data, *p;
+ char **names, *filename = NULL, *start_s, *end_s, *cf;
+ u_int i, j, t, first = 1;
+ time_t start, end;
+ struct ndpi_ses_struct ses;
+ float alpha;
+ char c;
+
+ /* Defaults */
+ alpha = DEFAULT_ALPHA;
+ start_s = DEFAULT_START;
+ end_s = DEFAULT_END;
+ cf = "AVERAGE";
+
+ while((c = getopt(argc, argv, "s:e:a:f:")) != '?') {
+ if(c == -1) break;
+
+ switch(c) {
+ case 's':
+ start_s = optarg;
+ break;
+
+ case 'e':
+ end_s = optarg;
+ break;
+
+ case 'a':
+ {
+ float f = atof(optarg);
+
+ if((f > 0) && (f < 1))
+ alpha = f;
+ else
+ printf("Discarding -a: valid range is >0 .. <1\n");
+ }
+ break;
+
+ case 'f':
+ filename = optarg;
+ break;
+
+ default:
+ help();
+ break;
+ }
+ }
+
+ if(filename == NULL)
+ help();
+
+ ndpi_ses_init(&ses, alpha, 0.05);
+
+ if((rrd_parsetime(start_s, &start_tv) != NULL)) {
+ printf("Unable to parse start time %s\n", start_s);
+ return(-1);
+ }
+
+ if((rrd_parsetime(end_s, &end_tv) != NULL)) {
+ printf("Unable to parse end time %s\n", end_s);
+ return(-1);
+ }
+
+ rrd_proc_start_end(&start_tv, &end_tv, &start, &end);
+
+ if(rrd_fetch_r(filename, cf, &start, &end, &step, &ds_cnt, &names, &data) != 0) {
+ printf("Unable to extract data from rrd %s\n", filename);
+ return(-2);
+ }
+
+ p = data;
+ for(t=start+1, i=0; t<end; t+=step, i++) {
+ for(j=0; j<ds_cnt; j++) {
+ rrd_value_t value = *p++;
+
+ if(!isnan(value)) {
+ double prediction, confidence_band;
+ double lower, upper;
+ char buf[32];
+ int rc;
+ u_int is_anomaly;
+
+ value *= 100;
+ rc = ndpi_ses_add_value(&ses, value, &prediction, &confidence_band);
+ lower = prediction - confidence_band, upper = prediction + confidence_band;
+ is_anomaly = ((rc == 0) || ((value >= lower) && (value <= upper))) ? 0 : 1;
+
+ if(is_anomaly) {
+ struct tm *t_info = localtime((const time_t*)&t);
+
+ strftime(buf, sizeof(buf), "%d/%b/%Y %H:%M:%S", t_info);
+
+ if(first) {
+ first = 0;
+ printf("%s %s\t%s %s %s\t %s [%s]\n",
+ "When", "Value", "Prediction", "Lower", "Upper", "Out", "Band");
+ }
+
+ printf("%s %12.3f\t%.3f\t%12.3f\t%12.3f\t %s [%.3f]\n",
+ buf, value/100., prediction/100., lower/100., upper/100., is_anomaly? "ANOMALY" : "OK",
+ confidence_band/100.);
+ }
+ }
+ }
+ }
+
+ rrd_freemem(data);
+
+ return(0);
+}