]> arthur.barton.de Git - netdata.git/commitdiff
added units and info to alarms and templates - now all alarm badges are a log more...
authorCosta Tsaousis <costa@tsaousis.gr>
Sat, 27 Aug 2016 17:26:44 +0000 (20:26 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Sat, 27 Aug 2016 17:26:44 +0000 (20:26 +0300)
21 files changed:
conf.d/health.d/apache.conf
conf.d/health.d/cpu.conf
conf.d/health.d/disks.conf
conf.d/health.d/entropy.conf
conf.d/health.d/memcached.conf
conf.d/health.d/named.conf
conf.d/health.d/net.conf
conf.d/health.d/nginx.conf
conf.d/health.d/qos.conf
conf.d/health.d/ram.conf
conf.d/health.d/redis.conf
conf.d/health.d/squid.conf
conf.d/health.d/swap.conf
plugins.d/alarm-email.sh
src/common.c
src/health.c
src/health.h
src/web_buffer.c
src/web_buffer_svg.c
src/web_client.c
web/index.html

index ba1a41f51ed75a3bb002ad8e9ddfdbc7b43f45cc..1fddbc99f2fea924fcb8f084f5cf96613938545d 100644 (file)
@@ -7,4 +7,7 @@ template: apache_last_collected_secs
    every: 10s
     warn: $this > ( 5 * $update_every)
     crit: $this > (10 * $update_every)
+   units: seconds ago
+    info: number of seconds since the last successful data collection
+
 
index 6667b1174c4df12b1e68ea3fe7390138d95f995a..9332e508a3d7009cfab585dcb64a0859a0075eca 100644 (file)
@@ -4,15 +4,21 @@ template: 5min_cpu_pcent
   lookup: average -5m unaligned of user,system,nice,softirq,irq,guest,guest_nice
    every: 1m
     warn: $this > 90
+   units: %
+    info: average cpu utilization for the last 5 minutes
 
 template: 5min_iowait_cpu_pcent
       on: system.cpu
   lookup: average -5m unaligned of iowait
    every: 1m
     warn: $this > 10
+   units: %
+    info: average wait I/O for the last 5 minutes
 
 template: 20min_steal_cpu_pcent
       on: system.cpu
   lookup: average -20m unaligned of steal
    every: 5m
     warn: $this > 10
+   units: %
+    info: average stolen CPU time for the last 20 minutes
index 7cfcad2784f55d10cdc4694751dbdd2003911ca8..c38f1a0a03588fc10f142b9c3ac89a70f3ae9647 100644 (file)
@@ -11,6 +11,8 @@ template: disk_full_percent
    every: 1m
     warn: $this > 80
     crit: $this > 95
+   units: %
+    info: current disk space usage
 
 
 # -----------------------------------------------------------------------------
@@ -29,6 +31,8 @@ template: disk_fill_rate
   lookup: max -1s at -30m unaligned of avail
     calc: ($this - $avail) / ($now - $after)
    every: 15s
+   units: MB/s
+    info: average rate the disk fills up (positive), or frees up (negative) space, for the last 30 minutes
 
 
 # calculate the hours remaining
@@ -41,6 +45,8 @@ template: disk_full_after_hours
    every: 10s
     warn: $this > 0 and $this < 48
     crit: $this > 0 and $this < 24
+   units: hours
+    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
 
 
 # -----------------------------------------------------------------------------
@@ -58,6 +64,8 @@ template: 10min_disk_utilization
      red: 98
     warn: $this > $green
     crit: $this > $red
+   units: %
+    info: the percentage of time the disk was busy, during the last 10 minutes
 
 
 # raise an alarm if the disk backlog
@@ -73,3 +81,5 @@ template: 10min_disk_backlog
      red: 2000
     warn: $this > $green
     crit: $this > $red
+   units: ms
+    info: average of the kernel estimated disk backlog, for the last 10 minutes
index 417068b07821d3a4b40858915f213737e8f98997..6f8b6e85182fd4a162f6d19659d75e12d7056d18 100644 (file)
@@ -9,3 +9,5 @@
    every: 1m
     warn: $this < 200
     crit: $this < 100
+   units: entries
+    info: minimum entries in the random numbers pool (entropy), for the last 30 minutes
index e457755e687eb0ae18619cb74dc9a6e0d8ffd667..05ff14711832ebd469ece4052a9259d712c53f57 100644 (file)
@@ -2,12 +2,13 @@
 # make sure memcached is running
 
 template: memcached_last_collected_secs
-      on: memcached.connections
+      on: memcached.cache
     calc: $now - $last_collected_t
    every: 10s
     warn: $this > ( 5 * $update_every)
     crit: $this > (10 * $update_every)
-
+   units: seconds ago
+    info: number of seconds since the last successful data collection
 
 
 # detect if memcached cache is full
@@ -18,7 +19,8 @@ template: cache_full_pcent
    every: 10s
     warn: $this > 80
     crit: $this > 90
-
+   units: %
+    info: current cache memory usage
 
 
 # find the rate memcached cache is filling
@@ -28,7 +30,8 @@ template: cache_fill_rate
   lookup: max -1s at -30m unaligned of available
     calc: ($this - $available) / ($now - $after)
    every: 15s
-
+   units: KB/s
+    info: average rate the cache fills up (positive), or frees up (negative) space, for the last 30 minutes
 
 
 # find the hours remaining until memcached cache is full
@@ -39,3 +42,5 @@ template: cache_full_after_hours
    every: 10s
     warn: $this > 0 and $this < 48
     crit: $this > 0 and $this < 24
+   units: hours
+    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
index 67e86c37b88f15401076ac07d717224a947210c4..e46d1d33005e8da54cf73ad3adf196db82732613 100644 (file)
@@ -7,4 +7,6 @@ template: named_last_collected_secs
    every: 10s
     warn: $this > ( 5 * $update_every)
     crit: $this > (10 * $update_every)
+   units: seconds ago
+    info: number of seconds since the last successful data collection
 
index 84a63587d79e015dfe86d4f74c473fe3626528c4..f65bc4fcb0783ac8a9d4a99c75e69f1b5c04a03a 100644 (file)
@@ -8,6 +8,8 @@ template: 30min_packet_drops
   lookup: sum -30m unaligned absolute
    every: 1m
     crit: $this > 0
+   units: packets
+    info: dropped packets in the last 30 minutes
 
 
 # check if an interface is having FIFO
@@ -20,4 +22,6 @@ template: 30min_fifo_errors
   lookup: sum -30m unaligned absolute
    every: 1m
     crit: $this > 0
+   units: errors
+    info: network interface fifo errors in the last 30 minutes
 
index e1fb17ae10c8961815b24869b211eb3d7bb43e7f..da13008e396d92010a1caf17771700a002a54373 100644 (file)
@@ -7,4 +7,6 @@ template: nginx_last_collected_secs
    every: 10s
     warn: $this > ( 5 * $update_every)
     crit: $this > (10 * $update_every)
+   units: seconds ago
+    info: number of seconds since the last successful data collection
 
index 39842938c620cf09914a2348cca56bad07f8e384..ac3bf8ff4153fed9f91c3b73b1310b7b3287aa0f 100644 (file)
@@ -8,4 +8,5 @@
 #  lookup: sum -10m unaligned absolute
 #   every: 30s
 #    warn: $this > 0
-
+#   units: packets
+#    info: dropped packets in the last 30 minutes
index 4a435a7044b626f3cd53ed348bf17689c4f7d2ef..1d368112838464466a7231f54c412649282a6092 100644 (file)
@@ -5,3 +5,5 @@
    every: 10s
     warn: $this > 80
     crit: $this > 90
+   units: %
+    info: system RAM usage
index 92c433083cd3200c439ad2e825c166876cf0d250..3750176c5f5864d055d25a0b34783090d0a57ce1 100644 (file)
@@ -7,4 +7,6 @@ template: redis_last_collected_secs
    every: 10s
     warn: $this > ( 5 * $update_every)
     crit: $this > (10 * $update_every)
+   units: seconds ago
+    info: number of seconds since the last successful data collection
 
index 0b72496fafb5819d515462acc0ea27d503457a7e..cc5ce1c3a45fbefe0786ca5035e14fc1a25252d6 100644 (file)
@@ -7,4 +7,6 @@ template: squid_last_collected_secs
    every: 10s
     warn: $this > ( 5 * $update_every)
     crit: $this > (10 * $update_every)
+   units: seconds ago
+    info: number of seconds since the last successful data collection
 
index 39e6a523d1c48414ffd8ec529b554dde41d5a1d3..552dd310adfa81c8ba7c04051258c3b7ac7a16d3 100644 (file)
@@ -1,5 +1,5 @@
 
-   alarm: 30min_pcent_of_ram_swapped_out
+   alarm: 30min_ram_swapped_out
       on: system.swapio
   lookup: sum -30m unaligned absolute of out
           # we have to convert KB to MB by dividing $this (i.e. the result of the lookup) with 1024
@@ -7,6 +7,8 @@
    every: 1m
     warn: $this > 1
     crit: $this > 10
+   units: % of RAM
+    info: the sum of all memory swapped out during the last 30 minutes, as a percentage of the available RAM
 
    alarm: pcent_of_ram_in_swap
       on: system.swap
@@ -14,3 +16,5 @@
    every: 10s
     warn: $this > 10
     crit: $this > 50
+   units: % of RAM
+    info: the currently used swap space, as a percentage of the available RAM
index 16286f376932eb53ea99749b1c9881df7ee8831e..25ed6f77796b1c4c9194f988386a2a060be1bab5 100755 (executable)
@@ -31,6 +31,10 @@ old_value="${7}"  # the previous value
 src="${8}"        # the line number and file the alarm has been configured
 duration="${9}"   # the duration in seconds the previous state took
 non_clear_duration="${10}" # the total duration in seconds this is non-clear
+units="${11}"     # the units of the value
+info="${12}"      # a short description of the alarm
+
+[ ! -z "${info}" ] && info=" <br/>${info}"
 
 # get the system hostname
 hostname="${NETDATA_HOSTNAME}"
@@ -93,7 +97,7 @@ severity="${status}"
 raised_for="<br/>(was ${old_status,,} for $(duration4human ${duration}))"
 status_message="status unknown"
 color="grey"
-alarm="${name} = ${value}"
+alarm="${name} = ${value} ${units}"
 
 # prepare the title based on status
 case "${status}" in
@@ -200,7 +204,7 @@ Content-Type: text/html
                                     <tr style="margin:0;padding:0">
                                         <td style="font-size:18px;vertical-align:top;margin:0;padding:0 0 20px"
                                             align="left" valign="top">
-                                            <span>${alarm}</span>
+                                            <span>${alarm}${info}</span>
                                             <span style="display:block;color:#666666;font-size:12px;font-weight:300;line-height:1;text-transform:uppercase">Alarm</span>
                                         </td>
                                     </tr>
index 74f26e3b2a95d912315bee8e66f170633e82055a..7d0fac9aacab013d43e3d8e5dba757ddbdf8c389 100644 (file)
@@ -916,9 +916,7 @@ int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
     int size = vsnprintf(dst, n, fmt, args);
 
     if (unlikely((size_t) size > n)) {
-        // there is bug in vsnprintf() and it returns
-        // a number higher to len, but it does not
-        // overflow the buffer.
+        // truncated
         size = (int)n;
     }
 
index 89fad3f8e99b8c3914dce91ca3242686ba4ba5af..3156cd080f7457e033805bf0ab6f9ad382cde14f 100644 (file)
@@ -467,6 +467,8 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
 
     snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name);
     rc->hostname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value);
