#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2019             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# tails. You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.


def parse_aws_elbv2_application(info):
    metrics = _extract_aws_metrics_by_labels([
        'ConsumedLCUs',
        'ActiveConnectionCount',
        'NewConnectionCount',
        'RejectedConnectionCount',
        'ClientTLSNegotiationErrorCount',
        'RequestCount',
        'HTTPCode_ELB_3XX_Count',
        'HTTPCode_ELB_4XX_Count',
        'HTTPCode_ELB_5XX_Count',
        'HTTPCode_ELB_500_Count',
        'HTTPCode_ELB_502_Count',
        'HTTPCode_ELB_503_Count',
        'HTTPCode_ELB_504_Count',
        'HTTP_Fixed_Response_Count',
        'HTTP_Redirect_Count',
        'HTTP_Redirect_Url_Limit_Exceeded_Count',
        'ProcessedBytes',
        'RuleEvaluations',
        'IPv6ProcessedBytes',
        'IPv6RequestCount',
    ], parse_aws(info))
    # We get exactly one entry: {INST-ID: METRICS}
    # INST-ID is the piggyback host name
    try:
        return metrics.values()[-1]
    except IndexError:
        return {}


#   .--LCU-----------------------------------------------------------------.
#   |                          _     ____ _   _                            |
#   |                         | |   / ___| | | |                           |
#   |                         | |  | |   | | | |                           |
#   |                         | |__| |___| |_| |                           |
#   |                         |_____\____|\___/                            |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def check_aws_elbv2_application_lcu(item, params, parsed):
    lcus = parsed['ConsumedLCUs']
    yield check_levels(lcus,
                       'aws_consumed_lcus',
                       params.get('levels'),
                       human_readable_func=int,
                       infoname="Consumed")


check_info['aws_elbv2_application'] = {
    'parse_function': parse_aws_elbv2_application,
    'inventory_function': lambda p: inventory_aws_generic_single(p, ['ConsumedLCUs']),
    'check_function': check_aws_elbv2_application_lcu,
    'service_description': 'AWS/ApplicationELB LCUs',
    'includes': ['aws.include'],
    'group': 'aws_elbv2_lcu',
    'has_perfdata': True,
}

#.
#   .--connections---------------------------------------------------------.
#   |                                        _   _                         |
#   |         ___ ___  _ __  _ __   ___  ___| |_(_) ___  _ __  ___         |
#   |        / __/ _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \/ __|        |
#   |       | (_| (_) | | | | | | |  __/ (__| |_| | (_) | | | \__ \        |
#   |        \___\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|___/        |
#   |                                                                      |
#   '----------------------------------------------------------------------'

_aws_elbv2_application_connection_types = [
    'ActiveConnectionCount',
    'NewConnectionCount',
    'RejectedConnectionCount',
    'ClientTLSNegotiationErrorCount',
]


def inventory_aws_elbv2_application_connections(parsed):
    for conn_ty in _aws_elbv2_application_connection_types:
        if conn_ty in parsed:
            return [(None, {})]


def check_aws_elbv2_application_connections(item, params, parsed):
    for conn_ty, (key, title) in zip(_aws_elbv2_application_connection_types, [
        ('Active', 'active'),
        ('New', 'new'),
        ('Rejected', 'rejected'),
        ('TLS errors', 'tls_errors'),
    ]):
        conns = parsed.get(conn_ty)
        if conns is None:
            continue
        yield check_levels(conns,
                           'aws_%s_connections' % key,
                           None,
                           human_readable_func=int,
                           infoname=title)


check_info['aws_elbv2_application.connections'] = {
    'parse_function': parse_aws_elbv2_application,
    'inventory_function': inventory_aws_elbv2_application_connections,
    'check_function': check_aws_elbv2_application_connections,
    'service_description': 'AWS/ApplicationELB Connections',
    'includes': ['aws.include'],
    'has_perfdata': True,
}

#.
#   .--HTTP ELB------------------------------------------------------------.
#   |             _   _ _____ _____ ____    _____ _     ____               |
#   |            | | | |_   _|_   _|  _ \  | ____| |   | __ )              |
#   |            | |_| | | |   | | | |_) | |  _| | |   |  _ \              |
#   |            |  _  | | |   | | |  __/  | |___| |___| |_) |             |
#   |            |_| |_| |_|   |_| |_|     |_____|_____|____/              |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def check_aws_elbv2_application_http_elb(item, params, parsed):
    now = time.time()
    request_count = parsed.get('RequestCount')
    if request_count is not None:
        request_rate = get_rate('aws_elb_statistics', now, request_count)
        yield 0, 'Requests: %s/s' % request_rate, [('requests_per_second', request_rate)]
    else:
        request_rate = 0

    for http_errors_nr in ["4", "5"]:
        http_errors = parsed.get('HTTPCode_ELB_%sXX_Count' % http_errors_nr)
        if http_errors is None:
            continue

        http_errors_rate = get_rate('aws_elbv2_http_elb.%sxx' % http_errors_nr, now, http_errors)
        yield (0, '%sXX-Errors: %s/s' % (http_errors_nr, http_errors_rate),
               [('http_%sxx_rate' % http_errors_nr, http_errors_rate)])

        try:
            http_errors_perc = 100.0 * http_errors_rate / request_rate
        except ZeroDivisionError:
            pass
        else:
            yield check_levels(http_errors_perc,
                               'http_%sxx_perc' % http_errors_nr,
                               params.get('levels_http_%sxx_perc' % http_errors_nr),
                               human_readable_func=get_percent_human_readable,
                               infoname="%sXX-Errors of total requests" % http_errors_nr)

    http_backend_3xx = parsed.get('HTTPCode_ELB_3XX_Count')
    if http_backend_3xx is not None:
        yield 0, '3XX-Requests: %s/s' % get_rate('aws_elbv2_http_elb.3xx', now, http_backend_3xx)

    for http_500_errors_nr in ["0", "2", "3", "4"]:
        http_500_errors = parsed.get('HTTPCode_ELB_50%s_Count' % http_500_errors_nr)
        if http_500_errors is None:
            continue

        http_500_errors_rate = get_rate('aws_elbv2_http_elb.50%s' % http_500_errors_nr, now,
                                        http_500_errors)
        yield 0, '50%s-Errors: %s/s' % (http_500_errors_nr, http_500_errors_rate)


