]> granicus.if.org Git - vnstat/commitdiff
add new configuration options for data retention durations
authorTeemu Toivola <git@humdi.net>
Tue, 17 Jan 2017 19:47:13 +0000 (21:47 +0200)
committerTeemu Toivola <git@humdi.net>
Tue, 17 Jan 2017 19:47:13 +0000 (21:47 +0200)
README.md
cfg/vnstat.conf
src/cfg.c
src/common.h
src/dbsql.c

index 380973abf9a538ebfa324812b73d8c2d6a6504db..a04610eeaa18c4da9ae7d66a57bf2d52a0386374 100644 (file)
--- a/README.md
+++ b/README.md
@@ -26,13 +26,14 @@ configurable durations. Yearly and 5 minute resolution statistics are also plann
     * write support is no longer included in code
   * full data import from vnStat 1.x database format including reconstructed yearly data
   * legacy database is not kept in memory for each interface during daemon runtime
+  * new configuration options for data retention durations
+    * the daemon doesn't however yet use these new options
 
 ##### TODO
 
   * `grep TODO src/* tests/*`
   * continue daemon refactoring
   * add missing sanity checks to daemon
-  * rewrite disabled tests
   * all outputs (text and image)
     * use of 5 minute resolution statistics
   * old data cleanup, everything gets currently stored forever
index c127b29d399c85297faa769eb1ebce081a8d434e..895bc81d0defd1f244c558253675e7e07c83b27c 100644 (file)
@@ -1,4 +1,4 @@
-# vnStat 1.17 config file
+# vnStat 2.0 config file
 ##
 
 # default interface
@@ -76,6 +76,14 @@ BootVariation 15
 # log days without traffic to daily list (1 = enabled, 0 = disabled)
 TrafficlessDays 1
 
+# data retention durations (-1 = unlimited, 0 = log disabled)
+5MinuteHours   48
+HourlyDays      2
+DailyDays      30
+MonthlyMonths  12
+YearlyYears    -1
+TopDayEntries  10
+
 
 # vnstatd
 ##
index 01950598b0f72e0c86d6e2f65df7504fe0fcc258..e1289f728b4dc391126b875fa710f73fce719051 100644 (file)
--- a/src/cfg.c
+++ b/src/cfg.c
@@ -87,7 +87,15 @@ void printcfgfile(void)
        printf("BootVariation %d\n\n", cfg.bvar);
 
        printf("# log days without traffic to daily list (1 = enabled, 0 = disabled)\n");
-       printf("TrafficlessDays %d\n", cfg.traflessday);
+       printf("TrafficlessDays %d\n\n", cfg.traflessday);
+
+       printf("# data retention durations (-1 = unlimited, 0 = log disabled)\n");
+       printf("5MinuteHours   %2d\n", cfg.fiveminutehours);
+       printf("HourlyDays     %2d\n", cfg.hourlydays);
+       printf("DailyDays      %2d\n", cfg.dailydays);
+       printf("MonthlyMonths  %2d\n", cfg.monthlymonths);
+       printf("YearlyYears    %2d\n", cfg.yearlyyears);
+       printf("TopDayEntries  %2d\n", cfg.topdayentries);
 
        printf("\n\n");
 
@@ -200,6 +208,12 @@ int loadcfg(const char *cfgfile)
                { "UseFileLocking", 0, &cfg.flock, 0, 0 },
                { "BootVariation", 0, &cfg.bvar, 0, 0 },
                { "TrafficlessDays", 0, &cfg.traflessday, 0, 0 },
+               { "5MinuteHours", 0, &cfg.fiveminutehours, 0, 0 },
+               { "HourlyDays", 0, &cfg.hourlydays, 0, 0 },
+               { "DailyDays", 0, &cfg.dailydays, 0, 0 },
+               { "MonthlyMonths", 0, &cfg.monthlymonths, 0, 0 },
+               { "YearlyYears", 0, &cfg.yearlyyears, 0, 0 },
+               { "TopDayEntries", 0, &cfg.topdayentries, 0, 0 },
                { "DaemonUser", cfg.daemonuser, 0, 33, 0 },
                { "DaemonGroup", cfg.daemongroup, 0, 33, 0 },
                { "UpdateInterval", 0, &cfg.updateinterval, 0, 0 },
