Module: check_mk
Branch: master
Commit: 66ace72a2337b9135568bc5c0316a06f9a36b3b9
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=66ace72a2337b9…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Tue Nov 5 15:51:50 2013 +0100
Visual colorization of availability according to levels
The availability reporting has now a new option called <i>Visual levels for
the availability</i>. Here you can define two percentual levels, which are
called <i>Warning</i> and <i>Critical</i>. If these levels are
enabled, then
the column <i>OK</i> or <i>UP</i> will be interpreted as the
availability
of the object in question and the color will change to yellow or red, if
the actual percentual availability of that object is below those levels.
That way you can create a tabular report of several items that show whether
a certain availability has been reached.
---
.werks/52 | 16 +++++++++
ChangeLog | 1 +
web/htdocs/valuespec.py | 7 ++--
web/htdocs/views.css | 32 +++++++++++++++++
web/plugins/views/availability.py | 70 +++++++++++++++++++++++++++++++++++--
5 files changed, 121 insertions(+), 5 deletions(-)
diff --git a/.werks/52 b/.werks/52
new file mode 100644
index 0000000..bf3844c
--- /dev/null
+++ b/.werks/52
@@ -0,0 +1,16 @@
+Title: Visual colorization of availability according to levels
+Level: 2
+Component: reporting
+Version: 1.2.3i7
+Date: 1383662920
+Class: feature
+
+The availability reporting has now a new option called <i>Visual levels for
+the availability</i>. Here you can define two percentual levels, which are
+called <i>Warning</i> and <i>Critical</i>. If these levels are
enabled, then
+the column <i>OK</i> or <i>UP</i> will be interpreted as the
availability
+of the object in question and the color will change to yellow or red, if
+the actual percentual availability of that object is below those levels.
+
+That way you can create a tabular report of several items that show whether
+a certain availability has been reached.
diff --git a/ChangeLog b/ChangeLog
index 79c722f..9f75e24 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,7 @@
Reporting & Availability:
* 0051: Option for showing timeline directly in availability table...
+ * 0052: Visual colorization of availability according to levels...
Livestatus:
* 0023 FIX: table statehist: code cleanup / minor performance improvements...
diff --git a/web/htdocs/valuespec.py b/web/htdocs/valuespec.py
index 00fb846..0ba8c5c 100644
--- a/web/htdocs/valuespec.py
+++ b/web/htdocs/valuespec.py
@@ -239,7 +239,7 @@ class Integer(ValueSpec):
style = "text-align: right;"
else:
style = ""
- html.number_input(varprefix, str(value), size = self._size, style = style)
+ html.number_input(varprefix, self._display_format % value, size = self._size,
style = style)
if self._unit:
html.write(" ")
html.write(self._unit)
@@ -869,10 +869,13 @@ class Percentage(Float):
self._maxvalue = 101.0
if "unit" not in kwargs:
self._unit = "%"
+ if "display_format" not in kwargs:
+ self._display_format = "%.1f"
+
self._allow_int = kwargs.get("allow_int", False)
def value_to_text(self, value):
- return "%.1f%%" % value
+ return (self._display_format + "%%") % value
def validate_datatype(self, value, varprefix):
if self._allow_int:
diff --git a/web/htdocs/views.css b/web/htdocs/views.css
index fd03409..9fe39d8 100644
--- a/web/htdocs/views.css
+++ b/web/htdocs/views.css
@@ -629,3 +629,35 @@ table.data.timewarp {
width: 800px;
margin-bottom: 20px;
}
+
+div.av_levels_legend {
+ background-image: url("images/white_20percent.png");
+ background-repeat: repeat;
+ padding: 5px 15px;
+ border-radius: 5px;
+ margin-top: 10px;
+ text-align: right;
+}
+div.av_levels_legend h3 {
+ margin-top: 0px;
+ font-size: 13px;
+ color: black;
+}
+div.av_levels_legend div {
+ display: inline-block;
+ width: 50px;
+ white-space: nowrap;
+ margin-right: 5px;
+}
+div.av_levels_legend div.state {
+ text-align: center;
+ padding: 2px 0px;
+ font-size: 12px;
+}
+div.av_levels_legend div.level {
+ margin-right: 15px;
+ color: black;
+}
+div.av_levels_legend div:last-child {
+ margin-right: 0px;
+}
diff --git a/web/plugins/views/availability.py b/web/plugins/views/availability.py
index 25714be..b637a9e 100644
--- a/web/plugins/views/availability.py
+++ b/web/plugins/views/availability.py
@@ -157,7 +157,7 @@ avoption_entries = [
),
),
- # Optionally group some states togehter
+ # Optionally group some states together
( "state_grouping",
"double",
Dictionary(
@@ -203,6 +203,21 @@ avoption_entries = [
),
),
+ # Visual levels for the availability
+ ( "av_levels",
+ "double",
+ Optional(
+ Tuple(
+ elements = [
+ Percentage(title = _("Warning below"), default_value = 99,
display_format="%.3f", size=7),
+ Percentage(title = _("Critical below"), default_value = 95,
display_format="%.3f", size=7),
+ ]
+ ),
+ title = _("Visual levels for the availability (OK percentage)"),
+ )
+ ),
+
+
# Show colummns for min, max, avg duration and count
( "outage_statistics",
"double",
@@ -237,6 +252,15 @@ avoption_entries = [
)
),
+ # Omit all non-OK columns
+ ( "av_mode",
+ "single",
+ Checkbox(
+ title = _("Availability"),
+ label = _("Just show the availability (i.e. OK/UP)"),
+ ),
+ ),
+
# How to deal with times out of the notification period
( "notification_period",
@@ -335,6 +359,8 @@ def render_availability_options():
"host_down" : "host_down",
},
"outage_statistics" : ([],[]),
+ "av_levels" : None,
+ "av_mode" : False,
"short_intervals" : 0,
"dont_merge" : False,
"show_timeline" : False,
@@ -657,6 +683,7 @@ def do_render_availability(rows, what, avoptions, timeline,
timewarpcode):
else:
render_availability_table(availability, from_time, until_time, range_title, what,
avoptions, render_number)
+
# style is either inline (just the timeline bar) or "standalone" (the complete
page)
def render_timeline(timeline_rows, from_time, until_time, considered_duration,
timeline, range_title, render_number, what, timewarpcode, style):
@@ -801,7 +828,7 @@ def find_next_choord(broken, scale):
epoch = at_monday + 7 * 86400
broken[:] = list(time.localtime(epoch))
title = valuespec.weekdays[broken[6]] + time.strftime(", %d.%m.",
broken)
-
+
else: # scale == "months":
broken[3] = 0
broken[2] = 0
@@ -887,9 +914,15 @@ def render_availability_table(availability, from_time, until_time,
range_title,
state_groups = [ sg["warn"], sg["unknown"],
sg["host_down"] ]
show_timeline = avoptions["show_timeline"]
+ if avoptions["av_levels"]: # and
avoptions["timeformat"].startswith("percentage"):
+ av_levels = avoptions["av_levels"]
+ else:
+ av_levels = None
# Helper function, needed in row and in summary line
def cell_active(sid):
+ if sid not in [ "up", "ok" ] and
avoptions["av_mode"]:
+ return False
if sid == "outof_notification_period" and
avoptions["notification_period"] != "honor":
return False
elif sid == "in_downtime" and
avoptions["downtimes"]["include"] != "honor":
@@ -944,12 +977,15 @@ def render_availability_table(availability, from_time, until_time,
range_title,
if show_timeline:
table.cell(_("Timeline"), css="timeline")
html.write('<a href="%s">' % timeline_url)
- render_timeline(timeline_rows, from_time, until_time, considered_duration,
(site, host, service), range_title, render_number, what, "",
style="inline")
+ render_timeline(timeline_rows, from_time, until_time, considered_duration,
(site, host, service), range_title, render_number, what, "",
style="inline")
html.write('</a>')
for sid, css, sname, help in availability_columns:
if not cell_active(sid):
continue
+ if avoptions["av_mode"]:
+ sname = _("Avail.")
+
number = states.get(sid, 0)
if not number:
css = "unused"
@@ -960,6 +996,9 @@ def render_availability_table(availability, from_time, until_time,
range_title,
else:
summary[sid] += number
+ # Apply visual availability levels (render OK in yellow/red, if too low)
+ if number and av_levels and sid in [ "ok", "up" ]:
+ css = "state%d" % check_av_levels(number, av_levels,
considered_duration)
table.cell(sname, render_number(number, considered_duration),
css="number " + css, help=help)
# Statistics?
@@ -1005,6 +1044,9 @@ def render_availability_table(availability, from_time, until_time,
range_title,
number *= considered_duration
if not number:
css = "unused"
+
+ if number and av_levels and sid in [ "ok", "up" ]:
+ css = "state%d" % check_av_levels(number, av_levels,
considered_duration)
table.cell(sname, render_number(number, considered_duration),
css="number " + css, help=help)
os_aggrs, os_states = avoptions.get("outage_statistics", ([],[]))
if sid in os_states:
@@ -1023,6 +1065,28 @@ def render_availability_table(availability, from_time, until_time,
range_title,
table.end()
+ if av_levels:
+ warn, crit = av_levels
+ html.write('<div class="av_levels_legend">')
+ html.write('<h3>%s</h3>' % _("Availability
levels"))
+ html.write('<div class="state state0">%s</div><div
class=level>≥ %.3f%%</div>' % (_("OK"), warn))
+ html.write('<div class="state state1">%s</div><div
class=level>≥ %.3f%%</div>' % (_("WARN"), crit))
+ html.write('<div class="state state2">%s</div><div
class=level>< %.3f%%</div>' % (_("CRIT"), crit))
+ html.write('</div>')
+
+ # html.debug("HIRNKI")
+
+
+def check_av_levels(number, av_levels, considered_duration):
+ perc = 100 * float(number) / float(considered_duration)
+ warn, crit = av_levels
+ if perc < crit:
+ return 2
+ elif perc < warn:
+ return 1
+ else:
+ return 0
+
# Render availability of an BI aggregate. This is currently