@cryptotaxi247 / netdata-1 / commits / bb64457c9

added units and info to alarms and templates - now all alarm badges are a log more nice

Costa Tsaousis committed Aug 27, 2016 at 20:26 UTC bb64457c9125fa134495ec30b9e6733594bace0d
21 files changed +190 -47
conf.d/health.d/apache.conf
+3
@@ -7,4 +7,7 @@ template: apache_last_collected_secs
7 every: 10s
8 warn: $this > ( 5 * $update_every)
9 crit: $this > (10 * $update_every)
10 + units: seconds ago
11 + info: number of seconds since the last successful data collection
12 +
13
conf.d/health.d/cpu.conf
+6
@@ -4,15 +4,21 @@ template: 5min_cpu_pcent
4 lookup: average -5m unaligned of user,system,nice,softirq,irq,guest,guest_nice
5 every: 1m
6 warn: $this > 90
7 + units: %
8 + info: average cpu utilization for the last 5 minutes
9
10 template: 5min_iowait_cpu_pcent
11 on: system.cpu
12 lookup: average -5m unaligned of iowait
13 every: 1m
14 warn: $this > 10
15 + units: %
16 + info: average wait I/O for the last 5 minutes
17
18 template: 20min_steal_cpu_pcent
19 on: system.cpu
20 lookup: average -20m unaligned of steal
21 every: 5m
22 warn: $this > 10
23 + units: %
24 + info: average stolen CPU time for the last 20 minutes
conf.d/health.d/disks.conf
+10
@@ -11,6 +11,8 @@ template: disk_full_percent
11 every: 1m
12 warn: $this > 80
13 crit: $this > 95
14 + units: %
15 + info: current disk space usage
16
17
18 # -----------------------------------------------------------------------------
@@ -29,6 +31,8 @@ template: disk_fill_rate
31 lookup: max -1s at -30m unaligned of avail
32 calc: ($this - $avail) / ($now - $after)
33 every: 15s
34 + units: MB/s
35 + info: average rate the disk fills up (positive), or frees up (negative) space, for the last 30 minutes
36
37
38 # calculate the hours remaining
@@ -41,6 +45,8 @@ template: disk_full_after_hours
45 every: 10s
46 warn: $this > 0 and $this < 48
47 crit: $this > 0 and $this < 24
48 + units: hours
49 + info: estimated time the disk will run out of space, if the system continues to add data with the rate of the last 30 minutes
50
51
52 # -----------------------------------------------------------------------------
@@ -58,6 +64,8 @@ template: 10min_disk_utilization
64 red: 98
65 warn: $this > $green
66 crit: $this > $red
67 + units: %
68 + info: the percentage of time the disk was busy, during the last 10 minutes
69
70
71 # raise an alarm if the disk backlog
@@ -73,3 +81,5 @@ template: 10min_disk_backlog
81 red: 2000
82 warn: $this > $green
83 crit: $this > $red
84 + units: ms
85 + info: average of the kernel estimated disk backlog, for the last 10 minutes
conf.d/health.d/entropy.conf
+2
@@ -9,3 +9,5 @@
9 every: 1m
10 warn: $this < 200
11 crit: $this < 100
12 + units: entries
13 + info: minimum entries in the random numbers pool (entropy), for the last 30 minutes
conf.d/health.d/memcached.conf
+9 -4
@@ -2,12 +2,13 @@
2 # make sure memcached is running
3
4 template: memcached_last_collected_secs
5 - on: memcached.connections
5 + on: memcached.cache
6 calc: $now - $last_collected_t
7 every: 10s
8 warn: $this > ( 5 * $update_every)
9 crit: $this > (10 * $update_every)
10 -
10 + units: seconds ago
11 + info: number of seconds since the last successful data collection
12
13
14 # detect if memcached cache is full
@@ -18,7 +19,8 @@ template: cache_full_pcent
19 every: 10s
20 warn: $this > 80
21 crit: $this > 90
21 -
22 + units: %
23 + info: current cache memory usage
24
25
26 # find the rate memcached cache is filling
@@ -28,7 +30,8 @@ template: cache_fill_rate
30 lookup: max -1s at -30m unaligned of available
31 calc: ($this - $available) / ($now - $after)
32 every: 15s
31 -
33 + units: KB/s
34 + info: average rate the cache fills up (positive), or frees up (negative) space, for the last 30 minutes
35
36
37 # find the hours remaining until memcached cache is full
@@ -39,3 +42,5 @@ template: cache_full_after_hours
42 every: 10s
43 warn: $this > 0 and $this < 48
44 crit: $this > 0 and $this < 24
45 + units: hours
46 + info: estimated time the cache will run out of space, if the system continues to add data with the rate of the last 30 minutes
conf.d/health.d/named.conf
+2
@@ -7,4 +7,6 @@ template: named_last_collected_secs
7 every: 10s
8 warn: $this > ( 5 * $update_every)
9 crit: $this > (10 * $update_every)
10 + units: seconds ago
11 + info: number of seconds since the last successful data collection
12
conf.d/health.d/net.conf
+4
@@ -8,6 +8,8 @@ template: 30min_packet_drops
8 lookup: sum -30m unaligned absolute
9 every: 1m
10 crit: $this > 0
11 + units: packets
12 + info: dropped packets in the last 30 minutes
13
14
15 # check if an interface is having FIFO
@@ -20,4 +22,6 @@ template: 30min_fifo_errors
22 lookup: sum -30m unaligned absolute
23 every: 1m
24 crit: $this > 0
25 + units: errors
26 + info: network interface fifo errors in the last 30 minutes
27
conf.d/health.d/nginx.conf
+2
@@ -7,4 +7,6 @@ template: nginx_last_collected_secs
7 every: 10s
8 warn: $this > ( 5 * $update_every)
9 crit: $this > (10 * $update_every)
10 + units: seconds ago
11 + info: number of seconds since the last successful data collection
12
conf.d/health.d/qos.conf
+2 -1
@@ -8,4 +8,5 @@
8 # lookup: sum -10m unaligned absolute
9 # every: 30s
10 # warn: $this > 0
11 -
11 +# units: packets
12 +# info: dropped packets in the last 30 minutes
conf.d/health.d/ram.conf
+2
@@ -5,3 +5,5 @@
5 every: 10s
6 warn: $this > 80
7 crit: $this > 90
8 + units: %
9 + info: system RAM usage
conf.d/health.d/redis.conf
+2
@@ -7,4 +7,6 @@ template: redis_last_collected_secs
7 every: 10s
8 warn: $this > ( 5 * $update_every)
9 crit: $this > (10 * $update_every)
10 + units: seconds ago
11 + info: number of seconds since the last successful data collection
12
conf.d/health.d/squid.conf
+2
@@ -7,4 +7,6 @@ template: squid_last_collected_secs
7 every: 10s
8 warn: $this > ( 5 * $update_every)
9 crit: $this > (10 * $update_every)
10 + units: seconds ago
11 + info: number of seconds since the last successful data collection
12
conf.d/health.d/swap.conf
+5 -1
@@ -1,5 +1,5 @@
1
2 - alarm: 30min_pcent_of_ram_swapped_out
2 + alarm: 30min_ram_swapped_out
3 on: system.swapio
4 lookup: sum -30m unaligned absolute of out
5 # we have to convert KB to MB by dividing $this (i.e. the result of the lookup) with 1024
@@ -7,6 +7,8 @@
7 every: 1m
8 warn: $this > 1
9 crit: $this > 10
10 + units: % of RAM
11 + info: the sum of all memory swapped out during the last 30 minutes, as a percentage of the available RAM
12
13 alarm: pcent_of_ram_in_swap
14 on: system.swap
@@ -14,3 +16,5 @@
16 every: 10s
17 warn: $this > 10
18 crit: $this > 50
19 + units: % of RAM
20 + info: the currently used swap space, as a percentage of the available RAM
plugins.d/alarm-email.sh
+6 -2
@@ -31,6 +31,10 @@ old_value="${7}" # the previous value
31 src="${8}" # the line number and file the alarm has been configured
32 duration="${9}" # the duration in seconds the previous state took
33 non_clear_duration="${10}" # the total duration in seconds this is non-clear
34 +units="${11}" # the units of the value
35 +info="${12}" # a short description of the alarm
36 +
37 +[ ! -z "${info}" ] && info=" <br/>${info}"
38
39 # get the system hostname
40 hostname="${NETDATA_HOSTNAME}"
@@ -93,7 +97,7 @@ severity="${status}"
97 raised_for="<br/>(was ${old_status,,} for $(duration4human ${duration}))"
98 status_message="status unknown"
99 color="grey"
96 -alarm="${name} = ${value}"
100 +alarm="${name} = ${value} ${units}"
101
102 # prepare the title based on status
103 case "${status}" in
@@ -200,7 +204,7 @@ Content-Type: text/html
204 <tr style="margin:0;padding:0">
205 <td style="font-size:18px;vertical-align:top;margin:0;padding:0 0 20px"
206 align="left" valign="top">
203 - <span>${alarm}</span>
207 + <span>${alarm}${info}</span>
208 <span style="display:block;color:#666666;font-size:12px;font-weight:300;line-height:1;text-transform:uppercase">Alarm</span>
209 </td>
210 </tr>
src/common.c
+1 -3
@@ -916,9 +916,7 @@ int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
916 int size = vsnprintf(dst, n, fmt, args);
917
918 if (unlikely((size_t) size > n)) {
919 - // there is bug in vsnprintf() and it returns
920 - // a number higher to len, but it does not
921 - // overflow the buffer.
919 + // truncated
920 size = (int)n;
921 }
922
src/health.c
+96 -14
@@ -467,6 +467,8 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
467
468 snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name);
469 rc->hostname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value);
470 +
471 + if(!rc->units) rc->units = strdupz(st->units);
472 }
473
474 static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) {
@@ -604,8 +606,9 @@ static inline uint32_t rrdcalc_fullname(char *fullname, size_t len, const char *
606 return simple_hash(fullname);
607 }
608
607 -static inline RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const char *chart, const char *dimensions, int group_method,
608 - int after, int before, int update_every, uint32_t options,
609 +static inline RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const char *chart, const char *dimensions,
610 + const char *units, const char *info,
611 + int group_method, int after, int before, int update_every, uint32_t options,
612 calculated_number green, calculated_number red,
613 const char *exec, const char *source,
614 const char *calc, const char *warn, const char *crit) {
@@ -639,6 +642,8 @@ static inline RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const cha
642
643 if(exec) rc->exec = strdupz(exec);
644 if(source) rc->source = strdupz(source);
645 + if(units) rc->units = strdupz(units);
646 + if(info) rc->info = strdupz(info);
647
648 if(calc) {
649 rc->calculation = expression_parse(calc, NULL, NULL);
@@ -706,11 +711,14 @@ void rrdcalc_free(RRDHOST *host, RRDCALC *rc) {
711 expression_free(rc->warning);
712 expression_free(rc->critical);
713
709 - freez(rc->source);
714 freez(rc->name);
715 freez(rc->chart);
716 + freez(rc->family);
717 freez(rc->dimensions);
718 freez(rc->exec);
719 + freez(rc->source);
720 + freez(rc->units);
721 + freez(rc->info);
722 freez(rc);
723 }
724
@@ -724,7 +732,7 @@ void rrdcalctemplate_link_matching(RRDSET *st) {
732 if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context)) {
733
734 RRDCALC *rc = rrdcalc_create(st->rrdhost, rt->name, st->id,
727 - rt->dimensions, rt->group, rt->after, rt->before, rt->update_every, rt->options,
735 + rt->dimensions, rt->units, rt->info, rt->group, rt->after, rt->before, rt->update_every, rt->options,
736 rt->green, rt->red, rt->exec, rt->source,
737 (rt->calculation)?rt->calculation->source:NULL,
738 (rt->warning)?rt->warning->source:NULL,
@@ -766,11 +774,13 @@ static inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
774 expression_free(rt->warning);
775 expression_free(rt->critical);
776
769 - freez(rt->dimensions);
770 - freez(rt->context);
777 freez(rt->name);
778 freez(rt->exec);
779 + freez(rt->context);
780 freez(rt->source);
781 + freez(rt->units);
782 + freez(rt->info);
783 + freez(rt->dimensions);
784 freez(rt);
785 }
786
@@ -790,6 +800,8 @@ static inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
800 #define HEALTH_WARN_KEY "warn"
801 #define HEALTH_CRIT_KEY "crit"
802 #define HEALTH_EXEC_KEY "exec"
803 +#define HEALTH_UNITS_KEY "units"
804 +#define HEALTH_INFO_KEY "info"
805
806 static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) {
807 {
@@ -1034,10 +1046,17 @@ static inline char *health_source_file(size_t line, const char *path, const char
1046 return strdupz(buffer);
1047 }
1048
1049 +static inline void strip_quotes(char *s) {
1050 + while(*s) {
1051 + if(*s == '\'' || *s == '"') *s = ' ';
1052 + s++;
1053 + }
1054 +}
1055 +
1056 int health_readfile(const char *path, const char *filename) {
1057 debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename);
1058
1040 - static uint32_t hash_alarm = 0, hash_template = 0, hash_on = 0, hash_calc = 0, hash_green = 0, hash_red = 0, hash_warn = 0, hash_crit = 0, hash_exec = 0, hash_every = 0, hash_lookup = 0;
1059 + static uint32_t hash_alarm = 0, hash_template = 0, hash_on = 0, hash_calc = 0, hash_green = 0, hash_red = 0, hash_warn = 0, hash_crit = 0, hash_exec = 0, hash_every = 0, hash_lookup = 0, hash_units = 0, hash_info = 0;
1060 char buffer[HEALTH_CONF_MAX_LINE + 1];
1061
1062 if(unlikely(!hash_alarm)) {
@@ -1052,6 +1071,8 @@ int health_readfile(const char *path, const char *filename) {
1071 hash_crit = simple_uhash(HEALTH_CRIT_KEY);
1072 hash_exec = simple_uhash(HEALTH_EXEC_KEY);
1073 hash_every = simple_uhash(HEALTH_EVERY_KEY);
1074 + hash_units = simple_hash(HEALTH_UNITS_KEY);
1075 + hash_info = simple_hash(HEALTH_INFO_KEY);
1076 }
1077
1078 snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename);
@@ -1229,6 +1250,28 @@ int health_readfile(const char *path, const char *filename) {
1250 }
1251 rc->exec = strdupz(value);
1252 }
1253 + else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
1254 + if(rc->units) {
1255 + if(strcmp(rc->units, value))
1256 + info("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
1257 + line, path, filename, rc->name, key, rc->units, value, value);
1258 +
1259 + freez(rc->units);
1260 + }
1261 + rc->units = strdupz(value);
1262 + strip_quotes(rc->units);
1263 + }
1264 + else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
1265 + if(rc->info) {
1266 + if(strcmp(rc->info, value))
1267 + info("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
1268 + line, path, filename, rc->name, key, rc->info, value, value);
1269 +
1270 + freez(rc->info);
1271 + }
1272 + rc->info = strdupz(value);
1273 + strip_quotes(rc->info);
1274 + }
1275 else {
1276 error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.",
1277 line, path, filename, rc->name, key);
@@ -1309,6 +1352,28 @@ int health_readfile(const char *path, const char *filename) {
1352 }
1353 rt->exec = strdupz(value);
1354 }
1355 + else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
1356 + if(rt->units) {
1357 + if(strcmp(rt->units, value))
1358 + info("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
1359 + line, path, filename, rt->name, key, rt->units, value, value);
1360 +
1361 + freez(rt->units);
1362 + }
1363 + rt->units = strdupz(value);
1364 + strip_quotes(rt->units);
1365 + }
1366 + else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
1367 + if(rt->info) {
1368 + if(strcmp(rt->info, value))
1369 + info("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
1370 + line, path, filename, rt->name, key, rt->info, value, value);
1371 +
1372 + freez(rt->info);
1373 + }
1374 + rt->info = strdupz(value);
1375 + strip_quotes(rt->info);
1376 + }
1377 else {
1378 error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.",
1379 line, path, filename, rt->name, key);
@@ -1428,6 +1493,8 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae) {
1493 "\t\t\"exec\":\"%s\",\n"
1494 "\t\t\"exec_code\":%d,\n"
1495 "\t\t\"source\":\"%s\",\n"
1496 + "\t\t\"units\":\"%s\",\n"
1497 + "\t\t\"info\":\"%s\",\n"
1498 "\t\t\"when\":%lu,\n"
1499 "\t\t\"duration\":%lu,\n"
1500 "\t\t\"non_clear_duration\":%lu,\n"
@@ -1444,6 +1511,8 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae) {
1511 ae->exec?ae->exec:health_default_exec,
1512 ae->exec_code,
1513 ae->source,
1514 + ae->units?ae->units:"",
1515 + ae->info?ae->info:"",
1516 (unsigned long)ae->when,
1517 (unsigned long)ae->duration,
1518 (unsigned long)ae->non_clear_duration,
@@ -1489,7 +1558,9 @@ static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) {
1558 "\t\t\t\"active\": %s,\n"
1559 "\t\t\t\"exec\": \"%s\",\n"
1560 "\t\t\t\"source\": \"%s\",\n"
1492 - "\t\t\t\"status\": \"%s\",\n"
1561 + "\t\t\t\"units\": \"%s\",\n"
1562 + "\t\t\t\"info\": \"%s\",\n"
1563 + "\t\t\t\"status\": \"%s\",\n"
1564 "\t\t\t\"last_status_change\": %lu,\n"
1565 "\t\t\t\"last_updated\": %lu,\n"
1566 "\t\t\t\"next_update\": %lu,\n"
@@ -1501,6 +1572,8 @@ static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) {
1572 , (rc->rrdset)?"true":"false"
1573 , rc->exec?rc->exec:health_default_exec
1574 , rc->source
1575 + , rc->units?rc->units:""
1576 + , rc->info?rc->info:""
1577 , rrdcalc_status2string(rc->status)
1578 , (unsigned long)rc->last_status_change
1579 , (unsigned long)rc->last_updated
@@ -1677,7 +1750,7 @@ static inline void health_alarm_execute(ALARM_ENTRY *ae) {
1750 const char *exec = ae->exec;
1751 if(!exec) exec = health_default_exec;
1752
1680 - snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u'",
1753 + snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u' '%s' '%s'",
1754 exec,
1755 ae->name,
1756 ae->chart?ae->chart:"NOCAHRT",
@@ -1688,7 +1761,9 @@ static inline void health_alarm_execute(ALARM_ENTRY *ae) {
1761 ae->old_value,
1762 ae->source?ae->source:"UNKNOWN",
1763 (uint32_t)ae->duration,
1691 - (uint32_t)ae->non_clear_duration
1764 + (uint32_t)ae->non_clear_duration,
1765 + ae->units?ae->units:"",
1766 + ae->info?ae->info:""
1767 );
1768
1769 ae->notifications |= HEALTH_ENTRY_NOTIFICATIONS_EXEC_RUN;
@@ -1726,7 +1801,9 @@ static inline void health_alarm_log(RRDHOST *host, time_t when,
1801 const char *exec, time_t duration,
1802 calculated_number old_value, calculated_number new_value,
1803 int old_status, int new_status,
1729 - const char *source
1804 + const char *source,
1805 + const char *units,
1806 + const char *info
1807 ) {
1808 ALARM_ENTRY *ae = callocz(1, sizeof(ALARM_ENTRY));
1809 ae->name = strdupz(name);
@@ -1742,6 +1819,8 @@ static inline void health_alarm_log(RRDHOST *host, time_t when,
1819
1820 if(exec) ae->exec = strdupz(exec);
1821 if(source) ae->source = strdupz(source);
1822 + if(units) ae->units = strdupz(units);
1823 + if(info) ae->info = strdupz(info);
1824
1825 ae->id = host->health_log.nextid++;
1826 ae->when = when;
@@ -1827,10 +1906,13 @@ static inline void health_alarm_log_process(RRDHOST *host) {
1906 while(ae) {
1907 ALARM_ENTRY *t = ae->next;
1908
1830 - freez(ae->family);
1831 - freez(ae->chart);
1909 freez(ae->name);
1910 + freez(ae->chart);
1911 + freez(ae->family);
1912 freez(ae->exec);
1913 + freez(ae->source);
1914 + freez(ae->units);
1915 + freez(ae->info);
1916 freez(ae);
1917
1918 ae = t;
@@ -2071,7 +2153,7 @@ void *health_main(void *ptr) {
2153 }
2154
2155 if(status != rc->status) {
2074 - health_alarm_log(&localhost, time(NULL), rc->name, rc->rrdset->id, rc->rrdset->family, rc->exec, now - rc->last_status_change, rc->old_value, rc->value, rc->status, status, rc->source);
2156 + health_alarm_log(&localhost, time(NULL), rc->name, rc->rrdset->id, rc->rrdset->family, rc->exec, now - rc->last_status_change, rc->old_value, rc->value, rc->status, status, rc->source, rc->units, rc->info);
2157 rc->last_status_change = now;
2158 rc->status = status;
2159 }
src/health.h
+7
@@ -129,6 +129,8 @@ typedef struct rrdcalc {
129 uint32_t hash_chart;
130
131 char *source; // the source of this calculation
132 + char *units;
133 + char *info;
134
135 char *dimensions; // the chart dimensions
136
@@ -185,6 +187,8 @@ typedef struct rrdcalctemplate {
187 uint32_t hash_context;
188
189 char *source; // the source of this template
190 + char *units;
191 + char *info;
192
193 char *dimensions;
194
@@ -230,6 +234,9 @@ typedef struct alarm_entry {
234 int exec_code;
235
236 char *source;
237 + char *units;
238 + char *info;
239 +
240 calculated_number old_value;
241 calculated_number new_value;
242 int old_status;
src/web_buffer.c
+1 -5
@@ -189,11 +189,7 @@ void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
189 va_end(args);
190
191 if(unlikely(wrote >= len)) {
192 - // there is bug in vsnprintf() and it returns
193 - // a number higher to len, but it does not
194 - // overflow the buffer.
195 - // our buffer overflow detector will log it
196 - // if it does.
192 + // truncated
193 buffer_overflow_check(wb);
194
195 debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
src/web_buffer_svg.c
+13 -7
@@ -529,7 +529,7 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
529 strcpy(value_string, "-");
530
531 else if(precision < 0) {
532 - size_t len, l, lstop = 0;
532 + int len, l, lstop = 0;
533
534 calculated_number abs = value;
535 if(isless(value, 0)) {
@@ -537,25 +537,31 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
537 abs = -value;
538 }
539
540 - if(isgreaterequal(abs, 1000)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.0Lf%s%s", (long double)value, separator, units);
541 - else if(isgreaterequal(abs, 100)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.1Lf%s%s", (long double)value, separator, units);
542 - else if(isgreaterequal(abs, 1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.2Lf%s%s", (long double)value, separator, units);
543 - else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.3Lf%s%s", (long double)value, separator, units);
544 - else len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.4Lf%s%s", (long double)value, separator, units);
540 + if(isgreaterequal(abs, 1000)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.0Lf", (long double)value);
541 + else if(isgreaterequal(abs, 100)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.1Lf", (long double)value);
542 + else if(isgreaterequal(abs, 1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.2Lf", (long double)value);
543 + else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.3Lf", (long double)value);
544 + else len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.4Lf", (long double)value);
545
546 // remove trailing zeros
547 for(l = len - 1; l > lstop ; l--) {
548 - if(likely(value_string[l] == '0'))
548 + if(likely(value_string[l] == '0')) {
549 value_string[l] = '\0';
550 + len--;
551 + }
552
553 else if(unlikely(value_string[l] == '.')) {
554 value_string[l] = '\0';
555 + len--;
556 break;
557 }
558
559 else
560 break;
561 }
562 +
563 + if(len >= 0)
564 + snprintfz(&value_string[len], VALUE_STRING_SIZE - len, "%s%s", separator, units);
565 }
566 else {
567 if(precision > 50) precision = 50;
src/web_client.c
+6 -2
@@ -876,8 +876,12 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) {
876 label = st->name;
877 }
878 if(!units) {
879 - if(alarm)
880 - units = "";
879 + if(alarm) {
880 + if(rc->units)
881 + units = rc->units;
882 + else
883 + units = "";
884 + }
885 else if(options & RRDR_OPTION_PERCENTAGE)
886 units = "%";
887 else
web/index.html
+9 -8
@@ -2403,9 +2403,9 @@ function renderChartsAndMenu(data) {
2403 }
2404
2405 function alarmsUpdateModal() {
2406 - var active = '<h3>Raised Alarms</h3>';
2407 - var all = '<h3>All Running Alarms</h3>';
2408 - var log = '<h3>Alarm Log</h3>';
2406 + var active = '<h3>Raised Alarms</h3><table class="table">';
2407 + var all = '<h3>All Running Alarms</h3><table class="table">';
2408 + var log = '<h3>Alarm Log</h3><table class="table"><tr><th>When</th><th>Chart</th><th>Alarm</th><th>Status</th></tr>';
2409 var footer = '<hr/>These are <a href="https://github.com/firehol/netdata/wiki/Generating-Badges" target="_blank">netdata badges</a>. You can copy and paste their URLs to embed them in any web page. Their color indicates the state of the alarm: <b>red</b> is critical, <b>orange</b> is warning, <b>bright green</b> is ok, <b>light grey</b> is undefined (i.e. no data or no status), <b>black</b> is not initialized.';
2410
2411 NETDATA.alarms.get('all', function(data) {
@@ -2447,20 +2447,22 @@ function alarmsUpdateModal() {
2447 if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
2448 if(!active_family_added) {
2449 active_family_added = true;
2450 - active += '<h4>' + x + '</h4>';
2450 + active += '<tr><th class="text-center"><h4>' + x + '</h4></th><th></th></tr>';
2451 }
2452 - active += '<embed><img src="' + NETDATA.serverDefault + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto&_=' + now.toString()+ '"></img></embed><br/>';
2452 + active += '<tr><td class="text-center" style="vertical-align:middle"><embed><img src="' + NETDATA.serverDefault + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto&_=' + now.toString()+ '"></img></embed></td><td>' + alarm.info + '</td></tr>';
2453 count_active++;
2454 }
2455
2456 if(!all_family_added) {
2457 all_family_added = true;
2458 - all += '<h4>' + x + '</h4>';
2458 + all += '<tr><th class="text-center"><h4>' + x + '</h4></th><th></th></tr>';
2459 }
2460 - all += '<embed><img src="' + NETDATA.serverDefault + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto&_=' + now.toString()+ '"></img></embed><br/>';
2460 + all += '<tr><td class="text-center" style="vertical-align:middle"><embed><img src="' + NETDATA.serverDefault + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto&_=' + now.toString()+ '"></img></embed></td><td>' + alarm.info + '</td></tr>';
2461 count_all++;
2462 }
2463 }
2464 + active += "</table>";
2465 + all += "</table>";
2466
2467 if(!count_active)
2468 active += "<h4>Everything is normal. No raised alarms.</h4>";
@@ -2482,7 +2484,6 @@ function alarmsUpdateModal() {
2484 return;
2485 }
2486
2485 - log += '<table class="table"><tr><th>When</th><th>Chart</th><th>Alarm</th><th>Status</th></tr>';
2487 var i = 0;
2488 var len = data.length;
2489 if(len > 50) len = 50;