@@ -297,69 +311,72 @@ int loadcfg(const char *cfgfile)
 
 void validatecfg(void)
 {
+       const char *invalidvalue = "Invalid value for";
+       const char *resettingto = "resetting to";
+
        if (cfg.unitmode<0 || cfg.unitmode>1) {
                cfg.unitmode = UNITMODE;
-               snprintf(errorstring, 512, "Invalid value for UnitMode, resetting to \"%d\".", cfg.unitmode);
+               snprintf(errorstring, 512, "%s UnitMode, %s \"%d\".", invalidvalue, resettingto, cfg.unitmode);
                printe(PT_Config);
        }
 
        if (cfg.rateunitmode<0 || cfg.rateunitmode>1) {
                cfg.rateunitmode = RATEUNITMODE;
-               snprintf(errorstring, 512, "Invalid value for RateUnitMode, resetting to \"%d\".", cfg.rateunitmode);
+               snprintf(errorstring, 512, "%s RateUnitMode, %s \"%d\".", invalidvalue, resettingto, cfg.rateunitmode);
                printe(PT_Config);
        }
 
        if (cfg.ostyle<0 || cfg.ostyle>3) {
                cfg.ostyle = OSTYLE;
-               snprintf(errorstring, 512, "Invalid value for OutputStyle, resetting to \"%d\".", cfg.ostyle);
+               snprintf(errorstring, 512, "%s OutputStyle, %s \"%d\".", invalidvalue, resettingto, cfg.ostyle);
                printe(PT_Config);
        }
 
        if (cfg.bvar<0 || cfg.bvar>300) {
                cfg.bvar = BVAR;
-               snprintf(errorstring, 512, "Invalid value for BootVariation, resetting to \"%d\".", cfg.bvar);
+               snprintf(errorstring, 512, "%s BootVariation, %s \"%d\".", invalidvalue, resettingto, cfg.bvar);
                printe(PT_Config);
        }
 
        if (cfg.sampletime<2 || cfg.sampletime>600) {
                cfg.sampletime = DEFSAMPTIME;
-               snprintf(errorstring, 512, "Invalid value for Sampletime, resetting to \"%d\".", cfg.sampletime);
+               snprintf(errorstring, 512, "%s Sampletime, %s \"%d\".", invalidvalue, resettingto, cfg.sampletime);
                printe(PT_Config);
        }
 
        if (cfg.monthrotate<1 || cfg.monthrotate>28) {
                cfg.monthrotate = MONTHROTATE;
-               snprintf(errorstring, 512, "Invalid value for MonthRotate, resetting to \"%d\".", cfg.monthrotate);
+               snprintf(errorstring, 512, "%s MonthRotate, %s \"%d\".", invalidvalue, resettingto, cfg.monthrotate);
                printe(PT_Config);
        }
 
        if (cfg.maxbw<0 || cfg.maxbw>BWMAX) {
                cfg.maxbw = DEFMAXBW;
-               snprintf(errorstring, 512, "Invalid value for MaxBandwidth, resetting to \"%d\".", cfg.maxbw);
+               snprintf(errorstring, 512, "%s MaxBandwidth, %s \"%d\".", invalidvalue, resettingto, cfg.maxbw);
                printe(PT_Config);
        }
 
        if (cfg.spacecheck<0 || cfg.spacecheck>1) {
                cfg.spacecheck = USESPACECHECK;
-               snprintf(errorstring, 512, "Invalid value for CheckDiskSpace, resetting to \"%d\".", cfg.spacecheck);
+               snprintf(errorstring, 512, "%s CheckDiskSpace, %s \"%d\".", invalidvalue, resettingto, cfg.spacecheck);
                printe(PT_Config);
        }
 
        if (cfg.flock<0 || cfg.flock>1) {
                cfg.flock = USEFLOCK;
-               snprintf(errorstring, 512, "Invalid value for UseFileLocking, resetting to \"%d\".", cfg.flock);
+               snprintf(errorstring, 512, "%s UseFileLocking, %s \"%d\".", invalidvalue, resettingto, cfg.flock);
                printe(PT_Config);
        }
 
        if (cfg.dbdir[0] != '/') {
                strncpy_nt(cfg.dbdir, DATABASEDIR, 512);
-               snprintf(errorstring, 512, "DatabaseDir doesn't start with \"/\", resetting to default.");
+               snprintf(errorstring, 512, "DatabaseDir doesn't start with \"/\", %s default.", resettingto);
                printe(PT_Config);
        }
 
        if (cfg.pollinterval<2 || cfg.pollinterval>60) {
                cfg.pollinterval = POLLINTERVAL;
-               snprintf(errorstring, 512, "Invalid value for PollInterval, resetting to \"%d\".", cfg.pollinterval);
+               snprintf(errorstring, 512, "%s PollInterval, %s \"%d\".", invalidvalue, resettingto, cfg.pollinterval);
                printe(PT_Config);
        }
 
@@ -369,7 +386,7 @@ void validatecfg(void)
                } else {
                        cfg.updateinterval = UPDATEINTERVAL;
                }
