From a48e8fd16d338c8e391939bd4e90f160c2f98326 Mon Sep 17 00:00:00 2001 From: themylogin Date: Mon, 27 Aug 2018 19:25:04 +0300 Subject: [PATCH] LogOnce option for df plugin Enabling LogOnce true option in df plugin reduces syslog spam when stat constantly fails for any of the mounted partitions. --- src/collectd.conf.in | 1 + src/collectd.conf.pod | 4 ++++ src/df.c | 27 ++++++++++++++++++++++++--- src/utils/ignorelist/ignorelist.c | 31 +++++++++++++++++++++++++++++++ src/utils/ignorelist/ignorelist.h | 6 ++++++ 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 9e30358b5..007f80eff 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -578,6 +578,7 @@ # MountPoint "/home" # FSType "ext3" # IgnoreSelected false +# LogOnce false # ReportByDevice false # ReportInodes false # ValuesAbsolute true diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 7e761b45c..9ef529afa 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -2745,6 +2745,10 @@ match any one of the criteria are collected. By default only selected partitions are collected if a selection is made. If no selection is configured at all, B partitions are selected. +=item B B|B + +Only log stat() errors once. + =item B B|B Report using the device name rather than the mountpoint. i.e. with this I, diff --git a/src/df.c b/src/df.c index 5b3fbd28e..60f20d3e8 100644 --- a/src/df.c +++ b/src/df.c @@ -47,18 +47,21 @@ #endif static const char *config_keys[] = { - "Device", "MountPoint", "FSType", "IgnoreSelected", - "ReportByDevice", "ReportInodes", "ValuesAbsolute", "ValuesPercentage"}; + "Device", "MountPoint", "FSType", + "IgnoreSelected", "ReportByDevice", "ReportInodes", + "ValuesAbsolute", "ValuesPercentage", "LogOnce"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static ignorelist_t *il_device; static ignorelist_t *il_mountpoint; static ignorelist_t *il_fstype; +static ignorelist_t *il_errors; static bool by_device; static bool report_inodes; static bool values_absolute = true; static bool values_percentage; +static bool log_once; static int df_init(void) { if (il_device == NULL) @@ -67,6 +70,8 @@ static int df_init(void) { il_mountpoint = ignorelist_create(1); if (il_fstype == NULL) il_fstype = ignorelist_create(1); + if (il_errors == NULL) + il_errors = ignorelist_create(1); return 0; } @@ -122,6 +127,13 @@ static int df_config(const char *key, const char *value) { else values_percentage = false; + return 0; + } else if (strcasecmp(key, "LogOnce") == 0) { + if (IS_TRUE(value)) + log_once = true; + else + log_once = false; + return 0; } @@ -203,8 +215,17 @@ static int df_read(void) { continue; if (STATANYFS(mnt_ptr->dir, &statbuf) < 0) { - ERROR(STATANYFS_STR "(%s) failed: %s", mnt_ptr->dir, STRERRNO); + if (log_once == false || ignorelist_match(il_errors, mnt_ptr->dir) == 0) { + if (log_once == true) { + ignorelist_add(il_errors, mnt_ptr->dir); + } + ERROR(STATANYFS_STR "(%s) failed: %s", mnt_ptr->dir, STRERRNO); + } continue; + } else { + if (log_once == true) { + ignorelist_remove(il_errors, mnt_ptr->dir); + } } if (!statbuf.f_blocks) diff --git a/src/utils/ignorelist/ignorelist.c b/src/utils/ignorelist/ignorelist.c index 9e1b9e3a2..f0298e8dc 100644 --- a/src/utils/ignorelist/ignorelist.c +++ b/src/utils/ignorelist/ignorelist.c @@ -278,6 +278,37 @@ int ignorelist_add(ignorelist_t *il, const char *entry) { return ignorelist_append_string(il, entry); } /* int ignorelist_add (ignorelist_t *il, const char *entry) */ +/* + * remove entry from ignorelist_t + * return 0 for success + */ +int ignorelist_remove(ignorelist_t *il, const char *entry) { + /* if no entries, nothing to remove */ + if ((il == NULL) || (il->head == NULL)) + return (1); + + if ((entry == NULL) || (strlen(entry) == 0)) + return (1); + + /* traverse list and check entries */ + for (ignorelist_item_t *prev = NULL, *traverse = il->head; traverse != NULL; + prev = traverse, traverse = traverse->next) { + if (traverse->smatch != NULL && strcmp(traverse->smatch, entry) == 0) { + if (prev == NULL) { + il->head = traverse->next; + } else { + prev->next = traverse->next; + } + sfree(traverse->smatch); + traverse->smatch = NULL; + sfree(traverse); + return (0); + } + } /* for traverse */ + + return (1); +} /* int ignorelist_remove (ignorelist_t *il, const char *entry) */ + /* * check list for entry * return 1 for ignored entry diff --git a/src/utils/ignorelist/ignorelist.h b/src/utils/ignorelist/ignorelist.h index a7fa86d54..5b8d3a67a 100644 --- a/src/utils/ignorelist/ignorelist.h +++ b/src/utils/ignorelist/ignorelist.h @@ -60,6 +60,12 @@ void ignorelist_set_invert(ignorelist_t *il, int invert); */ int ignorelist_add(ignorelist_t *il, const char *entry); +/* + * remote entry from ignorelist_t + * returns zero on success, non-zero upon failure. + */ +int ignorelist_remove(ignorelist_t *il, const char *entry); + /* * check list for entry * return 1 for ignored entry -- 2.47.2