Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
dship2postgis / check_mk_service.py
Size: Mime:
from gmr_underway_connect.underway_data import UnderwayDailyHandler, UnderwayNmeaHandler
from dshipparser import helpers
import email, datetime, logging
from dateutil import parser as datetime_parser
import chardet
"""
Service can be called to perform checks which will generate check_mk compatible output
see https://mathias-kettner.de/checkmk_localchecks.html
"""
#_date_response_format = '%a, %d %b %Y %H:%M:%S %z'  # format of Date field in mail headers, e.g. 'Fri, 27 Apr 2018 00:08:08 +0000'


default_warn_nmea = 12
default_crit_nmea = 24

default_warn_daily = 26
default_crit_daily = 48


def get_dates_from_mails(mail_handler):
    mail_ids = mail_handler.get_mail_ids(10)
    if not mail_ids:  # Folder is empty, no mails found
        return None
    status, raw_headers = mail_handler.udw_mail.get_mail_connection().fetch(mail_ids, '(BODY.PEEK[HEADER])')
    dates = []
    raw_dates = []
    for response_part in raw_headers:
        if isinstance(response_part, tuple):
            part = response_part[1]
            part = part.decode(chardet.detect(part)['encoding'])
            msg = email.message_from_string(part)
            # print(msg.keys())
            raw_date = msg['Date']
            raw_dates.append(raw_date)
            the_date = None
            try:
                the_date = datetime_parser.parse(raw_date)
            except ValueError as exc:
                pass
            if not the_date:
                # after dship-update, dates like 'Di, 15 Dez 2020 00:16:42 0000' are returned
                #  which cannot be parsed. Alternatively, look for date in received header
                #  written by geomar mta
                try:
                    raw_date = msg.get_all('received')[0].split(';')[-1]
                    the_date = datetime_parser.parse(raw_date)
                    dates.append(the_date)
                except Exception:
                    raise ValueError(f"Could not parse date from '{raw_date}'") from exc

            dates.append(the_date)

    return dates


def get_age_of_mails_as_hours(mail_handler):
    dates = get_dates_from_mails(mail_handler)
    if dates == None:  #  returned when no mails were foundn in folder
        return [9999]
    deltas = [datetime.datetime.utcnow() - d.replace(tzinfo=None) for d in dates]
    return [d.days * 24 + d.seconds // 3600 for d in deltas]


def get_age_last_nmea_mail(platform):
    """Returns age (in hours) of the last NMEA telegram found.
        Age is taken from email timestamp, not NMEA timestamp!
    """
    mh = UnderwayNmeaHandler(platform)
    return min(get_age_of_mails_as_hours(mh))


def get_age_last_daily_mail(platform):
    """Returns age (in hours) of the last NMEA telegram found.
        Age is taken from email timestamp, not NMEA timestamp!
    """
    mh = UnderwayDailyHandler(platform)
    return min(get_age_of_mails_as_hours(mh))


def do_check_age_nmea(platform, warn=default_warn_nmea, crit=default_crit_nmea):
    return _do_check('nmea', platform, warn, crit)


def do_check_age_daily(platform, warn=default_warn_daily, crit=default_crit_daily):
    return _do_check('daily', platform, warn, crit)


def _do_check(check_type, platform, warn, crit):
    status = 3  # UNKNOWN
    try:
        if check_type == 'nmea':
            age = get_age_last_nmea_mail(platform)
        else:
            age = get_age_last_daily_mail(platform)

        if age == 9999:
            status = 2  # CRITICAL
            status_txt = f'CRITICAL - No {check_type} mails found for {platform}!'

        elif age < warn:
            status = 0  # OK
            status_txt = f'OK - age of last {check_type} mail for {platform} is less than {warn} hours'
        elif warn <= age < crit:
            status = 1  # WARNING
            status_txt = f'WARNING - age of last {check_type} mail for {platform} is more than {warn} hours'
        elif crit < age:
            status = 2  # CRITICAL
            status_txt = f'CRITICAL - age of last {check_type} mail for {platform} is more than {crit} hours'

    except Exception as e:
        status = 3  # UNKNOWN
        age = 'N/A'
        error_str = str(e)
        logging.error(f'ERROR - age check for {platform} resulted in error: {error_str}')
        status_txt = f'ERROR - age check for {platform} resulted in error: {error_str}'

    return f"{status} age_check_{check_type}_{platform} age={age};{warn};{crit} {status_txt}"