Module: check_mk
Branch: master
Commit: 6e37a7b43115bc1ac2cc9b07f7b4ae11d571dd14
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=6e37a7b43115bc…
Author: Florian Kromer <fk(a)mathias-kettner.de>
Date: Wed Apr 24 08:42:43 2019 +0200
7295: postgres_stats: Optional ignore of db table
This check plugin notifies about db tables which have never been analyzed or
vacuumed with status according to the configuration in the WATO rule
"PostgresSQL VACUUM and ANALYZE: Age of never analyzed/vacuumed tables".
Users can now disable this rule, such that never analyzed or vacuumed tables
are always {OK}.
CMK-1385
Change-Id: I858fb6784321a45ad0ffb617d9be4d818a6b9570
---
.werks/7295 | 14 ++++++++++++++
checkman/postgres_stats | 11 ++++++++++-
checks/postgres_stats | 2 +-
.../wato/check_parameters/postgres_maintenance.py | 22 ++++++++++++++++++----
.../checks/generictests/datasets/postgres_stats.py | 4 ++--
5 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/.werks/7295 b/.werks/7295
new file mode 100644
index 0000000..842d74b
--- /dev/null
+++ b/.werks/7295
@@ -0,0 +1,14 @@
+Title: postgres_stats: Optional ignore of db table
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1556035464
+Class: feature
+
+This check plugin notifies about db tables which have never been analyzed or
+vacuumed with status according to the configuration in the WATO rule
+"PostgresSQL VACUUM and ANALYZE: Age of never analyzed/vacuumed tables".
+Users can now disable this rule, such that never analyzed or vacuumed tables
+are always {OK}.
diff --git a/checkman/postgres_stats b/checkman/postgres_stats
index 91360da..2488ba0 100644
--- a/checkman/postgres_stats
+++ b/checkman/postgres_stats
@@ -8,7 +8,16 @@ description:
a PostgreSQL database. You can configure limits specifiying the maximum age of the last operation.
Without additional limits configuration this check is always OK.
- This check relies on data reported by the agent-side plugin {mk_postgres}
+ This check relies on data reported by the agent-side plugin {mk_postgres}.
+
+ Check status:
+
+ For every table the time since it has last been analyzed or vacuumed is checked
+ according to the WATO rule "PostgresSQL VACUUM and ANALYZE: Time since the last
+ VACUUM" and "Time since the last ANALYZE" respectively. For tables that were
+ never analyzed or vacuumed the time period for which they exist is checked
+ according to the WATO rule "PostgresSQL VACUUM and ANALYZE: Age of never
+ analyzed/vacuumed tables".
inventory:
Two services for each database. One for VACUUM and one for ANALYZE.
diff --git a/checks/postgres_stats b/checks/postgres_stats
index b4903b2..da2958b 100644
--- a/checks/postgres_stats
+++ b/checks/postgres_stats
@@ -37,7 +37,7 @@
# postgres;pg_catalog;pg_attribute;-1;-1
factory_settings["postgres_stats_default_levels"] = {
- "never_analyze_vacuum": (0, float('inf')),
+ "never_analyze_vacuum": (0, 1000 * 365 * 24 * 3600),
}
diff --git a/cmk/gui/plugins/wato/check_parameters/postgres_maintenance.py b/cmk/gui/plugins/wato/check_parameters/postgres_maintenance.py
index e6d9cac..92107d2 100644
--- a/cmk/gui/plugins/wato/check_parameters/postgres_maintenance.py
+++ b/cmk/gui/plugins/wato/check_parameters/postgres_maintenance.py
@@ -27,7 +27,9 @@
from cmk.gui.i18n import _
from cmk.gui.valuespec import (
Age,
+ Alternative,
Dictionary,
+ FixedValue,
TextAscii,
Tuple,
)
@@ -82,11 +84,23 @@ class RulespecCheckgroupParametersPostgresMaintenance(CheckParameterRulespecWith
],
)),
("never_analyze_vacuum",
- Tuple(
- title=_("Age of never analyzed/vacuumed tables"),
+ Alternative(
+ title=_("Never analyzed/vacuumed tables"),
+ style="dropdown",
elements=[
- Age(title=_("Warning if older than"), default_value=86400 * 7),
- Age(title=_("Critical if older than"), default_value=86400 * 14)
+ Tuple(
+ title=_("Age of never analyzed/vacuumed tables"),
+ elements=[
+ Age(title=_("Warning if older than"), default_value=0),
+ Age(title=_("Critical if older than"),
+ default_value=1000 * 365 * 24 * 3600)
+ ],
+ ),
+ FixedValue(
+ None,
+ title=_("Do not check age of never analyzed/vacuumed tables"),
+ totext="",
+ ),
],
)),
],
diff --git a/tests/unit/checks/generictests/datasets/postgres_stats.py b/tests/unit/checks/generictests/datasets/postgres_stats.py
index 0367d79..98fc68b 100644
--- a/tests/unit/checks/generictests/datasets/postgres_stats.py
+++ b/tests/unit/checks/generictests/datasets/postgres_stats.py
@@ -39,11 +39,11 @@ checks = {
(0, u'2 tables were never analyzed: anrede/auftrag_mediadaten', []),
(2, u'Unhandled tables for: 20 m (warn/crit at 16 m/18 m)', []),
]),
- (u'ANALYZE adwebconnect', {"never_analyze_vacuum": (0, float('inf'))}, [
+ (u'ANALYZE adwebconnect', {'never_analyze_vacuum': (0, 1000 * 365 * 24 * 3600)}, [
(0, u'Table: auftrag', []),
(0, u'Time since last vacuum: 674 d', []),
(0, u'2 tables were never analyzed: anrede/auftrag_mediadaten', []),
- (1, u'Unhandled tables for: 20 m (warn/crit at 0.00 s/inf y)', []),
+ (1, u'Unhandled tables for: 20 m (warn/crit at 0.00 s/1000 y)', []),
]),
(u'ANALYZE adwebconnect', {'never_analyze_vacuum': None}, [
(0, u'Table: auftrag', []),
Module: check_mk
Branch: master
Commit: 7d06b53666f1b6a1fceef21a2260639a45ca9da0
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=7d06b53666f1b6…
Author: Moritz Kiemer <mo(a)mathias-kettner.de>
Date: Tue Apr 23 09:47:21 2019 +0200
7474 check_mk_agent: Cache information for local checks
For local checks running asynchronously the cache age information
is now included in the section header. Services corresponding to
outdated check data will become stale.
CMK-1313
Change-Id: I5dfb7326fc360fa915466f07fc19f7b49f333987
---
.werks/7474 | 13 +++++++++++++
agents/check_mk_agent.aix | 12 ++++++++----
agents/check_mk_agent.freebsd | 12 ++++++++----
agents/check_mk_agent.linux | 12 ++++++++----
agents/check_mk_agent.solaris | 12 ++++++++----
checks/local | 22 ++++++++++++++++++++--
.../checks/generictests/datasets/local_cached.py | 17 +++++++++++++++++
tests/unit/checks/test_local_expired.py | 22 ++++++++++++++++++++++
8 files changed, 104 insertions(+), 18 deletions(-)
diff --git a/.werks/7474 b/.werks/7474
new file mode 100644
index 0000000..9187e40
--- /dev/null
+++ b/.werks/7474
@@ -0,0 +1,13 @@
+Title: check_mk_agent: Cache information for local checks
+Level: 2
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1556030292
+Class: feature
+
+For local checks running asynchronously the cache age information
+is now included in the agent output. Services corresponding to
+outdated check data will become stale.
+Previously the user was not able to recognize outdated data in this case.
diff --git a/agents/check_mk_agent.aix b/agents/check_mk_agent.aix
index 9ca0aa5..ba84653 100755
--- a/agents/check_mk_agent.aix
+++ b/agents/check_mk_agent.aix
@@ -124,10 +124,14 @@ function run_cached {
if (( $MTIME < $MAXAGE )) ; then
USE_CACHEFILE=1
fi
- CACHE_INFO=":cached($MTIME,$MAXAGE)"
- # insert the cache info in the section header (^= after '!'),
- # if none is present (^= before '!')
- sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1'$CACHE_INFO'>>>/' "$CACHEFILE"
+ CACHE_INFO="cached($MTIME,$MAXAGE)"
+ if [[ $NAME == local_* ]]; then
+ sed -e "s/^/$CACHE_INFO /" "$CACHEFILE"
+ else
+ # insert the cache info in the section header (^= after '!'),
+ # if none is present (^= before '!')
+ sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1:'$CACHE_INFO'>>>/' "$CACHEFILE"
+ fi
fi
if [ -z "$USE_CACHEFILE" -a ! -e "$CACHEFILE.new" ]
then
diff --git a/agents/check_mk_agent.freebsd b/agents/check_mk_agent.freebsd
index f187bbd..849cd19 100755
--- a/agents/check_mk_agent.freebsd
+++ b/agents/check_mk_agent.freebsd
@@ -97,10 +97,14 @@ function run_cached() {
if [ $((NOW - MTIME)) -le $MAXAGE ] ; then local USE_CACHEFILE=1 ; fi
# Output the file in any case, even if it is
# outdated. The new file will not yet be available
- CACHE_INFO=":cached($MTIME,$MAXAGE)"
- # insert the cache info in the section header (^= after '!'),
- # if none is present (^= before '!')
- sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1'$CACHE_INFO'>>>/' "$CACHEFILE"
+ CACHE_INFO="cached($MTIME,$MAXAGE)"
+ if [[ $NAME == local_* ]]; then
+ sed -e "s/^/$CACHE_INFO /" "$CACHEFILE"
+ else
+ # insert the cache info in the section header (^= after '!'),
+ # if none is present (^= before '!')
+ sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1:'$CACHE_INFO'>>>/' "$CACHEFILE"
+ fi
fi
# Cache file outdated and new job not yet running? Start it
diff --git a/agents/check_mk_agent.linux b/agents/check_mk_agent.linux
index 90c8c34..5a3e01d 100755
--- a/agents/check_mk_agent.linux
+++ b/agents/check_mk_agent.linux
@@ -290,10 +290,14 @@ function run_cached () {
# all further lines are long output)
sed -e "2s/|/ (Cached: ${AGE}\/${MAXAGE}s)|/" -e t -e "2s/$/ (Cached: ${AGE}\/${MAXAGE}s)/" < "$CACHEFILE"
else
- CACHE_INFO=":cached($MTIME,$MAXAGE)"
- # insert the cache info in the section header (^= after '!'),
- # if none is present (^= before '!')
- sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1'$CACHE_INFO'>>>/' "$CACHEFILE"
+ CACHE_INFO="cached($MTIME,$MAXAGE)"
+ if [[ $NAME == local_* ]]; then
+ sed -e "s/^/$CACHE_INFO /" "$CACHEFILE"
+ else
+ # insert the cache info in the section header (^= after '!'),
+ # if none is present (^= before '!')
+ sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1:'$CACHE_INFO'>>>/' "$CACHEFILE"
+ fi
fi
fi
diff --git a/agents/check_mk_agent.solaris b/agents/check_mk_agent.solaris
index 74ebf51..b0c9228 100755
--- a/agents/check_mk_agent.solaris
+++ b/agents/check_mk_agent.solaris
@@ -127,10 +127,14 @@ function run_cached () {
# all further lines are long output)
cat "$CACHEFILE" | sed -e "2s/|/ (Cached: ${AGE}\/${MAXAGE}s)|/" -e t -e "2s/$/ (Cached: ${AGE}\/${MAXAGE}s)/"
else
- CACHE_INFO=":cached($MTIME,$MAXAGE)"
- # insert the cache info in the section header (^= after '!'),
- # if none is present (^= before '!')
- sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1'$CACHE_INFO'>>>/' "$CACHEFILE"
+ CACHE_INFO="cached($MTIME,$MAXAGE)"
+ if [[ $NAME == local_* ]]; then
+ sed -e "s/^/$CACHE_INFO /" "$CACHEFILE"
+ else
+ # insert the cache info in the section header (^= after '!'),
+ # if none is present (^= before '!')
+ sed -e '/^<<<.*\(:cached(\).*>>>/!s/^<<<\([^>]*\)>>>$/<<<\1:'$CACHE_INFO'>>>/' "$CACHEFILE"
+ fi
fi
fi
diff --git a/checks/local b/checks/local
index f6f6ba1..a5c0e7c 100644
--- a/checks/local
+++ b/checks/local
@@ -45,6 +45,16 @@ def float_ignore_uom(value):
return 0.0
+def _parse_cache(line, now):
+ if not line or not line[0].startswith("cached("):
+ return 0, line
+
+ cache_raw, stripped_line = line[0], line[1:]
+ time, maxage = (float(v) for v in cache_raw[7:-1].split(',', 1))
+
+ return max(now - time - maxage, 0), stripped_line
+
+
def _is_valid_line(line):
return len(line) >= 4 or (len(line) == 3 and line[0] == 'P')
@@ -118,11 +128,13 @@ def _parse_perftxt(string):
def parse_local(info):
LocalResult = collections.namedtuple("LocalResult",
- ("node", "item", "state", "text", "perfdata"))
+ ("node", "expired", "item", "state", "text", "perfdata"))
+ now = time.time()
parsed = {}
for line in info:
node, stripped_line = line[0], line[1:]
+ expired, stripped_line = _parse_cache(stripped_line, now)
if not _is_valid_line(stripped_line):
parsed.setdefault(None, []).append(LocalResult(node, None, None, stripped_line))
continue
@@ -136,7 +148,7 @@ def parse_local(info):
if state_msg or perf_msg:
state = 3
text = "%s%sOutput is: %s" % (state_msg, perf_msg, text)
- parsed.setdefault(item, []).append(LocalResult(node, item, state, text, perfdata))
+ parsed.setdefault(item, []).append(LocalResult(node, expired, item, state, text, perfdata))
return parsed
@@ -200,8 +212,14 @@ def _calculate_local_worst_state(collected_stats):
def check_local(_no_item, params, data):
collected_stats = {}
for result in data:
+ if result.expired > 0:
+ continue
node_dict = collected_stats.setdefault(result.node, {})
node_dict.setdefault(result.item, _parse_local_line(result))
+ if not collected_stats:
+ most_recent_expirery = min(r.expired for r in data)
+ raise MKCounterWrapped(
+ "Cached data expired %s ago." % get_age_human_readable(most_recent_expirery))
if params is not None and params.get("outcome_on_cluster", "worst") == "best":
yield _calculate_local_best_state(collected_stats)
diff --git a/tests/unit/checks/generictests/datasets/local_cached.py b/tests/unit/checks/generictests/datasets/local_cached.py
new file mode 100644
index 0000000..f7cb085
--- /dev/null
+++ b/tests/unit/checks/generictests/datasets/local_cached.py
@@ -0,0 +1,17 @@
+# yapf: disable
+
+
+checkname = 'local'
+
+freeze_time = "2019-04-23 07:45:00"
+
+info = [
+ ['node_1', 'cached(1556005301,300)', '0', 'Service_FOO', 'V=1', 'This', 'Check', 'is', 'OK'],
+]
+
+
+discovery = {
+ '': [
+ ('Service_FOO', {}),
+ ],
+}
diff --git a/tests/unit/checks/test_local_expired.py b/tests/unit/checks/test_local_expired.py
new file mode 100644
index 0000000..f967ae7
--- /dev/null
+++ b/tests/unit/checks/test_local_expired.py
@@ -0,0 +1,22 @@
+import pytest # type: ignore
+from cmk_base.check_api import MKCounterWrapped
+from checktestlib import CheckResult
+
+pytestmark = pytest.mark.checks
+
+
+(a)pytest.mark.parametrize('item,info', [
+ ('Service_FOO', [[
+ 'node_1', 'cached(1556005301,300)', '0', 'Service_FOO', 'V=1', 'This', 'Check', 'is',
+ 'outdated'
+ ]]),
+])
+def test_local_check(check_manager, monkeypatch, item, info):
+ monkeypatch.setattr('time.time', lambda: 1556005721)
+ check = check_manager.get_check('local')
+
+ parsed = check.run_parse(info)
+ assert parsed[item][0].expired == 120.
+
+ with pytest.raises(MKCounterWrapped):
+ CheckResult(check.run_check(item, {}, parsed))