#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             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-
# ails.  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.

# <<<mysql>>>
# Aborted_clients 0
# Aborted_connects        15
# Binlog_cache_disk_use   0
# Binlog_cache_use        0
# Binlog_stmt_cache_disk_use      0
# Binlog_stmt_cache_use   0
# Bytes_received  7198841
# Bytes_sent      19266624
# Com_admin_commands      200
# Com_assign_to_keycache  0
# Com_alter_db    0
# Com_alter_db_upgrade    0

#   .--Helpers-------------------------------------------------------------.
#   |                  _   _      _                                        |
#   |                 | | | | ___| |_ __   ___ _ __ ___                    |
#   |                 | |_| |/ _ \ | '_ \ / _ \ '__/ __|                   |
#   |                 |  _  |  __/ | |_) |  __/ |  \__ \                   |
#   |                 |_| |_|\___|_| .__/ \___|_|  |___/                   |
#   |                              |_|                                     |
#   '----------------------------------------------------------------------'

def inventory_mysql(info):
    if len(info) > 200: # should be at least 321 line
        return [(None, {})]

def parse_mysql(info):
    values = {}
    for line in info:
        if len(line) == 2:
            varname, value = line
            try:
                value = int(value)
            except:
                pass
        else:
            varname = line[0]
            value = None

        values[varname] = value
    return values

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

# params:
# { "running" : (20, 40),
#    "total" : (100, 400),
#    "connections" : (3, 5 ),
# }


def check_mysql_sessions(_no_item, params, info):
    values = parse_mysql(info)
    total_sessions = values["Threads_connected"]
    running_sessions = values["Threads_running"]
    connections = get_rate("mysql.sessions", time.time(), values["Connections"])

    infotext = " - %d sessions (%d running), %.2f connections/s" % (
        total_sessions, running_sessions, connections)

    infos = []
    perfdata = []
    status = 0

    for value, what, format, unit in [
        ( total_sessions,   "total",       "%d",   "" ),
        ( running_sessions, "running",     "%d",   "" ),
        ( connections,      "connections", "%.2f", "/s")]:
        infos.append((format + " %s%s") % (value, what, unit))
        if what in params:
            warn, crit = params[what]
            if value >= crit:
                status = 2
                infos[-1] += "(!!)"
            elif value >= warn:
                status = max(status, 1)
                infos[-1] += "(!)"
        else:
            warn, crit = None, None
        perfdata.append((what, value, warn, crit))

    return (status, ", ".join(infos), perfdata)


check_info['mysql.sessions'] = {
    "check_function"          : check_mysql_sessions,
    "inventory_function"      : inventory_mysql,
    "service_description"     : "MySQL Daemon Sessions",
    "has_perfdata"            : True,
    "group"                   : "mysql_sessions",
}

#.
#   .--InnoDB-IO-----------------------------------------------------------.
#   |           ___                   ____  ____       ___ ___             |
#   |          |_ _|_ __  _ __   ___ |  _ \| __ )     |_ _/ _ \            |
#   |           | || '_ \| '_ \ / _ \| | | |  _ \ _____| | | | |           |
#   |           | || | | | | | | (_) | |_| | |_) |_____| | |_| |           |
#   |          |___|_| |_|_| |_|\___/|____/|____/     |___\___/            |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_mysql_iostat(info):
    values = parse_mysql(info)
    if "Innodb_data_read" in values.keys():
        return [(None, {})]

def check_mysql_iostat(item, params, info):
    values = parse_mysql(info)
    line = [ None, None, values["Innodb_data_read"] / 512, values["Innodb_data_written"] / 512]
    return check_diskstat_line(time.time(), 'innodb_io', params, line)


check_info['mysql.innodb_io'] = {
    "includes"                : [ "diskstat.include" ],
    "check_function"          : check_mysql_iostat,
    "inventory_function"      : inventory_mysql_iostat,
    "service_description"     : "MySQL Daemon InnoDB IO",
    "has_perfdata"            : True,
    "group"                   : "mysql_innodb_io",
}

#.
#   .--Connections---------------------------------------------------------.
#   |        ____                            _   _                         |
#   |       / ___|___  _ __  _ __   ___  ___| |_(_) ___  _ __  ___         |
#   |      | |   / _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \/ __|        |
#   |      | |__| (_) | | | | | | |  __/ (__| |_| | (_) | | | \__ \        |
#   |       \____\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|___/        |
#   |                                                                      |
#   +----------------------------------------------------------------------+

def inventory_mysql_connections(info):
    values = parse_mysql(info)
    if 'Max_used_connections' in values and 'max_connections' in values:
        return [(None, {})]

def check_mysql_connections(item, params, info):
    values = parse_mysql(info)
    if 'Max_used_connections' not in values:
        return (3, 'Connection information are missing')

    # The maximum number of connections that have been in use simultaneously
    # since the server started.
    conn = float(values['Max_used_connections'])
    # Maximum number of possible parallel connections
    max_conn = float(values['max_connections'])

    perc_used = conn / max_conn * 100

    status = 0
    status_txt = ''
    if 'perc_used' in params:
        warn, crit = params['perc_used']
        if perc_used >= crit:
            status = 2
            status_txt = ' (Threshold (%0.2f%%) for number of maximum parallel connections ' \
                         'has been reached at least once since program start' % crit
        elif perc_used >= warn:
            status = 1
            status_txt = ' (Threshold (%0.2f%%) for number of maximum parallel connections ' \
                         'has been reached at least once since program start)' % warn

    return (status, 'Max. parallel Connections: %d (Max.: %d): %0.2f%%%s' %
        (conn, max_conn, perc_used, status_txt))


check_info['mysql.connections'] = {
    "check_function"          : check_mysql_connections,
    "inventory_function"      : inventory_mysql_connections,
    "service_description"     : "MySQL Daemon Connections",
    "has_perfdata"            : False,
    "group"                   : "mysql_connections",
}

