summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Nierlein <sven@consol.de>2024-02-23 17:24:28 (GMT)
committerGitHub <noreply@github.com>2024-02-23 17:24:28 (GMT)
commit117cd8e4b826e471e795536228628d817df33f5a (patch)
tree4ce82a1ad714f95e0bb790aa9396f059bf5a3677
parent0c01f2946ed21f5e7977b5503f9c9f00e72fd708 (diff)
downloadmonitoring-plugins-117cd8e4b826e471e795536228628d817df33f5a.tar.gz
check_disk increase alert precision (#1989)
* check_disk increase alert precision Free disk percentage value was rounded to a full integer meaning it alerted about ~1% percent too early. This is about 10GB on a 1TB disk. The warning and critical thresholds already support float values, so just the percentage calculation needs to be improved. old: ./check_disk -w 35% -c 20% -p / -f -vvv Thresholds(pct) for / warn: 35.000000 crit 20.000000 calling stat on / For /, used_pct=65 free_pct=35 used_units=286451 free_units=156651 total_units=443102 used_inodes_pct=11 free_inodes_pct=89 fsp.fsu_blocksize=4096 mult=1048576 Freespace_units result=0 Freespace% result=1 Usedspace_units result=0 Usedspace_percent result=0 Usedinodes_percent result=0 Freeinodes_percent result=0 DISK WARNING - free space: WARNING [ / 156651MiB (35% inode=89%)];| /=300365643776B;302006979788;371700898201;0;464626122752 new: ./check_disk -w 35% -c 20% -p / -f -vvv Thresholds(pct) for / warn: 35.000000 crit 20.000000 calling stat on / For /, used_pct=64.649722 free_pct=35.350278 used_units=286464 free_units=156637 total_units=443102 used_inodes_pct=10.016183 free_inodes_pct=89.983817 fsp.fsu_blocksize=4096 mult=1048576 Freespace_units result=0 Freespace% result=0 Usedspace_units result=0 Usedspace_percent result=0 Usedinodes_percent result=0 Freeinodes_percent result=0 DISK OK - free space: / 156637MiB (35.4% inode=90%);| /=300379275264B;302006979788;371700898201;0;464626122752 * check_disk: adjust test case to support float precision
-rw-r--r--plugins/check_disk.c28
-rw-r--r--plugins/t/check_disk.t2
2 files changed, 7 insertions, 23 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index c6bba24..0d84ecd 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -46,7 +46,7 @@ const char *email = "devel@monitoring-plugins.org";
46#include <stdarg.h> 46#include <stdarg.h>
47#include "fsusage.h" 47#include "fsusage.h"
48#include "mountlist.h" 48#include "mountlist.h"
49#include "intprops.h" /* necessary for TYPE_MAXIMUM */ 49#include <float.h>
50#if HAVE_LIMITS_H 50#if HAVE_LIMITS_H
51# include <limits.h> 51# include <limits.h>
52#endif 52#endif
@@ -325,7 +325,7 @@ main (int argc, char **argv)
325 get_stats (path, &fsp); 325 get_stats (path, &fsp);
326 326
327 if (verbose >= 3) { 327 if (verbose >= 3) {
328 printf ("For %s, used_pct=%g free_pct=%g used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%lu mult=%lu\n", 328 printf ("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
329 me->me_mountdir, 329 me->me_mountdir,
330 path->dused_pct, 330 path->dused_pct,
331 path->dfree_pct, 331 path->dfree_pct,
@@ -431,7 +431,7 @@ main (int argc, char **argv)
431 } else { 431 } else {
432 xasprintf(&flag_header, ""); 432 xasprintf(&flag_header, "");
433 } 433 }
434 xasprintf (&output, "%s%s %s %llu%s (%.0f%%", 434 xasprintf (&output, "%s%s %s %llu%s (%.1f%%",
435 output, flag_header, 435 output, flag_header,
436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, 436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
437 path->dfree_units, 437 path->dfree_units,
@@ -461,24 +461,8 @@ main (int argc, char **argv)
461 461
462double calculate_percent(uintmax_t value, uintmax_t total) { 462double calculate_percent(uintmax_t value, uintmax_t total) {
463 double pct = -1; 463 double pct = -1;
464 /* I don't understand the below, but it is taken from coreutils' df */ 464 if(value <= DBL_MAX && total != 0) {
465 /* Seems to be calculating pct, in the best possible way */ 465 pct = (double)value / total * 100.0;
466 if (value <= TYPE_MAXIMUM(uintmax_t) / 100
467 && total != 0) {
468 uintmax_t u100 = value * 100;
469 pct = u100 / total + (u100 % total != 0);
470 } else {
471 /* Possible rounding errors - see coreutils' df for more explanation */
472 double u = value;
473 double t = total;
474 if (t) {
475 long int lipct = pct = u * 100 / t;
476 double ipct = lipct;
477
478 /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */
479 if (ipct - 1 < pct && pct <= ipct + 1)
480 pct = ipct + (ipct < pct);
481 }
482 } 466 }
483 return pct; 467 return pct;
484} 468}
@@ -1130,7 +1114,7 @@ get_stats (struct parameter_list *p, struct fs_usage *fsp) {
1130 } 1114 }
1131 /* finally calculate percentages for either plain FS or summed up group */ 1115 /* finally calculate percentages for either plain FS or summed up group */
1132 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */ 1116 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1133 p->dfree_pct = 100 - p->dused_pct; 1117 p->dfree_pct = 100.0 - p->dused_pct;
1134 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total); 1118 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1135 p->dfree_inodes_percent = 100 - p->dused_inodes_percent; 1119 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1136 1120
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index bf8dd36..e0dd70e 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -44,7 +44,7 @@ my @perf_data = sort(split(/ /, $result->perf_output));
44# Calculate avg_free free on mountpoint1 and mountpoint2 44# Calculate avg_free free on mountpoint1 and mountpoint2
45# because if you check in the middle, you should get different errors 45# because if you check in the middle, you should get different errors
46$_ = $result->output; 46$_ = $result->output;
47my ($free_on_mp1, $free_on_mp2) = (m/\((\d+)%.*\((\d+)%/); 47my ($free_on_mp1, $free_on_mp2) = (m/\((\d+\.\d+)%.*\((\d+\.\d+)%/);
48die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2); 48die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2);
49my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2); 49my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2);
50my ($more_free, $less_free); 50my ($more_free, $less_free);