check_info['aws_elbv2_application.http_elb'] = {
    'inventory_function': lambda p: inventory_aws_generic_single(p, [
        'RequestCount', 'HTTPCode_ELB_3XX_Count', 'HTTPCode_ELB_4XX_Count', 'HTTPCode_ELB_5XX_Count'
    ]),
    'check_function': check_aws_elbv2_application_http_elb,
    'service_description': 'AWS/ApplicationELB HTTP ELB',
    'includes': ['aws.include'],
    'group': 'aws_elb_http',
    'has_perfdata': True,
}

#.
#   .--HTTP redirects------------------------------------------------------.
#   |  _   _ _____ _____ ____                 _ _               _          |
#   | | | | |_   _|_   _|  _ \   _ __ ___  __| (_)_ __ ___  ___| |_ ___    |
#   | | |_| | | |   | | | |_) | | '__/ _ \/ _` | | '__/ _ \/ __| __/ __|   |
#   | |  _  | | |   | | |  __/  | | |  __/ (_| | | | |  __/ (__| |_\__ \   |
#   | |_| |_| |_|   |_| |_|     |_|  \___|\__,_|_|_|  \___|\___|\__|___/   |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def check_aws_elbv2_application_http_redirects(item, params, parsed):
    for redirect_ty, title, key in [
        ('HTTP_Redirect_Count', 'Successful', 'http_redirects'),
        ('HTTP_Redirect_Url_Limit_Exceeded_Count', 'Not completed', 'http_redirect_url_limit'),
        ('HTTP_Fixed_Response_Count', 'Successful fixed-responses', 'http_fixed_response'),
    ]:
        redirects = parsed.get(redirect_ty)
        if redirects is None:
            continue
        yield check_levels(redirects, 'aws_%s' % key, None, human_readable_func=int, infoname=title)


check_info['aws_elbv2_application.http_redirects'] = {
    'inventory_function': lambda p: inventory_aws_generic_single(p, [
        'HTTP_Redirect_Count',
        'HTTP_Redirect_Url_Limit_Exceeded_Count',
    ]),
    'check_function': check_aws_elbv2_application_http_redirects,
    'service_description': 'AWS/ApplicationELB HTTP Redirects',
    'includes': ['aws.include'],
    'has_perfdata': True,
}

#.
#   .--statistics----------------------------------------------------------.
#   |                    _        _   _     _   _                          |
#   |                ___| |_ __ _| |_(_)___| |_(_) ___ ___                 |
#   |               / __| __/ _` | __| / __| __| |/ __/ __|                |
#   |               \__ \ || (_| | |_| \__ \ |_| | (__\__ \                |
#   |               |___/\__\__,_|\__|_|___/\__|_|\___|___/                |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def inventory_aws_elbv2_application_statistics(parsed):
    for metric in [
            'ProcessedBytes',
            'IPv6ProcessedBytes',
            'IPv6RequestCount',
            'RuleEvaluations',
    ]:
        if metric in parsed:
            return [(None, {})]


def check_aws_elbv2_application_statistics(item, params, parsed):
    processed_bytes = parsed.get('ProcessedBytes')
    if processed_bytes is not None:
        yield check_levels(processed_bytes,
                           "aws_proc_bytes",
                           None,
                           human_readable_func=get_bytes_human_readable,
                           infoname="Processed bytes")

    ipv6_processed_bytes = parsed.get('IPv6ProcessedBytes')
    if ipv6_processed_bytes is not None:
        yield check_levels(ipv6_processed_bytes,
                           "aws_ipv6_proc_bytes",
                           None,
                           human_readable_func=get_bytes_human_readable,
                           infoname="IPv6 Processed bytes")

    ipv6_requests = parsed.get('IPv6RequestCount')
    if ipv6_requests is not None:
        yield check_levels(ipv6_requests,
                           "aws_ipv6_requests",
                           None,
                           human_readable_func=int,
                           infoname="IPv6 requests")

    rule_evaluations = parsed.get('RuleEvaluations')
    if rule_evaluations is not None:
        yield check_levels(rule_evaluations,
                           'aws_rule_evaluations',
                           None,
                           human_readable_func=int,
                           infoname="Rule evaluations")


check_info['aws_elbv2_application.statistics'] = {
    'inventory_function': inventory_aws_elbv2_application_statistics,
    'check_function': check_aws_elbv2_application_statistics,
    'service_description': 'AWS/ApplicationELB Statistics',
    'includes': ['aws.include'],
    'has_perfdata': True,
}