-               snprintf(errorstring, 512, "Invalid value for UpdateInterval, resetting to \"%d\".", cfg.updateinterval);
+               snprintf(errorstring, 512, "%s UpdateInterval, %s \"%d\".", invalidvalue, resettingto, cfg.updateinterval);
                printe(PT_Config);
        }
 
@@ -379,7 +396,7 @@ void validatecfg(void)
                } else {
                        cfg.saveinterval = SAVEINTERVAL;
                }
-               snprintf(errorstring, 512, "Invalid value for SaveInterval, resetting to \"%d\".", cfg.saveinterval);
+               snprintf(errorstring, 512, "%s SaveInterval, %s \"%d\".", invalidvalue, resettingto, cfg.saveinterval);
                printe(PT_Config);
        }
 
@@ -389,85 +406,121 @@ void validatecfg(void)
                } else {
                        cfg.offsaveinterval = OFFSAVEINTERVAL;
                }
-               snprintf(errorstring, 512, "Invalid value for OfflineSaveInterval, resetting to \"%d\".", cfg.offsaveinterval);
+               snprintf(errorstring, 512, "%s OfflineSaveInterval, %s \"%d\".", invalidvalue, resettingto, cfg.offsaveinterval);
                printe(PT_Config);
        }
 
        if (cfg.savestatus<0 || cfg.savestatus>1) {
                cfg.savestatus = SAVESTATUS;
-               snprintf(errorstring, 512, "Invalid value for SaveOnStatusChange, resetting to \"%d\".", cfg.savestatus);
+               snprintf(errorstring, 512, "%s SaveOnStatusChange, %s \"%d\".", invalidvalue, resettingto, cfg.savestatus);
                printe(PT_Config);
        }
 
        if (cfg.uselogging<0 || cfg.uselogging>2) {
                cfg.uselogging = USELOGGING;
-               snprintf(errorstring, 512, "Invalid value for UseLogging, resetting to \"%d\".", cfg.uselogging);
+               snprintf(errorstring, 512, "%s UseLogging, %s \"%d\".", invalidvalue, resettingto, cfg.uselogging);
                printe(PT_Config);
        }
 
        if (cfg.createdirs<0 || cfg.createdirs>2) {
                cfg.createdirs = CREATEDIRS;
-               snprintf(errorstring, 512, "Invalid value for CreateDirs, resetting to \"%d\".", cfg.createdirs);
+               snprintf(errorstring, 512, "%s CreateDirs, %s \"%d\".", invalidvalue, resettingto, cfg.createdirs);
                printe(PT_Config);
        }
 
        if (cfg.updatefileowner<0 || cfg.updatefileowner>2) {
                cfg.updatefileowner = UPDATEFILEOWNER;
-               snprintf(errorstring, 512, "Invalid value for UpdateFileOwner, resetting to \"%d\".", cfg.updatefileowner);
+               snprintf(errorstring, 512, "%s UpdateFileOwner, %s \"%d\".", invalidvalue, resettingto, cfg.updatefileowner);
                printe(PT_Config);
        }
 
        if (cfg.logfile[0] != '/') {
                strncpy_nt(cfg.logfile, LOGFILE, 512);
-               snprintf(errorstring, 512, "LogFile doesn't start with \"/\", resetting to default.");
+               snprintf(errorstring, 512, "LogFile doesn't start with \"/\", %s default.", resettingto);
                printe(PT_Config);
        }
 
        if (cfg.pidfile[0] != '/') {
                strncpy_nt(cfg.pidfile, PIDFILE, 512);
-               snprintf(errorstring, 512, "PidFile doesn't start with \"/\", resetting to default.");
+               snprintf(errorstring, 512, "PidFile doesn't start with \"/\", %s default.", resettingto);
                printe(PT_Config);
        }
 
        if (cfg.transbg<0 || cfg.transbg>1) {
                cfg.transbg = TRANSBG;
-               snprintf(errorstring, 512, "Invalid value for TransparentBg, resetting to \"%d\".", cfg.transbg);
+               snprintf(errorstring, 512, "%s TransparentBg, %s \"%d\".", invalidvalue, resettingto, cfg.transbg);
                printe(PT_Config);
        }
 
        if (cfg.hourlyrate<0 || cfg.hourlyrate>1) {
                cfg.hourlyrate = HOURLYRATE;
-               snprintf(errorstring, 512, "Invalid value for HourlyRate, resetting to \"%d\".", cfg.hourlyrate);
+               snprintf(errorstring, 512, "%s HourlyRate, %s \"%d\".", invalidvalue, resettingto, cfg.hourlyrate);
                printe(PT_Config);
        }
 
        if (cfg.summaryrate<0 || cfg.summaryrate>1) {
                cfg.summaryrate = SUMMARYRATE;
-               snprintf(errorstring, 512, "Invalid value for SummaryRate, resetting to \"%d\".", cfg.summaryrate);
+               snprintf(errorstring, 512, "%s SummaryRate, %s \"%d\".", invalidvalue, resettingto, cfg.summaryrate);
                printe(PT_Config);
        }
 
        if (cfg.slayout<0 || cfg.slayout>1) {
                cfg.slayout = SUMMARYLAYOUT;
-               snprintf(errorstring, 512, "Invalid value for SummaryLayout, resetting to \"%d\".", cfg.slayout);
+               snprintf(errorstring, 512, "%s SummaryLayout, %s \"%d\".", invalidvalue, resettingto, cfg.slayout);
                printe(PT_Config);
        }
 
        if (cfg.traflessday<0 || cfg.traflessday>1) {
                cfg.traflessday = TRAFLESSDAY;
-               snprintf(errorstring, 512, "Invalid value for TrafficlessDays, resetting to \"%d\".", cfg.transbg);
+               snprintf(errorstring, 512, "%s TrafficlessDays, %s \"%d\".", invalidvalue, resettingto, cfg.traflessday);
+               printe(PT_Config);
+       }
+
+       if (cfg.fiveminutehours<-1) {
+               cfg.fiveminutehours = FIVEMINUTEHOURS;
+               snprintf(errorstring, 512, "%s 5MinuteHours, %s \"%d\".", invalidvalue, resettingto, cfg.fiveminutehours);
+               printe(PT_Config);
+       }
+
+       if (cfg.hourlydays<-1) {
+               cfg.hourlydays = HOURLYDAYS;
+               snprintf(errorstring, 512, "%s HourlyDays, %s \"%d\".", invalidvalue, resettingto, cfg.hourlydays);
+               printe(PT_Config);
+       }
+
+       if (cfg.dailydays<-1) {
+               cfg.dailydays = DAILYDAYS;
+               snprintf(errorstring, 512, "%s DailyDays, %s \"%d\".", invalidvalue, resettingto, cfg.dailydays);
+               printe(PT_Config);
+       }
+
+       if (cfg.monthlymonths<-1) {
+               cfg.monthlymonths = MONTHLYMONTHS;
+               snprintf(errorstring, 512, "%s MonthlyMonths, %s \"%d\".", invalidvalue, resettingto, cfg.monthlymonths);
+               printe(PT_Config);
+       }
+
+       if (cfg.yearlyyears<-1) {
+               cfg.yearlyyears = YEARLYYEARS;
+               snprintf(errorstring, 512, "%s YearlyYears, %s \"%d\".", invalidvalue, resettingto, cfg.yearlyyears);
+               printe(PT_Config);
+       }
+
+       if (cfg.topdayentries<-1) {
+               cfg.topdayentries = TOPDAYENTRIES;
+               snprintf(errorstring, 512, "%s TopDayEntries, %s \"%d\".", invalidvalue, resettingto, cfg.topdayentries);
                printe(PT_Config);
        }
 
        if (cfg.bwdetection<0 || cfg.bwdetection>1) {
                cfg.bwdetection = BWDETECT;
-               snprintf(errorstring, 512, "Invalid value for BandwidthDetection, resetting to \"%d\".", cfg.bwdetection);
+               snprintf(errorstring, 512, "%s BandwidthDetection, %s \"%d\".", invalidvalue, resettingto, cfg.bwdetection);
                printe(PT_Config);
        }
 
        if (cfg.bwdetectioninterval<0 || cfg.bwdetectioninterval>30) {
                cfg.bwdetectioninterval = BWDETECTINTERVAL;
-               snprintf(errorstring, 512, "Invalid value for BandwidthDetectionInterval, resetting to \"%d\".", cfg.bwdetectioninterval);
+               snprintf(errorstring, 512, "%s BandwidthDetectionInterval, %s \"%d\".", invalidvalue, resettingto, cfg.bwdetectioninterval);
                printe(PT_Config);
        }
 }
