diff --git a/check_mk-informix/Informix_transactions-1.0.1.mkp b/check_mk-informix/Informix_transactions-1.0.1.mkp new file mode 100644 index 0000000..764c170 Binary files /dev/null and b/check_mk-informix/Informix_transactions-1.0.1.mkp differ diff --git a/check_mk-informix/README.MD b/check_mk-informix/README.MD new file mode 100644 index 0000000..8b745f8 --- /dev/null +++ b/check_mk-informix/README.MD @@ -0,0 +1,22 @@ +{'author': 'George Pochiscan', + 'description': 'This package extends current informix package with the ' + 'following checks:\n' + '\n' + 'Alert if the number of locks kept by a session is higher than ' + 'a specific number (configured by WATO rule).\n' + 'Inactive transactions with locks \n' + 'Long transactions\n', + 'download_url': '', + 'files': {'agents': ['plugins/mk_informix'], + 'checkman': ['informix_transactions_activity', + 'informix_transactions_locks', + 'informix_transactions_long_transactions'], + 'checks': ['informix_transactions'], + 'web': ['plugins/wato/informix_nlocks.py']}, + 'name': 'Informix_transactions', + 'num_files': 6, + 'title': 'Informix monitoring', + 'version': '1.0.1', + 'version.min_required': '2.0.0p17', + 'version.packaged': '2.0.0p17', + 'version.usable_until': None} diff --git a/check_mk-informix/checkman/informix_transactions_activity b/check_mk-informix/checkman/informix_transactions_activity new file mode 100644 index 0000000..cc622c8 --- /dev/null +++ b/check_mk-informix/checkman/informix_transactions_activity @@ -0,0 +1,16 @@ +title: Informix DB: Sessions with no activity in current log +agents: linux +catalog: app/informix +license: GPL +distribution: check_mk +description: + This checks monitors the transactions that doesn't + have activity in current log in Informix Database application. + + No rules are needed. + +item: + Name of the instance + +inventory: + One service is created for each instance. diff --git a/check_mk-informix/checkman/informix_transactions_locks b/check_mk-informix/checkman/informix_transactions_locks new file mode 100644 index 0000000..ede9950 --- /dev/null +++ b/check_mk-informix/checkman/informix_transactions_locks @@ -0,0 +1,16 @@ +title: Informix DB: Sessions with high number of locks +agents: linux +catalog: app/informix +license: GPL +distribution: check_mk +description: + This checks monitors the sessions that have + high number of locks in Informix Database application. + + WARN and CRIT levels can be specified. + +item: + Name of the instance + +inventory: + One service is created for each instance. diff --git a/check_mk-informix/checkman/informix_transactions_long_transactions b/check_mk-informix/checkman/informix_transactions_long_transactions new file mode 100644 index 0000000..7eff5c3 --- /dev/null +++ b/check_mk-informix/checkman/informix_transactions_long_transactions @@ -0,0 +1,16 @@ +title: Informix DB: Long transactions that are using more than 3 logical logs +agents: linux +catalog: app/informix +license: GPL +distribution: check_mk +description: + This checks monitors the transactions that are using + more than 3 logical logs in Informix Database application. + + No rules are needed. + +item: + Name of the instance + +inventory: + One service is created for each instance. diff --git a/check_mk-informix/checks/informix_transactions b/check_mk-informix/checks/informix_transactions new file mode 100644 index 0000000..fbdbb24 --- /dev/null +++ b/check_mk-informix/checks/informix_transactions @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +factory_settings['informix_transactions_default_levels'] = { + 'levels': (70, 80), +} +#first line represents current log ID +#line[2]= sessionID +#line[3]= number of locks kept by sessionID +#line[4]= begin log position +#line[5]= current log position + + +def parse_informix_transactions(info): + parsed = {} + instance = None + entry = None + for line in info: + if line[0].startswith("[[[") and line[0].endswith("]]]"): + instance = line[0][3:-3] + + elif instance is not None: + entry = {} + parsed.setdefault(instance, []) + parsed[instance].append(entry) + if "C" in line[2]: + entry.setdefault("current_log_id", line[3]) + elif entry is not None: + if ":" in str(line[4]): + line[4] = line[4].split(":",1)[0] + if ":" in str(line[5]): + line[5] = line[5].split(":",1)[0] + + entry.setdefault("session", [line[2], line[3], line[4], line[5]]) + return parsed + +#############Transaction with more than 70 locks +def inventory_informix_transactions_locks(parsed): + return [(instance, {}) for instance in parsed] + + +def check_informix_transactions_locks(item, params, parsed): + if item in parsed: + warn, crit = params['levels'] + data = parsed[item] + infotext = "" + state = 0 + for session in data[1:]: + if "-" not in session["session"][1]: + if int(session["session"][1]) >= crit: + state = 2 + infotext += 'Session with ID %s has %s locks; ' % (session["session"][0], session["session"][1]) + elif int(session["session"][1]) >= warn: + state = 1 + infotext += 'Session with ID %s has %s locks; ' % (session["session"][0], session["session"][1]) + + if state: + infotext += " (warn/crit at %s/%s)" % (warn, crit) + else: + infotext = 'There are no sessions with high number of locks' + return state, infotext, [] + + +check_info['informix_transactions.locks'] = { + 'parse_function': parse_informix_transactions, + 'inventory_function': inventory_informix_transactions_locks, + 'check_function': check_informix_transactions_locks, + 'has_perfdata': False, + 'service_description': 'Informix sessions nLocks %s', + "group": "informix_nlocks", + 'default_levels_variable': 'informix_transactions_default_levels', +} + + +#############Sesiuni fara activitate in logul curent +def inventory_informix_transactions_activity(parsed): + return [(instance, {}) for instance in parsed] + + +def check_informix_transactions_activity(item, no_params, parsed): + if item in parsed: + data = parsed[item] + state = 0 + infotext = '' + for session in data[1:]: + if "-" not in session["session"][2]: + if int(session["session"][2]) < int(data[0]['current_log_id']): + state = 2 + infotext += "Session %s doesn't have activity in current log; " % (session["session"][0]) + + + if not state: + infotext = 'There are no sessions with no activity in current log; ' + + return state, infotext, [] + + +check_info['informix_transactions.activity'] = { + 'parse_function': parse_informix_transactions, + 'inventory_function': inventory_informix_transactions_activity, + 'check_function': check_informix_transactions_activity, + 'has_perfdata': False, + 'service_description': 'Informix sessions activity %s', +} + +#############Long transactions (over 3 logical logs used) +def inventory_informix_long_transactions(parsed): + return [(instance, {}) for instance in parsed] + + +def check_informix_long_transactions(item, no_params, parsed): + if item in parsed: + data = parsed[item] + state = 0 + infotext = '' + for session in data[1:]: + if "-" not in session["session"][2]: + if (int(session["session"][2]) - int(session["session"][3])) < 2: + state = 2 + infotext += "Session %s is using more than 3 logical logs; " % (session["session"][0]) + + + if not state: + infotext = 'There are no long running transactions; ' + + return state, infotext, [] + + +check_info['informix_transactions.long_transactions'] = { + 'parse_function': parse_informix_transactions, + 'inventory_function': inventory_informix_long_transactions, + 'check_function': check_informix_long_transactions, + 'has_perfdata': False, + 'service_description': 'Informix sessions Long transactions %s', +} diff --git a/check_mk-informix/plugins/mk_informix b/check_mk-informix/plugins/mk_informix new file mode 100755 index 0000000..fba88cc --- /dev/null +++ b/check_mk-informix/plugins/mk_informix @@ -0,0 +1,296 @@ +#!/bin/bash +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +# Reason for this no-op: shellcheck disable=... before the first command disables the error for the +# entire script. +: + +# Disable unused variable error (needed to keep track of version) +# shellcheck disable=SC2034 +CMK_VERSION="2.0.0p17" + +# Informix +# Make ENV-VARs avail for subshells +set -a + +# .--helper--------------------------------------------------------------. +# | _ _ | +# | | |__ ___| |_ __ ___ _ __ | +# | | '_ \ / _ \ | '_ \ / _ \ '__| | +# | | | | | __/ | |_) | __/ | | +# | |_| |_|\___|_| .__/ \___|_| | +# | |_| | +# '----------------------------------------------------------------------' + + +function do_check () { + # $1:section, $2:excludelist + if echo "$2" | grep -qe "${1}"; then + return 1 + else + return 0 + fi +} + + +function sql () { + db="sysmaster" + sqltxt="$1" + export DBDELIMITER="|" + echo "$sqltxt" | dbaccess ${db} +} + + +function set_excludes () { + excludes="" + if [ "$EXCLUDES" = "ALL" ]; then + excludes="$all_sections" + global_exclude=true + elif [ ! -z "$EXCLUDES" ]; then + excludes=$EXCLUDES + global_exclude=true + else + global_exclude=false + fi + + if [ "$global_exclude" = "false" ]; then + excludes_i="EXCLUDES_${1}" + if [ "${!excludes_i}" = "ALL" ]; then + excludes="$all_sections" + elif [ ! -z "${!excludes_i}" ]; then + excludes=${!excludes_i} + fi + fi +} + + +#. +# .--sqls----------------------------------------------------------------. +# | _ | +# | ___ __ _| |___ | +# | / __|/ _` | / __| | +# | \__ \ (_| | \__ \ | +# | |___/\__, |_|___/ | +# | |_| | +# '----------------------------------------------------------------------' + + +all_sections="sessions locks tabextents dbspaces logusage" + + +function informix_status(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + $INFORMIXDIR/bin/onstat - >/dev/null 2>&1 + state=$? + echo "Status:"$state + $INFORMIXDIR/bin/onstat -g dis + port=$(grep $INFORMIXSERVER /etc/services) + echo "PORT:"$port +} + + +function informix_sessions(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + # don't count our own session + sql "select 'SESSIONS', (count(*)-1)::int from syssessions" +} + + +function informix_locks(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + # don't count our own session + sql "select 'LOCKS', (count(*)-1)::int, type from syslocks group by type" +} + + +function informix_tabextents(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + sql "select first 10 + 'TABEXTENTS', + trim(n.dbsname) db, + trim(n.tabname) tab, + h.nextns extents, + nrows + from sysptnhdr h, systabnames n + where h.partnum = n.partnum + and nrows > 0 + and n.dbsname not in ( 'sysadmin', 'sysuser', 'sysutils', 'sysmaster' ) + and n.tabname not like 'sys%' + order by extents desc" +} + + +function informix_dbspaces(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + sql "select + trim(sd.name) || ' DBSPACE', + sd.dbsnum, + sd.is_temp, + sd.flags, + 'CHUNK', + sc.fname, + sc.pagesize, + sc.chksize, + sc.nfree, + sc.flags, + trim(sc.mfname), + sc.mflags + from sysdbspaces sd, syschunks sc + where sd.dbsnum = sc.dbsnum + -- NO SBSPACE CURRENTLY + and sd.is_sbspace = 0 + order by sd.name" +} + + +function informix_logusage(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + sql "select 'LOGUSAGE', + number, + sh_pagesize, + size, + used, + flags, + 'is_used:'||is_used, + 'is_current:'||is_current, + 'is_backed_up:'||is_backed_up, + 'is_new:'||is_new, + 'is_archived:'||is_archived, + 'is_temp:'||is_temp, + 'is_pre_dropped:'||is_pre_dropped + from syslogs, sysshmvals + order by number" +} + + +function informix_transactions(){ + echo "<<>>" + echo "[[[$INFORMIXSERVER/$SERVERNUM]]]" + $INFORMIXDIR/bin/onstat -l | grep C | tail -n 1 + $INFORMIXDIR/bin/onstat -x |egrep -v "IBM|maximum|Transactions|est.|userthread" | sed 's/:[^:]*$//' +} +#. +# .--config--------------------------------------------------------------. +# | __ _ | +# | ___ ___ _ __ / _(_) __ _ | +# | / __/ _ \| '_ \| |_| |/ _` | | +# | | (_| (_) | | | | _| | (_| | | +# | \___\___/|_| |_|_| |_|\__, | | +# | |___/ | +# '----------------------------------------------------------------------' + + +# Config opts: +# - oninit-path; Default is empty, which means autodetection: +# ONINIT_PATH= +# - Excluding sections ("status sessions locks tabextents dbspaces logusage"): +# EXCLUDES_INFORMIX_INSTANCE="SECTION SECTION ..." +# EXCLUDES_INFORMIX_INSTANCE=ALL +# EXCLUDES="SECTION SECTION ..." +# EXCLUDES=ALL + + +if [ -f "$MK_CONFDIR/informix.cfg" ]; then + . $MK_CONFDIR/informix.cfg +fi + + +if [ -z "$ONINIT_PATH" -o ! -x "$ONINIT_PATH" ]; then + ONINIT=$(UNIX95=true ps ax | grep oninit | grep -v grep | head -1 | awk '{print $1 " " $5}') + if [ -z "$ONINIT" ]; then + exit 0 + fi + + ONINIT_PATH=${ONINIT#* } + ONINIT_PID=${ONINIT% *} + case "$ONINIT_PATH" in + /*) + ;; + *) # BUG not platform independent! + ONINIT_PATH=$(ls -l /proc/$ONINIT_PID/exe 2>/dev/null| sed 's/.* //') + ;; + esac + + # If not set in config or not found we end up here + if [ -z "$ONINIT_PATH" -o ! -f "$ONINIT_PATH" ]; then + exit 1 + fi +fi + + +#. +# .--main----------------------------------------------------------------. +# | _ | +# | _ __ ___ __ _(_)_ __ | +# | | '_ ` _ \ / _` | | '_ \ | +# | | | | | | | (_| | | | | | | +# | |_| |_| |_|\__,_|_|_| |_| | +# | | +# '----------------------------------------------------------------------' + + +for IDSENV in $( export INFORMIXDIR=${ONINIT_PATH%/bin*} + $INFORMIXDIR/bin/onstat -g dis | \ + egrep '^Server[ ]*:|^Server Number[ ]*:|^INFORMIX|^SQLHOSTS|^ONCONFIG' | \ + sed -e 's/Server Number/SERVERNUM/' \ + -e 's/Server/INFORMIXSERVER/' \ + -e 's/SQLHOSTS/INFORMIXSQLHOSTS/' \ + -e 's/[ ]*:[ ]*/=/' | \ + tr '\n' ';' | \ + sed -e 's/;$/\\n/' -e 's/;\(INFORMIXSERVER=[^;]*;\)/\\n\1/g' | \ + awk '{ gsub(/\\n/,"\n")}1' + ) ; do + ( + # Set environment + eval $IDSENV + PATH=$INFORMIXDIR/bin:$PATH + + # try to set them via 'onstat -g env' otherwise + # DB HAS TO BE RUNNING + if [ -z "$INFORMIXSQLHOSTS" -o -z "$ONCONFIG" ]; then + onstat -g env | egrep -e '^INFORMIXSQLHOSTS' \ + -e '^ONCONFIG' | \ + sed -e 's/[ ][ ]*/=/' + fi + + informix_status + + set_excludes $INFORMIXSERVER + + if do_check "sessions" "$excludes"; then + informix_sessions + fi + + if do_check "locks" "$excludes"; then + informix_locks + fi + + if do_check "tabextents" "$excludes"; then + informix_tabextents + fi + + if do_check "dbspaces" "$excludes"; then + informix_dbspaces + fi + + if do_check "logusage" "$excludes"; then + informix_logusage + fi + + if do_check "transactions" "$excludes"; then + informix_transactions + fi + + ) +done + + + diff --git a/check_mk-informix/web/plugins/wato/informix_nlocks.py b/check_mk-informix/web/plugins/wato/informix_nlocks.py new file mode 100644 index 0000000..17eaf2e --- /dev/null +++ b/check_mk-informix/web/plugins/wato/informix_nlocks.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +from cmk.gui.i18n import _ +from cmk.gui.valuespec import ( + Dictionary, + Integer, + Tuple, +) + +from cmk.gui.plugins.wato import ( + CheckParameterRulespecWithoutItem, + rulespec_registry, + RulespecGroupCheckParametersApplications, +) + + +def _parameter_valuespec_informix_nlocks(): + return Dictionary(elements=[ + ("levels", + Tuple( + title=_("Levels for number of locks for a session"), + help= + _("You can set a limit to the number of locks for a session in Informix Database application" + ), + elements=[ + Integer(title=_("Warning at"), default_value=40), + Integer(title=_("Critical at"), default_value=70), + ], + )), + ]) + + +rulespec_registry.register( + CheckParameterRulespecWithoutItem( + check_group_name="informix_nlocks", + group=RulespecGroupCheckParametersApplications, + match_type="dict", + parameter_valuespec=_parameter_valuespec_informix_nlocks, + title=lambda: _("Informix number of Locks"), + ))