+
+       if(!rc->units) rc->units = strdupz(st->units);
 }
 
 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 *
     return simple_hash(fullname);
 }
 
-static inline RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const char *chart, const char *dimensions, int group_method,
-                        int after, int before, int update_every, uint32_t options,
+static inline RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const char *chart, const char *dimensions,
+                        const char *units, const char *info,
+                        int group_method, int after, int before, int update_every, uint32_t options,
                         calculated_number green, calculated_number red,
                         const char *exec, const char *source,
                         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
 
     if(exec) rc->exec = strdupz(exec);
     if(source) rc->source = strdupz(source);
+    if(units) rc->units = strdupz(units);
+    if(info) rc->info = strdupz(info);
 
     if(calc) {
         rc->calculation = expression_parse(calc, NULL, NULL);
@@ -706,11 +711,14 @@ void rrdcalc_free(RRDHOST *host, RRDCALC *rc) {
     expression_free(rc->warning);
     expression_free(rc->critical);
 
-    freez(rc->source);
     freez(rc->name);
     freez(rc->chart);
+    freez(rc->family);
     freez(rc->dimensions);
     freez(rc->exec);
+    freez(rc->source);
+    freez(rc->units);
+    freez(rc->info);
     freez(rc);
 }
 
@@ -724,7 +732,7 @@ void rrdcalctemplate_link_matching(RRDSET *st) {
         if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context)) {
 
             RRDCALC *rc = rrdcalc_create(st->rrdhost, rt->name, st->id,
-                           rt->dimensions, rt->group, rt->after, rt->before, rt->update_every, rt->options,
+                           rt->dimensions, rt->units, rt->info, rt->group, rt->after, rt->before, rt->update_every, rt->options,
                            rt->green, rt->red, rt->exec, rt->source,
                            (rt->calculation)?rt->calculation->source:NULL,
                            (rt->warning)?rt->warning->source:NULL,
@@ -766,11 +774,13 @@ static inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
     expression_free(rt->warning);
     expression_free(rt->critical);
 
-    freez(rt->dimensions);
-    freez(rt->context);
     freez(rt->name);
     freez(rt->exec);
+    freez(rt->context);
     freez(rt->source);
+    freez(rt->units);
+    freez(rt->info);
+    freez(rt->dimensions);
     freez(rt);
 }
 
@@ -790,6 +800,8 @@ static inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
 #define HEALTH_WARN_KEY "warn"
 #define HEALTH_CRIT_KEY "crit"
 #define HEALTH_EXEC_KEY "exec"
+#define HEALTH_UNITS_KEY "units"
+#define HEALTH_INFO_KEY "info"
 
 static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) {
     {
@@ -1034,10 +1046,17 @@ static inline char *health_source_file(size_t line, const char *path, const char
     return strdupz(buffer);
 }
 
+static inline void strip_quotes(char *s) {
+    while(*s) {
+        if(*s == '\'' || *s == '"') *s = ' ';
+        s++;
+    }
+}
+
 int health_readfile(const char *path, const char *filename) {
     debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename);
 
-    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;
+    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;
     char buffer[HEALTH_CONF_MAX_LINE + 1];
 
     if(unlikely(!hash_alarm)) {
@@ -1052,6 +1071,8 @@ int health_readfile(const char *path, const char *filename) {
         hash_crit = simple_uhash(HEALTH_CRIT_KEY);
         hash_exec = simple_uhash(HEALTH_EXEC_KEY);
         hash_every = simple_uhash(HEALTH_EVERY_KEY);
+        hash_units = simple_hash(HEALTH_UNITS_KEY);
+        hash_info = simple_hash(HEALTH_INFO_KEY);
     }
 
     snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename);
@@ -1229,6 +1250,28 @@ int health_readfile(const char *path, const char *filename) {
                 }
                 rc->exec = strdupz(value);
             }
+            else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
+                if(rc->units) {
+                    if(strcmp(rc->units, value))
+                        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').",
+                             line, path, filename, rc->name, key, rc->units, value, value);
+
+                    freez(rc->units);
+                }
+                rc->units = strdupz(value);
+                strip_quotes(rc->units);
+            }
+            else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
+                if(rc->info) {
+                    if(strcmp(rc->info, value))
+                        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').",
+                             line, path, filename, rc->name, key, rc->info, value, value);
+
+                    freez(rc->info);
+                }
+                rc->info = strdupz(value);
+                strip_quotes(rc->info);
+            }
             else {
                 error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.",
                      line, path, filename, rc->name, key);