@@ -494,6 +547,14 @@ void defaultcfg(void)
        cfg.slayout = SUMMARYLAYOUT;
        cfg.traflessday = TRAFLESSDAY;
        cfg.utflocale = UTFLOCALE;
+
+       cfg.fiveminutehours = FIVEMINUTEHOURS;
+       cfg.hourlydays = HOURLYDAYS;
+       cfg.dailydays = DAILYDAYS;
+       cfg.monthlymonths = MONTHLYMONTHS;
+       cfg.yearlyyears = YEARLYYEARS;
+       cfg.topdayentries = TOPDAYENTRIES;
+
        strncpy_nt(cfg.dbdir, DATABASEDIR, 512);
        strncpy_nt(cfg.iface, DEFIFACE, 32);
        strncpy_nt(cfg.locale, LOCALE, 32);
index 301672914ff5531f6b11a455a2ed2b68ddae5dc1..4231a146d32d22042349bfc54e272d42756ab386 100644 (file)
@@ -148,6 +148,14 @@ and most can be changed later from the config file.
 /* log trafficless days by default */
 #define TRAFLESSDAY 1
 
+/* data retention defaults */
+#define FIVEMINUTEHOURS 48
+#define HOURLYDAYS 2
+#define DAILYDAYS 30
+#define MONTHLYMONTHS 12
+#define YEARLYYEARS -1
+#define TOPDAYENTRIES 10
+
 /* assume that locale can be UTF-n when enabled */
 #define UTFLOCALE 1
 
