]> git.ipfire.org Git - oddments/collecty.git/commitdiff
source: Don't try to commit metrics too soon
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 22 Oct 2025 19:26:42 +0000 (19:26 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 22 Oct 2025 19:26:42 +0000 (19:26 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/daemon/source.c

index 009925106f9dc47bd89762800b2af8a0785a6ab6..002aa4988a5da79fbf6bf0ec2751408e6d452d81 100644 (file)
@@ -907,12 +907,45 @@ static int td_source_fetch_lastupdate(td_source* self, rrd_info_t* info, time_t*
        return 0;
 }
 
+static int td_source_serialize_metrics(td_source* self, char*** samples,
+               unsigned int num_metrics, td_metrics** metrics, time_t lastupdate) {
+       const struct timeval* t = NULL;
+       char sample[4096];
+       int r;
+
+       for (unsigned int i = 0; i < num_metrics; i++) {
+               // Fetch the time of the metric
+               t = td_metrics_get_time(metrics[i]);
+
+               // RRD throws an error if we try to write more than one sample per second.
+               // Therefore, we will throw away all metrics that have been collected too soon.
+               if (lastupdate && t->tv_sec <= lastupdate) {
+                       DEBUG(self->ctx, "Throwing away metric for %s which has been collected too soon\n",
+                               td_source_name(self));
+                       continue;
+               }
+
+               // Serialize the metrics
+               r = td_metrics_serialize(metrics[i], sample);
+               if (r < 0)
+                       return r;
+
+               // Append it to the array
+               r = td_strings_append(samples, sample);
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
+}
+
 /*
-       Called to write all collected samples to disk
+       Called to write all collected metrics to disk
 */
-static int td_source_commit_samples(td_source* self,
-               const char* object, unsigned int num_samples, const char** samples) {
+int td_source_commit_metrics(td_source* self, const char* object,
+               unsigned int num_metrics, td_metrics** metrics) {
        rrd_info_t* info = NULL;
+       char** samples = NULL;
        time_t lastupdate = 0;
        char path[PATH_MAX];
        int r;
@@ -951,45 +984,26 @@ static int td_source_commit_samples(td_source* self,
                        goto ERROR;
        }
 
-       // Write the samples
-       r = rrd_update_r(path, NULL, num_samples, samples);
-       if (r < 0) {
-               ERROR(self->ctx, "Failed to write to %s: %s\n", path, rrd_get_error());
-               rrd_clear_error();
-               return -EFAULT;
-       }
-
-ERROR:
-       if (info)
-               rrd_info_free(info);
-
-       return r;
-}
-
-int td_source_commit_metrics(td_source* self, const char* object,
-               unsigned int num_metrics, td_metrics** metrics) {
-       char** samples = NULL;
-       char sample[4096];
-       int r;
-
-       for (unsigned int i = 0; i < num_metrics; i++) {
-               // Serialize the metrics
-               r = td_metrics_serialize(metrics[i], sample);
-               if (r < 0)
-                       goto ERROR;
+       // Serialize the samples
+       r = td_source_serialize_metrics(self, &samples, num_metrics, metrics, lastupdate);
+       if (r < 0)
+               goto ERROR;
 
-               // Append it to the array
-               r = td_strings_append(&samples, sample);
-               if (r < 0)
-                       goto ERROR;
+       // Write the samples
+       if (samples) {
+               r = rrd_update_r(path, NULL, td_strings_length(samples), (const char**)samples);
+               if (r < 0) {
+                       ERROR(self->ctx, "Failed to write to %s: %s\n", path, rrd_get_error());
+                       rrd_clear_error();
+                       return -EFAULT;
+               }
        }
 
-       // Commit the samples
-       r = td_source_commit_samples(self, object, num_metrics, (const char**)samples);
-
 ERROR:
        if (samples)
                td_strings_free(samples);
+       if (info)
+               rrd_info_free(info);
 
        return r;
 }