]> arthur.barton.de Git - netdata.git/commitdiff
validate and verify microseconds passed by plugins
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Mon, 7 Nov 2016 21:06:46 +0000 (23:06 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Mon, 7 Nov 2016 21:06:46 +0000 (23:06 +0200)
src/rrd.c
src/rrd.h

index f9b5d4e04971ab008e70faf0fbafeeb64330e062..ebcbc5cc713a7902b95b903e94db4c5fbd3c53c3 100644 (file)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -974,35 +974,52 @@ collected_number rrddim_set(RRDSET *st, const char *id, collected_number value)
     return rrddim_set_by_pointer(st, rd, value);
 }
 
-void rrdset_next_usec(RRDSET *st, unsigned long long microseconds)
+void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds)
 {
-    if(!microseconds) rrdset_next(st);
-    else {
-        debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds);
-
-        if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds);
-        st->usec_since_last_update = microseconds;
+    if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) {
+        // the first entry
+        microseconds = st->update_every * 1000000ULL;
     }
+    st->usec_since_last_update = microseconds;
 }
 
-void rrdset_next(RRDSET *st)
+void rrdset_next_usec(RRDSET *st, unsigned long long microseconds)
 {
-    unsigned long long microseconds = 0;
+    struct timeval now;
+    gettimeofday(&now, NULL);
 
-    if(likely(st->last_collected_time.tv_sec)) {
-        struct timeval now;
-        gettimeofday(&now, NULL);
+    if(unlikely(!st->last_collected_time.tv_sec)) {
+        // the first entry
+        microseconds = st->update_every * 1000000ULL;
+    }
+    else if(unlikely(!microseconds)) {
+        // no dt given by the plugin
         microseconds = usec_dt(&now, &st->last_collected_time);
     }
-    // prevent infinite loop
-    else microseconds = st->update_every * 1000000ULL;
+    else {
+        // microseconds has the time since the last collection
+        unsigned long long now_usec = timeval_usec(&now);
+        unsigned long long last_usec = timeval_usec(&st->last_collected_time);
+        unsigned long long since_last_usec = usec_dt(&now, &st->last_collected_time);
 
-    rrdset_next_usec(st, microseconds);
-}
+        // verify the microseconds given is good
+        if(unlikely(last_usec + microseconds > now_usec)) {
+            debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with dt %llu is %llu usec to the future", st->name, microseconds, last_usec + microseconds - now_usec);
 
-void rrdset_next_plugins(RRDSET *st)
-{
-    rrdset_next(st);
+            if(unlikely(last_usec + microseconds > now_usec + 10000))
+                error("Invalid dt %llu usec given - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, last_usec + microseconds - now_usec, st->name, st->id);
+
+            microseconds = since_last_usec;
+        }
+        else if(unlikely(microseconds < since_last_usec * 0.2 || microseconds > since_last_usec * 1.2)) {
+            error("Invalid dt %llu usec given - expected %llu usec +/- 20%%, for chart '%s' (%s).", microseconds, since_last_usec, st->name, st->id);
+            microseconds = since_last_usec;
+        }
+    }
+    debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds);
+
+    if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds);
+    st->usec_since_last_update = microseconds;
 }
 
 unsigned long long rrdset_done(RRDSET *st)
index 92a65fe8a7beb77a54032480f12cf54390e4b541..f0d86540ddd62bb321438b4df7b229cde17d0c68 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -355,9 +355,9 @@ extern RRDSET *rrdset_find(const char *id);
 extern RRDSET *rrdset_find_bytype(const char *type, const char *id);
 extern RRDSET *rrdset_find_byname(const char *name);
 
+extern void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds);
 extern void rrdset_next_usec(RRDSET *st, unsigned long long microseconds);
-extern void rrdset_next(RRDSET *st);
-extern void rrdset_next_plugins(RRDSET *st);
+#define rrdset_next(st) rrdset_next_usec(st, 0ULL)
 
 extern unsigned long long rrdset_done(RRDSET *st);