@@ -231,6 +239,7 @@ typedef struct {
        char daemonuser[33], daemongroup[33];
        int32_t updateinterval, pollinterval, saveinterval, offsaveinterval, savestatus, uselogging;
        int32_t createdirs, updatefileowner, bwdetection, bwdetectioninterval, utflocale;
+       int32_t fiveminutehours, hourlydays, dailydays, monthlymonths, yearlyyears, topdayentries;
 } CFG;
 
 /* internal interface information structure */
index 24403b40be069f2e0f8db38f9251476c777ef5d9..a86889516c06f1ab23aad1e2936553d181c73ede 100644 (file)
@@ -502,6 +502,7 @@ int db_addtraffic_dated(const char *iface, const uint64_t rx, const uint64_t tx,
        }
 
        /* time specific */
+       /* TODO: skip if feature disabled in configuration */
        for (i=0; i<5; i++) {
                snprintf(datebuffer, 512, datadates[i], nowdate);
                sqlite3_snprintf(1024, sql, "insert or ignore into %s (interface, date, rx, tx) values (%"PRId64", %s, 0, 0);", datatables[i], (int64_t)ifaceid, datebuffer);
@@ -591,47 +592,61 @@ int db_removeoldentries(void)
                return 0;
        }
 
-       /* TODO: read cleanup limits from configuration and actually use this function somewhere */
+       /* TODO: actually use this function somewhere */
        /* running this about once every hour during cache flush would keep the fiveminute table from accumulating too much excess data */
 
