Changeset View
Changeset View
Standalone View
Standalone View
site-modules/profile/files/icinga2/plugins/check_journal
Show All 19 Lines | |||||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||||
# SOFTWARE. | # SOFTWARE. | ||||||||
import argparse | import argparse | ||||||||
import logging | import logging | ||||||||
import yaml | |||||||||
import nagiosplugin | import nagiosplugin | ||||||||
from nagiosplugin import ScalarContext | from nagiosplugin import ScalarContext | ||||||||
import systemd.journal | import systemd.journal | ||||||||
_log = logging.getLogger('nagiosplugin') | _log = logging.getLogger('nagiosplugin') | ||||||||
Show All 20 Lines | def evaluate(self, metric, resource): | ||||||||
return self.result_cls(nagiosplugin.state.Warn, "NOT OK", metric) | return self.result_cls(nagiosplugin.state.Warn, "NOT OK", metric) | ||||||||
else: | else: | ||||||||
return self.result_cls(nagiosplugin.state.Ok, "OK", metric) | return self.result_cls(nagiosplugin.state.Ok, "OK", metric) | ||||||||
class JournalLag(nagiosplugin.Resource): | class JournalLag(nagiosplugin.Resource): | ||||||||
"""Check journal lag""" | """Check journal lag""" | ||||||||
def __init__(self, cursorfile): | def __init__(self, cursorfile, registryfile, registryentry): | ||||||||
self.cursorfile = cursorfile | self.cursorfile = cursorfile | ||||||||
self.registryfile = registryfile | |||||||||
self.registryentry = registryentry | |||||||||
def parse_cursor(self, cursor): | def parse_cursor(self, cursor): | ||||||||
"""Parse a journald cursor entry""" | """Parse a journald cursor entry""" | ||||||||
entries = cursor.strip().split(';') | entries = cursor.strip().split(';') | ||||||||
ret = {} | ret = {} | ||||||||
for entry in entries: | for entry in entries: | ||||||||
key, value = entry.split('=') | key, value = entry.split('=') | ||||||||
ret[key] = value | ret[key] = value | ||||||||
for key in ('i', 'm', 't'): | for key in ('i', 'm', 't'): | ||||||||
# Those cursor keys are hexadecimal | # Those cursor keys are hexadecimal | ||||||||
if key in ret: | if key in ret: | ||||||||
ret[key] = int(ret[key], 16) | ret[key] = int(ret[key], 16) | ||||||||
return ret | return ret | ||||||||
def get_file_journal_cursor(self): | def get_legacy_journal_cursor(self): | ||||||||
_log.info("querying the journal cursor cache file %s" % self.cursorfile) | _log.info("querying the journal cursor cache file %s", self.cursorfile) | ||||||||
try: | try: | ||||||||
with open(self.cursorfile, 'r') as f: | with open(self.cursorfile, 'r') as f: | ||||||||
ret = f.read().strip() | ret = f.read().strip() | ||||||||
except OSError as e: | except OSError as e: | ||||||||
raise nagiosplugin.CheckError("failed to read journal cursor file: %s" % e) | _log.warning("failed to read the legacy journal cursor file %s", self.cursorfile) | ||||||||
else: | else: | ||||||||
_log.debug("current journal cursor: %s" % ret) | _log.debug("current journal cursor: %s" % ret) | ||||||||
return ret | return ret | ||||||||
def get_journal_cursor_from_registry(self): | |||||||||
ardumont: The initial version is fine for raw print statements, it's better for log instruction to do the… | |||||||||
_log.info("querying the journal cursor %s from registry file %s", self.registryentry, self.registryfile) | |||||||||
try: | |||||||||
with open(self.registryfile, 'r') as f: | |||||||||
registrycontent = yaml.safe_load(f) | |||||||||
except OSError as e: | |||||||||
_log.warning("failed to read the journal registry file %s", self.registryfile) | |||||||||
else: | |||||||||
entry = [e for e in registrycontent['journal_entries'] if e['path'] == self.registryentry] | |||||||||
cursor = entry[0]["cursor"] | |||||||||
Not Done Inline Actions
for your general information (not necessary to change), let the formatting be done by the log instruction. ardumont: for your general information (not necessary to change), let the formatting be done by the log… | |||||||||
_log.debug("current journal cursor: %s" % cursor) | |||||||||
return cursor | |||||||||
def get_file_journal_cursor(self): | |||||||||
cursor = self.get_journal_cursor_from_registry() | |||||||||
if not cursor: | |||||||||
_log.debug("Unable to read cursor position from the registry, fallback on the legacy file") | |||||||||
cursor = self.get_legacy_journal_cursor() | |||||||||
if not cursor: | |||||||||
raise nagiosplugin.CheckError("failed to get cursor from registry or legacy file") | |||||||||
return cursor | |||||||||
def get_system_journal_cursor(self): | def get_system_journal_cursor(self): | ||||||||
_log.info("querying the system journal for the current cursor") | _log.info("querying the system journal for the current cursor") | ||||||||
reader = systemd.journal.Reader() | reader = systemd.journal.Reader() | ||||||||
reader.seek_tail() | reader.seek_tail() | ||||||||
ret = reader.get_previous()['__CURSOR'] | ret = reader.get_previous()['__CURSOR'] | ||||||||
_log.debug("current journald cursor: %s" % ret) | _log.debug("current journald cursor: %s" % ret) | ||||||||
return ret | return ret | ||||||||
Show All 30 Lines | |||||||||
@nagiosplugin.guarded | @nagiosplugin.guarded | ||||||||
def main(): | def main(): | ||||||||
argp = argparse.ArgumentParser(description=__doc__) | argp = argparse.ArgumentParser(description=__doc__) | ||||||||
argp.add_argument('-v', '--verbose', action='count', default=0, | argp.add_argument('-v', '--verbose', action='count', default=0, | ||||||||
help='increase output verbosity (use up to 3 times)') | help='increase output verbosity (use up to 3 times)') | ||||||||
argp.add_argument('-f', '--file', metavar='FILE', default='/var/lib/journalbeat/cursor-state', | argp.add_argument('-f', '--file', metavar='FILE', default='/var/lib/journalbeat/cursor-state', | ||||||||
help='read journald cursor state from this file') | help='read journald cursor state from this file') | ||||||||
argp.add_argument('-r', '--registry', metavar='FILE', default='/var/lib/journalbeat/registry', | |||||||||
help='read journald cursor state from this journalbeat registry file') | |||||||||
argp.add_argument('-e', '--entry', default='LOCAL_SYSTEM_JOURNAL', | |||||||||
help='Check this registry entry') | |||||||||
argp.add_argument('-w', '--warning', metavar='RANGE', default='1200', | argp.add_argument('-w', '--warning', metavar='RANGE', default='1200', | ||||||||
help='return warning if temporal lag is outside RANGE') | help='return warning if temporal lag is outside RANGE') | ||||||||
argp.add_argument('-c', '--critical', metavar='RANGE', default='3600', | argp.add_argument('-c', '--critical', metavar='RANGE', default='3600', | ||||||||
help='return critical if temporal lag is outside RANGE') | help='return critical if temporal lag is outside RANGE') | ||||||||
argp.add_argument('-wn', '--warning-entries', metavar='RANGE', default='', | argp.add_argument('-wn', '--warning-entries', metavar='RANGE', default='', | ||||||||
help='return warning if entries lag is outside RANGE') | help='return warning if entries lag is outside RANGE') | ||||||||
argp.add_argument('-cn', '--critical-entries', metavar='RANGE', default='', | argp.add_argument('-cn', '--critical-entries', metavar='RANGE', default='', | ||||||||
help='return critical if entries lag is outside RANGE') | help='return critical if entries lag is outside RANGE') | ||||||||
args = argp.parse_args() | args = argp.parse_args() | ||||||||
check = nagiosplugin.Check( | check = nagiosplugin.Check( | ||||||||
JournalLag(args.file), | JournalLag(args.file, args.registry, args.entry), | ||||||||
BooleanContext('sameboot'), | BooleanContext('sameboot'), | ||||||||
ScalarContext('lag_time', args.warning, args.critical), | ScalarContext('lag_time', args.warning, args.critical), | ||||||||
ScalarContext('lag_entries', args.warning_entries, args.critical_entries), | ScalarContext('lag_entries', args.warning_entries, args.critical_entries), | ||||||||
JournalSummary(), | JournalSummary(), | ||||||||
) | ) | ||||||||
check.name = 'JOURNAL LAG' | check.name = 'JOURNAL LAG' | ||||||||
check.main(verbose=args.verbose) | check.main(verbose=args.verbose) | ||||||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||||||
main() | main() |
The initial version is fine for raw print statements, it's better for log instruction to do the formatting if need be otherwise.