X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=src%2Fplugin_proc_diskspace.c;h=37133e044955059ce87e56f25705c2e12f37d18e;hb=909e26f825bc1f6f907231761412c885331fec7e;hp=43e6dd7c5594e19120bb3f8e09171110dd3d9845;hpb=f0e24433ec499294378bc02c33a900cc733ebad2;p=netdata.git diff --git a/src/plugin_proc_diskspace.c b/src/plugin_proc_diskspace.c index 43e6dd7c..37133e04 100644 --- a/src/plugin_proc_diskspace.c +++ b/src/plugin_proc_diskspace.c @@ -1,6 +1,8 @@ #include "common.h" -#define DELAULT_EXLUDED_PATHS "/proc/* /sys/* /var/run/user/* /run/user/*" +#define DELAULT_EXLUDED_PATHS "/proc/* /sys/* /var/run/user/* /run/user/* /snap/* /var/lib/docker/*" +#define DEFAULT_EXCLUDED_FILESYSTEMS "" +#define CONFIG_SECTION_DISKSPACE "plugin:proc:diskspace" static struct mountinfo *disk_mountinfo_root = NULL; static int check_for_new_mountpoints_every = 15; @@ -14,17 +16,19 @@ static inline void mountinfo_reload(int force) { mountinfo_free(disk_mountinfo_root); // re-read mountinfo in case something changed - disk_mountinfo_root = mountinfo_read(1); + disk_mountinfo_root = mountinfo_read(0); last_loaded = now; } } -// Data to be stored in DICTIONARY mount_points used by do_disk_space_stats(). +// Data to be stored in DICTIONARY dict_mountpoints used by do_disk_space_stats(). // This DICTIONARY is used to lookup the settings of the mount point on each iteration. struct mount_point_metadata { int do_space; int do_inodes; + int shown_error; + int updated; size_t collected; // the number of times this has been collected @@ -39,41 +43,86 @@ struct mount_point_metadata { RRDDIM *rd_inodes_reserved; }; +static DICTIONARY *dict_mountpoints = NULL; + +#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE); st = NULL; } } while(st) + +int mount_point_cleanup(void *entry, void *data) { + (void)data; + + struct mount_point_metadata *mp = (struct mount_point_metadata *)entry; + if(!mp) return 0; + + if(likely(mp->updated)) { + mp->updated = 0; + return 0; + } + + if(likely(mp->collected)) { + mp->collected = 0; + mp->updated = 0; + mp->shown_error = 0; + + mp->rd_space_avail = NULL; + mp->rd_space_used = NULL; + mp->rd_space_reserved = NULL; + + mp->rd_inodes_avail = NULL; + mp->rd_inodes_used = NULL; + mp->rd_inodes_reserved = NULL; + + rrdset_obsolete_and_pointer_null(mp->st_space); + rrdset_obsolete_and_pointer_null(mp->st_inodes); + } + + return 0; +} + static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { const char *family = mi->mount_point; const char *disk = mi->persistent_id; - static DICTIONARY *mount_points = NULL; static SIMPLE_PATTERN *excluded_mountpoints = NULL; + static SIMPLE_PATTERN *excluded_filesystems = NULL; int do_space, do_inodes; - if(unlikely(!mount_points)) { - const char *s; + if(unlikely(!dict_mountpoints)) { SIMPLE_PREFIX_MODE mode = SIMPLE_PATTERN_EXACT; - if(config_exists("plugin:proc:/proc/diskstats", "exclude space metrics on paths") && !config_exists("plugin:proc:diskspace", "exclude space metrics on paths")) { - // the config exists in the old section - s = config_get("plugin:proc:/proc/diskstats", "exclude space metrics on paths", DELAULT_EXLUDED_PATHS); + if(config_move("plugin:proc:/proc/diskstats", "exclude space metrics on paths", CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths") != -1) { + // old configuration, enable backwards compatibility mode = SIMPLE_PATTERN_PREFIX; } - else - s = config_get("plugin:proc:diskspace", "exclude space metrics on paths", DELAULT_EXLUDED_PATHS); - mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); - excluded_mountpoints = simple_pattern_create(s, mode); + excluded_mountpoints = simple_pattern_create( + config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths", DELAULT_EXLUDED_PATHS), + mode + ); + + excluded_filesystems = simple_pattern_create( + config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on filesystems", DEFAULT_EXCLUDED_FILESYSTEMS), + SIMPLE_PATTERN_EXACT + ); + + dict_mountpoints = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); } - struct mount_point_metadata *m = dictionary_get(mount_points, mi->mount_point); + struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point); if(unlikely(!m)) { char var_name[4096 + 1]; snprintfz(var_name, 4096, "plugin:proc:diskspace:%s", mi->mount_point); - int def_space = config_get_boolean_ondemand("plugin:proc:diskspace", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND); - int def_inodes = config_get_boolean_ondemand("plugin:proc:diskspace", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND); + int def_space = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "space usage for all disks", CONFIG_BOOLEAN_AUTO); + int def_inodes = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO); if(unlikely(simple_pattern_matches(excluded_mountpoints, mi->mount_point))) { - def_space = CONFIG_ONDEMAND_NO; - def_inodes = CONFIG_ONDEMAND_NO; + def_space = CONFIG_BOOLEAN_NO; + def_inodes = CONFIG_BOOLEAN_NO; + } + + if(unlikely(simple_pattern_matches(excluded_filesystems, mi->filesystem))) { + def_space = CONFIG_BOOLEAN_NO; + def_inodes = CONFIG_BOOLEAN_NO; } do_space = config_get_boolean_ondemand(var_name, "space usage", def_space); @@ -82,6 +131,8 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { struct mount_point_metadata mp = { .do_space = do_space, .do_inodes = do_inodes, + .shown_error = 0, + .updated = 0, .collected = 0, @@ -96,14 +147,12 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { .rd_inodes_reserved = NULL }; - m = dictionary_set(mount_points, mi->mount_point, &mp, sizeof(struct mount_point_metadata)); - } - else { - do_space = m->do_space; - do_inodes = m->do_inodes; + m = dictionary_set(dict_mountpoints, mi->mount_point, &mp, sizeof(struct mount_point_metadata)); } - if(unlikely(do_space == CONFIG_ONDEMAND_NO && do_inodes == CONFIG_ONDEMAND_NO)) + m->updated = 1; + + if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO)) return; if(unlikely(mi->flags & MOUNTINFO_READONLY && !m->collected)) @@ -111,9 +160,18 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { struct statvfs buff_statvfs; if (statvfs(mi->mount_point, &buff_statvfs) < 0) { - error("Failed statvfs() for '%s' (disk '%s')", mi->mount_point, disk); + if(!m->shown_error) { + error("Failed statvfs() for '%s' (disk '%s', filesystem '%s', root '%s')" + , mi->mount_point + , disk + , mi->filesystem?mi->filesystem:"" + , mi->root?mi->root:"" + ); + m->shown_error = 1; + } return; } + m->shown_error = 0; // logic found at get_fs_usage() in coreutils unsigned long bsize = (buff_statvfs.f_frsize) ? buff_statvfs.f_frsize : buff_statvfs.f_bsize; @@ -150,19 +208,30 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { int rendered = 0; - if(do_space == CONFIG_ONDEMAND_YES || (do_space == CONFIG_ONDEMAND_ONDEMAND && (bavail || breserved_root || bused))) { + if(m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (bavail || breserved_root || bused))) { if(unlikely(!m->st_space)) { - m->do_space = CONFIG_ONDEMAND_YES; - m->st_space = rrdset_find_bytype("disk_space", disk); + m->do_space = CONFIG_BOOLEAN_YES; + m->st_space = rrdset_find_bytype_localhost("disk_space", disk); if(unlikely(!m->st_space)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mi->mount_source); - m->st_space = rrdset_create("disk_space", disk, NULL, family, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED); + m->st_space = rrdset_create_localhost( + "disk_space" + , disk + , NULL + , family + , "disk.space" + , title + , "GB" + , 2023 + , update_every + , RRDSET_TYPE_STACKED + ); } - m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL, bsize, 1024 * 1024 * 1024, RRDDIM_ABSOLUTE); - m->rd_space_used = rrddim_add(m->st_space, "used", NULL, bsize, 1024 * 1024 * 1024, RRDDIM_ABSOLUTE); - m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", bsize, 1024 * 1024 * 1024, RRDDIM_ABSOLUTE); + m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + m->rd_space_used = rrddim_add(m->st_space, "used", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(m->st_space); @@ -177,19 +246,30 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { // -------------------------------------------------------------------------- - if(do_inodes == CONFIG_ONDEMAND_YES || (do_inodes == CONFIG_ONDEMAND_ONDEMAND && (favail || freserved_root || fused))) { + if(m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (favail || freserved_root || fused))) { if(unlikely(!m->st_inodes)) { - m->do_inodes = CONFIG_ONDEMAND_YES; - m->st_inodes = rrdset_find_bytype("disk_inodes", disk); + m->do_inodes = CONFIG_BOOLEAN_YES; + m->st_inodes = rrdset_find_bytype_localhost("disk_inodes", disk); if(unlikely(!m->st_inodes)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mi->mount_source); - m->st_inodes = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED); + m->st_inodes = rrdset_create_localhost( + "disk_inodes" + , disk + , NULL + , family + , "disk.inodes" + , title + , "Inodes" + , 2024 + , update_every + , RRDSET_TYPE_STACKED + ); } - m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE); - m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRDDIM_ABSOLUTE); - m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE); + m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(m->st_inodes); @@ -221,30 +301,23 @@ void *proc_diskspace_main(void *ptr) { int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1); - int update_every = (int)config_get_number("plugin:proc:diskspace", "update every", rrd_update_every); - if(update_every < rrd_update_every) - update_every = rrd_update_every; + int update_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "update every", localhost->rrd_update_every); + if(update_every < localhost->rrd_update_every) + update_every = localhost->rrd_update_every; - check_for_new_mountpoints_every = (int)config_get_number("plugin:proc:diskspace", "check for new mount points every", check_for_new_mountpoints_every); + check_for_new_mountpoints_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "check for new mount points every", check_for_new_mountpoints_every); if(check_for_new_mountpoints_every < update_every) check_for_new_mountpoints_every = update_every; struct rusage thread; - usec_t last = 0, dt = 0; + usec_t duration = 0; usec_t step = update_every * USEC_PER_SEC; + heartbeat_t hb; + heartbeat_init(&hb); for(;;) { - usec_t now = now_monotonic_usec(); - usec_t next = now - (now % step) + step; - - dt = (last)?now - last:0; - - while(now < next) { - sleep_usec(next - now); - now = now_monotonic_usec(); - } - - last = now; + duration = heartbeat_dt_usec(&hb); + /* usec_t hb_dt = */ heartbeat_next(&hb, step); if(unlikely(netdata_exit)) break; @@ -270,6 +343,8 @@ void *proc_diskspace_main(void *ptr) { if(unlikely(netdata_exit)) break; + dictionary_get_all(dict_mountpoints, mount_point_cleanup, NULL); + if(vdo_cpu_netdata) { static RRDSET *stcpu_thread = NULL, *st_duration = NULL; static RRDDIM *rd_user = NULL, *rd_system = NULL, *rd_duration = NULL; @@ -279,13 +354,23 @@ void *proc_diskspace_main(void *ptr) { getrusage(RUSAGE_THREAD, &thread); if(!stcpu_thread) { - stcpu_thread = rrdset_find("netdata.plugin_diskspace"); - if(!stcpu_thread) stcpu_thread = rrdset_create("netdata", "plugin_diskspace", NULL, "diskspace", NULL - , "NetData Disk Space Plugin CPU usage", "milliseconds/s", 132020 - , update_every, RRDSET_TYPE_STACKED); - - rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); + stcpu_thread = rrdset_find_localhost("netdata.plugin_diskspace"); + if(!stcpu_thread) + stcpu_thread = rrdset_create_localhost( + "netdata" + , "plugin_diskspace" + , NULL + , "diskspace" + , NULL + , "NetData Disk Space Plugin CPU usage" + , "milliseconds/s" + , 132020 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); @@ -297,17 +382,27 @@ void *proc_diskspace_main(void *ptr) { // ---------------------------------------------------------------- if(!st_duration) { - st_duration = rrdset_find("netdata.plugin_diskspace_dt"); - if(!st_duration) st_duration = rrdset_create("netdata", "plugin_diskspace_dt", NULL, "diskspace", NULL - , "NetData Disk Space Plugin Duration", "milliseconds/run", 132021 - , update_every, RRDSET_TYPE_AREA); - - rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRDDIM_ABSOLUTE); + st_duration = rrdset_find_localhost("netdata.plugin_diskspace_dt"); + if(!st_duration) + st_duration = rrdset_create_localhost( + "netdata" + , "plugin_diskspace_dt" + , NULL + , "diskspace" + , NULL + , "NetData Disk Space Plugin Duration" + , "milliseconds/run" + , 132021 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st_duration); - rrddim_set_by_pointer(st_duration, rd_duration, dt); + rrddim_set_by_pointer(st_duration, rd_duration, duration); rrdset_done(st_duration); // ----------------------------------------------------------------