-       sqlite3_snprintf(512, sql, "delete from fiveminute where date < datetime('now', '-48 hours', 'localtime');");
-       if (!db_exec(sql)) {
-               db_rollbacktransaction();
-               return 0;
+       if (cfg.fiveminutehours > 0) {
+               sqlite3_snprintf(512, sql, "delete from fiveminute where date < datetime('now', '-%d hours', 'localtime');", cfg.fiveminutehours);
+               if (!db_exec(sql)) {
+                       db_rollbacktransaction();
+                       return 0;
+               }
        }
 
-       sqlite3_snprintf(512, sql, "delete from hour where date < datetime('now', '-7 days', 'localtime');");
-       if (!db_exec(sql)) {
-               db_rollbacktransaction();
-               return 0;
+       if (cfg.hourlydays > 0) {
+               sqlite3_snprintf(512, sql, "delete from hour where date < datetime('now', '-%d days', 'localtime');", cfg.hourlydays);
+               if (!db_exec(sql)) {
+                       db_rollbacktransaction();
+                       return 0;
+               }
        }
 
-       sqlite3_snprintf(512, sql, "delete from day where date < date('now', '-30 days', 'localtime');");
-       if (!db_exec(sql)) {
-               db_rollbacktransaction();
-               return 0;
+       if (cfg.dailydays > 0) {
+               sqlite3_snprintf(512, sql, "delete from day where date < date('now', '-%d days', 'localtime');", cfg.dailydays);
+               if (!db_exec(sql)) {
+                       db_rollbacktransaction();
+                       return 0;
+               }
        }
 
-       sqlite3_snprintf(512, sql, "delete from month where date < date('now', '-12 months', 'localtime');");
-       if (!db_exec(sql)) {
-               db_rollbacktransaction();
-               return 0;
+       if (cfg.monthlymonths > 0) {
+               sqlite3_snprintf(512, sql, "delete from month where date < date('now', '-%d months', 'localtime');", cfg.monthlymonths);
+               if (!db_exec(sql)) {
+                       db_rollbacktransaction();
+                       return 0;
+               }
        }
 
-       sqlite3_snprintf(512, sql, "delete from year where date < date('now', '-10 years', 'localtime');");
-       if (!db_exec(sql)) {
-               db_rollbacktransaction();
-               return 0;
+       if (cfg.yearlyyears > 0) {
+               sqlite3_snprintf(512, sql, "delete from year where date < date('now', '-%d years', 'localtime');", cfg.yearlyyears);
+               if (!db_exec(sql)) {
+                       db_rollbacktransaction();
+                       return 0;
+               }
        }
 
        /* TODO: rewrite to handle entries per interface and use select for getting entry list */
        /* as the syntax below works only when sqlite is compiled with SQLITE_ENABLE_UPDATE_DELETE_LIMIT */
        /* causing failure in at least in Ubuntu <= 12.04, RHEL, Fedora and CentOS */
-       /*sqlite3_snprintf(512, sql, "delete from top order by rx+tx desc limit -1 offset 10;");
-       if (!db_exec(sql)) {
-               db_rollbacktransaction();
-               return 0;
-       }*/
+       /*
+       if (cfg.topdayentries > 0) {
+               sqlite3_snprintf(512, sql, "delete from top order by rx+tx desc limit -1 offset %d;", cfg.topdayentries);
+               if (!db_exec(sql)) {
+                       db_rollbacktransaction();
+                       return 0;
+               }
+       }
+       */
 
        return db_committransaction();
 }