@@ -1309,6 +1352,28 @@ int health_readfile(const char *path, const char *filename) {
                 }
                 rt->exec = strdupz(value);
             }
+            else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
+                if(rt->units) {
+                    if(strcmp(rt->units, value))
+                        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').",
+                             line, path, filename, rt->name, key, rt->units, value, value);
+
+                    freez(rt->units);
+                }
+                rt->units = strdupz(value);
+                strip_quotes(rt->units);
+            }
+            else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
+                if(rt->info) {
+                    if(strcmp(rt->info, value))
+                        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').",
+                             line, path, filename, rt->name, key, rt->info, value, value);
+
+                    freez(rt->info);
+                }
+                rt->info = strdupz(value);
+                strip_quotes(rt->info);
+            }
             else {
                 error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.",
                       line, path, filename, rt->name, key);
@@ -1428,6 +1493,8 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae) {
                            "\t\t\"exec\":\"%s\",\n"
                            "\t\t\"exec_code\":%d,\n"
                            "\t\t\"source\":\"%s\",\n"
+                           "\t\t\"units\":\"%s\",\n"
+                           "\t\t\"info\":\"%s\",\n"
                            "\t\t\"when\":%lu,\n"
                            "\t\t\"duration\":%lu,\n"
                            "\t\t\"non_clear_duration\":%lu,\n"
@@ -1444,6 +1511,8 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae) {
                    ae->exec?ae->exec:health_default_exec,
                    ae->exec_code,
                    ae->source,
+                   ae->units?ae->units:"",
+                   ae->info?ae->info:"",
                    (unsigned long)ae->when,
                    (unsigned long)ae->duration,
                    (unsigned long)ae->non_clear_duration,
@@ -1489,7 +1558,9 @@ static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) {
                    "\t\t\t\"active\": %s,\n"
                    "\t\t\t\"exec\": \"%s\",\n"
                    "\t\t\t\"source\": \"%s\",\n"
-                   "\t\t\t\"status\": \"%s\",\n"
+                   "\t\t\t\"units\": \"%s\",\n"
+                   "\t\t\t\"info\": \"%s\",\n"
+                                  "\t\t\t\"status\": \"%s\",\n"
                    "\t\t\t\"last_status_change\": %lu,\n"
                    "\t\t\t\"last_updated\": %lu,\n"
                    "\t\t\t\"next_update\": %lu,\n"
@@ -1501,6 +1572,8 @@ static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) {
             , (rc->rrdset)?"true":"false"
             , rc->exec?rc->exec:health_default_exec
             , rc->source
+            , rc->units?rc->units:""
+            , rc->info?rc->info:""
             , rrdcalc_status2string(rc->status)
             , (unsigned long)rc->last_status_change
             , (unsigned long)rc->last_updated
@@ -1677,7 +1750,7 @@ static inline void health_alarm_execute(ALARM_ENTRY *ae) {
     const char *exec = ae->exec;
     if(!exec) exec = health_default_exec;
 
-    snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u'",
+    snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u' '%s' '%s'",
               exec,
               ae->name,
               ae->chart?ae->chart:"NOCAHRT",
@@ -1688,7 +1761,9 @@ static inline void health_alarm_execute(ALARM_ENTRY *ae) {
               ae->old_value,
               ae->source?ae->source:"UNKNOWN",
               (uint32_t)ae->duration,
-              (uint32_t)ae->non_clear_duration
+              (uint32_t)ae->non_clear_duration,
+              ae->units?ae->units:"",
+              ae->info?ae->info:""
     );
 
     ae->notifications |= HEALTH_ENTRY_NOTIFICATIONS_EXEC_RUN;
@@ -1726,7 +1801,9 @@ static inline void health_alarm_log(RRDHOST *host, time_t when,
                 const char *exec, time_t duration,
                 calculated_number old_value, calculated_number new_value,
                 int old_status, int new_status,
-                const char *source
+                const char *source,
+                const char *units,
+                const char *info
 ) {
     ALARM_ENTRY *ae = callocz(1, sizeof(ALARM_ENTRY));
     ae->name = strdupz(name);
@@ -1742,6 +1819,8 @@ static inline void health_alarm_log(RRDHOST *host, time_t when,
 
     if(exec) ae->exec = strdupz(exec);
     if(source) ae->source = strdupz(source);
+    if(units) ae->units = strdupz(units);
+    if(info) ae->info = strdupz(info);
 
     ae->id = host->health_log.nextid++;
     ae->when = when;
@@ -1827,10 +1906,13 @@ static inline void health_alarm_log_process(RRDHOST *host) {
     while(ae) {
         ALARM_ENTRY *t = ae->next;
 
-        freez(ae->family);
-        freez(ae->chart);
         freez(ae->name);
+        freez(ae->chart);
+        freez(ae->family);
         freez(ae->exec);
+        freez(ae->source);
+        freez(ae->units);
+        freez(ae->info);
         freez(ae);
 
         ae = t;
@@ -2071,7 +2153,7 @@ void *health_main(void *ptr) {
                 }
 
                 if(status != rc->status) {
-                    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);
+                    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);
                     rc->last_status_change = now;
                     rc->status = status;
                 }
index 7399660a68ec19e7343dbf5929fa12b1806b3c74..ef1158a29812bdead936cd69de4028ee88318232 100644 (file)
@@ -129,6 +129,8 @@ typedef struct rrdcalc {
     uint32_t hash_chart;
 
     char *source;       // the source of this calculation
+    char *units;
+    char *info;
 
     char *dimensions;   // the chart dimensions
 
@@ -185,6 +187,8 @@ typedef struct rrdcalctemplate {
     uint32_t hash_context;
 
     char *source;       // the source of this template
+    char *units;
+    char *info;
 
     char *dimensions;
 
@@ -230,6 +234,9 @@ typedef struct alarm_entry {
     int exec_code;
 
     char *source;
+    char *units;
+    char *info;
+
     calculated_number old_value;
     calculated_number new_value;
     int old_status;
index b2285fadd229e6c7992733c91d8f64944bf9aa3b..01a97ddc96410fd4c2ff80d556ec6f8eff8fa4ae 100644 (file)
@@ -189,11 +189,7 @@ void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
     va_end(args);
 
     if(unlikely(wrote >= len)) {
-        // there is bug in vsnprintf() and it returns
-        // a number higher to len, but it does not
-        // overflow the buffer.
-        // our buffer overflow detector will log it
-        // if it does.
+        // truncated
         buffer_overflow_check(wb);
 
         debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
index d62e17522588750d5a0bffd04197ee1096658150..2f7627cc570438497c7890684f4e1a356013da60 100644 (file)
@@ -529,7 +529,7 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
         strcpy(value_string, "-");
 
     else if(precision < 0) {
-        size_t len, l, lstop = 0;
+        int len, l, lstop = 0;
 
         calculated_number abs = value;
         if(isless(value, 0)) {
@@ -537,25 +537,31 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
             abs = -value;
         }
 
-        if(isgreaterequal(abs, 1000))     len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.0Lf%s%s", (long double)value, separator, units);
-        else if(isgreaterequal(abs, 100)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.1Lf%s%s", (long double)value, separator, units);
-        else if(isgreaterequal(abs, 1))   len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.2Lf%s%s", (long double)value, separator, units);
-        else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.3Lf%s%s", (long double)value, separator, units);
-        else                              len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.4Lf%s%s", (long double)value, separator, units);
+        if(isgreaterequal(abs, 1000))     len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.0Lf", (long double)value);
+        else if(isgreaterequal(abs, 100)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.1Lf", (long double)value);
+        else if(isgreaterequal(abs, 1))   len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.2Lf", (long double)value);
+        else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.3Lf", (long double)value);
+        else                              len = snprintfz(value_string, VALUE_STRING_SIZE, "%0.4Lf", (long double)value);
 
         // remove trailing zeros
         for(l = len - 1; l > lstop ; l--) {
-            if(likely(value_string[l] == '0'))
+            if(likely(value_string[l] == '0')) {
                 value_string[l] = '\0';
+                len--;
+            }
 
             else if(unlikely(value_string[l] == '.')) {
                 value_string[l] = '\0';
+                len--;
                 break;
             }
 
             else
                 break;
         }
+
+        if(len >= 0)
+            snprintfz(&value_string[len], VALUE_STRING_SIZE - len, "%s%s", separator, units);
     }
     else {
         if(precision > 50) precision = 50;
index 405cfa1f8ff55757f155291ad755768f94f49590..4036d4c813f49411788d4af9e751f6a7931b482f 100644 (file)
@@ -876,8 +876,12 @@ int web_client_api_request_v1_badge(struct web_client *w, char *url) {
             label = st->name;
     }
     if(!units) {
-        if(alarm)
-            units = "";
+        if(alarm) {
+            if(rc->units)
+                units = rc->units;
+            else
+                units = "";
+        }
         else if(options & RRDR_OPTION_PERCENTAGE)
             units = "%";
         else
index aa54e0d974c94ae4f3beb9b8eb13c636e17682c6..1f60269229064a7cced3488d30b1cdbab7b29229 100644 (file)
@@ -2403,9 +2403,9 @@ function renderChartsAndMenu(data) {
 }
 
 function alarmsUpdateModal() {
-    var active = '<h3>Raised Alarms</h3>';
-    var all = '<h3>All Running Alarms</h3>';
-    var log = '<h3>Alarm Log</h3>';
+    var active = '<h3>Raised Alarms</h3><table class="table">';
+    var all = '<h3>All Running Alarms</h3><table class="table">';
+    var log = '<h3>Alarm Log</h3><table  class="table"><tr><th>When</th><th>Chart</th><th>Alarm</th><th>Status</th></tr>';
     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.';
 
     NETDATA.alarms.get('all', function(data) {
@@ -2447,20 +2447,22 @@ function alarmsUpdateModal() {
                 if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
                     if(!active_family_added) {
                         active_family_added = true;
-                        active += '<h4>' + x + '</h4>';
+                        active += '<tr><th class="text-center"><h4>' + x + '</h4></th><th></th></tr>';
                     }
-                    active += '<embed><img src="' + NETDATA.serverDefault + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto&_=' + now.toString()+ '"></img></embed><br/>';
+                    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>';
                     count_active++;
                 }
 
                 if(!all_family_added) {
                     all_family_added = true;
-                    all += '<h4>' + x + '</h4>';
+                    all += '<tr><th class="text-center"><h4>' + x + '</h4></th><th></th></tr>';
                 }
-                all += '<embed><img src="' + NETDATA.serverDefault + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto&_=' + now.toString()+ '"></img></embed><br/>';
+                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>';
                 count_all++;
             }
         }
+        active += "</table>";
+        all += "</table>";
 
         if(!count_active)
             active += "<h4>Everything is normal. No raised alarms.</h4>";
@@ -2482,7 +2484,6 @@ function alarmsUpdateModal() {
                 return;
             }
 
-            log += '<table  class="table"><tr><th>When</th><th>Chart</th><th>Alarm</th><th>Status</th></tr>';
             var i = 0;
             var len = data.length;
             if(len > 50) len = 50;