Add an informix_transactions plugin version that works for CheckMK v2.4.
This commit is contained in:
parent
0c882e643c
commit
fed4e940c0
BIN
informix/2.4/informix_transactions-1.1.0.mkp
Executable file
BIN
informix/2.4/informix_transactions-1.1.0.mkp
Executable file
Binary file not shown.
@ -0,0 +1,220 @@
|
||||
# Copyright 2026 Spearhead Systems SRL
|
||||
# Copyright (C) 2019 tribe29 GmbH
|
||||
#
|
||||
# Expected example input (and expect arbitrary blank lines):
|
||||
#
|
||||
# <<<informix_transactions>>>
|
||||
# [[[1/2]]]
|
||||
# a40dbb0 6 U---C-L 6 1:3263 500 372 74.40
|
||||
#
|
||||
# a6d8028 A---- a695028 0 - - COMMIT - 0
|
||||
# a6d8348 A---- a695878 0 - - COMMIT - 0
|
||||
# a6d8668 A---- a6960c8 0 - - COMMIT - 0
|
||||
# a6d8988 A---- a696918 0 - - COMMIT - 0
|
||||
# a6d8fc8 A---- a698208 0 - - COMMIT - 0
|
||||
# a6d92e8 A---- a6979b8 0 - - COMMIT - 0
|
||||
# a6d9608 A---- a698a58 0 - - COMMIT - 0
|
||||
# a6d9928 A---- a6992a8 1 - - DIRTY - 0
|
||||
# a6d9c48 A---- a6992a8 0 - - NOTRANS - 0
|
||||
# a6d9f68 A---- a69a348 0 - - COMMIT - 0
|
||||
# a6da288 A---- a69ab98 0 - - COMMIT - 0
|
||||
# a6da5a8 A---- a69b3e8 0 - - COMMIT - 0
|
||||
# a6da8c8 A---- a69bc38 0 - - COMMIT - 0
|
||||
# a6dabe8 A---- a69c488 0 - - COMMIT - 0
|
||||
# a6daf08 A---- a699af8 0 - - COMMIT - 0
|
||||
# a6db228 A---- a6992a8 0 - - COMMIT - 0
|
||||
# a6db548 A---- a69ccd8 1 - - DIRTY - 0
|
||||
# a6db868 A---- a69d528 1 - - DIRTY - 0
|
||||
# a6dbb88 A---- a69ccd8 0 - - COMMIT - 0
|
||||
# a6dbea8 A---- a69dd78 0 - - COMMIT - 0
|
||||
# a6dc1c8 A---- a69e5c8 0 - - COMMIT - 0
|
||||
# a6dc4e8 A-B-- a69ee18 502 33:0x25018 34:0x486fc COMMIT 0
|
||||
|
||||
|
||||
import json
|
||||
from cmk.agent_based.v2 import (
|
||||
Result,
|
||||
Service,
|
||||
Metric,
|
||||
State,
|
||||
CheckPlugin,
|
||||
AgentSection,
|
||||
)
|
||||
|
||||
|
||||
# This is what the columns from the onstat -x output represent:
|
||||
#
|
||||
# line[0]= first line represents current log ID
|
||||
# line[1]= <ignore>
|
||||
# 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(string_table):
|
||||
instance = string_table[0][0][3:-3]
|
||||
curr_log = ""
|
||||
sessions = []
|
||||
|
||||
for line in string_table[1:]:
|
||||
if len(line) <= 5:
|
||||
continue
|
||||
|
||||
if "C" in line[2]:
|
||||
curr_log = int(line[3])
|
||||
continue
|
||||
|
||||
if ":" in line[4]:
|
||||
line[4] = int(line[4].split(":")[0])
|
||||
else:
|
||||
line[4] = None
|
||||
|
||||
if ":" in line[5]:
|
||||
line[5] = int(line[5].split(":")[0])
|
||||
else:
|
||||
line[5] = None
|
||||
|
||||
sessions.append({
|
||||
"id": line[2],
|
||||
"locks": int(line[3]),
|
||||
"log_start": line[4],
|
||||
"log_end": line[5],
|
||||
})
|
||||
|
||||
return {
|
||||
instance: {
|
||||
"curr_log": curr_log,
|
||||
"sessions": sessions,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def discover_informix_transactions(section):
|
||||
for instance in section:
|
||||
yield Service(item=instance)
|
||||
|
||||
|
||||
def check_informix_locks(item, params, section):
|
||||
data = section.get(item)
|
||||
if not data:
|
||||
return
|
||||
|
||||
levels = params.get("levels")
|
||||
infotext = ""
|
||||
state = State.OK
|
||||
max_locks = 0
|
||||
|
||||
if levels and levels[0] == "fixed":
|
||||
warn, crit = levels[1]
|
||||
else:
|
||||
warn, crit = None, None
|
||||
|
||||
for session in data["sessions"]:
|
||||
id = session["id"]
|
||||
locks = session["locks"]
|
||||
log_start = session["log_start"]
|
||||
|
||||
max_locks = max(max_locks, locks)
|
||||
|
||||
if log_start == "-":
|
||||
continue
|
||||
|
||||
if crit and locks >= crit:
|
||||
state = State.CRIT
|
||||
infotext += f"Session with ID {id} has {locks} locks; "
|
||||
elif warn and locks >= warn:
|
||||
state = State.WARN
|
||||
infotext += f"Session with ID {id} has {locks} locks; "
|
||||
|
||||
if state != State.OK:
|
||||
infotext += f"(warn/crit at {warn}/{crit})"
|
||||
else:
|
||||
infotext = "There are no sessions with a high number of locks"
|
||||
|
||||
yield Metric(name="MaximumLocksInSession", value=max_locks)
|
||||
yield Result(state=state, summary=infotext)
|
||||
|
||||
|
||||
def check_informix_activity(item, params, section):
|
||||
data = section.get(item)
|
||||
if not data:
|
||||
return
|
||||
|
||||
state = State.OK
|
||||
infotext = ""
|
||||
curr_log = data["curr_log"]
|
||||
|
||||
for session in data["sessions"]:
|
||||
id = session["id"]
|
||||
log_start = session["log_start"]
|
||||
|
||||
if log_start is None:
|
||||
continue
|
||||
|
||||
if log_start < curr_log:
|
||||
state = State.CRIT
|
||||
infotext += f"Session {id} doesn't have activity in current log; "
|
||||
|
||||
if state == State.OK:
|
||||
infotext = "There are no inactive sessions in current log"
|
||||
|
||||
yield Result(state=state, summary=infotext)
|
||||
|
||||
|
||||
def check_informix_long_transactions(item, params, section):
|
||||
data = section.get(item)
|
||||
if not data:
|
||||
return
|
||||
|
||||
state = State.OK
|
||||
infotext = ""
|
||||
|
||||
for session in data["sessions"]:
|
||||
id = session["id"]
|
||||
log_start = session["log_start"]
|
||||
log_end = session["log_end"]
|
||||
|
||||
if log_start is None or log_end is None:
|
||||
continue
|
||||
|
||||
if log_end - log_start > 2:
|
||||
state = State.CRIT
|
||||
infotext += f"Session {id} is using more than 3 logical logs; "
|
||||
|
||||
if state == State.OK:
|
||||
infotext = "There are no long-running transactions"
|
||||
|
||||
yield Result(state=state, summary=infotext)
|
||||
|
||||
|
||||
agent_section_informix_transactions = AgentSection(
|
||||
name = "informix_transactions",
|
||||
parse_function = parse_informix_transactions,
|
||||
)
|
||||
|
||||
check_plugin_informix_session_locks = CheckPlugin(
|
||||
name = "informix_session_locks",
|
||||
check_ruleset_name = "informix_session_locks",
|
||||
service_name = "Informix session locks %s",
|
||||
sections = ["informix_transactions"],
|
||||
discovery_function = discover_informix_transactions,
|
||||
check_function = check_informix_locks,
|
||||
check_default_parameters = {},
|
||||
)
|
||||
|
||||
check_plugin_informix_session_activity = CheckPlugin(
|
||||
name = "informix_session_activity",
|
||||
service_name = "Informix session activity %s",
|
||||
sections = ["informix_transactions"],
|
||||
discovery_function = discover_informix_transactions,
|
||||
check_function = check_informix_activity,
|
||||
check_default_parameters = {},
|
||||
)
|
||||
|
||||
check_plugin_informix_session_long_transactions = CheckPlugin(
|
||||
name = "informix_session_long_transactions",
|
||||
service_name = "Informix session long transactions %s",
|
||||
sections = ["informix_transactions"],
|
||||
discovery_function = discover_informix_transactions,
|
||||
check_function = check_informix_long_transactions,
|
||||
check_default_parameters = {},
|
||||
)
|
||||
@ -0,0 +1,46 @@
|
||||
# Copyright 2026 Spearhead Systems SRL
|
||||
|
||||
from cmk.rulesets.v1.form_specs import (
|
||||
Dictionary,
|
||||
DictElement,
|
||||
Integer,
|
||||
DefaultValue,
|
||||
LevelDirection,
|
||||
SimpleLevels,
|
||||
)
|
||||
from cmk.rulesets.v1.rule_specs import (
|
||||
CheckParameters,
|
||||
HostAndItemCondition,
|
||||
Topic,
|
||||
Title,
|
||||
Help,
|
||||
)
|
||||
|
||||
|
||||
def _valuespec_informix_session_locks():
|
||||
return Dictionary(
|
||||
elements = {
|
||||
"levels": DictElement(
|
||||
parameter_form = SimpleLevels(
|
||||
title = Title("Session locks"),
|
||||
help_text = Help(
|
||||
"You can set a limit to the number of locks for a "
|
||||
"session in Informix Database application"
|
||||
),
|
||||
level_direction = LevelDirection.UPPER,
|
||||
form_spec_template = Integer(title = Title("locks")),
|
||||
prefill_fixed_levels = DefaultValue(value=(40, 70))
|
||||
)
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
rule_spec_informix_session_locks = CheckParameters(
|
||||
title = Title("Informix Session Locks"),
|
||||
name = "informix_session_locks",
|
||||
topic = Topic.APPLICATIONS,
|
||||
parameter_form = _valuespec_informix_session_locks,
|
||||
condition = HostAndItemCondition(
|
||||
item_title = Title("DBMS"),
|
||||
),
|
||||
)
|
||||
@ -0,0 +1,184 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2019 Checkmk 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.4.0"
|
||||
|
||||
# Informix
|
||||
# Make ENV-VARs avail for subshells
|
||||
set -a
|
||||
|
||||
# .--helper--------------------------------------------------------------.
|
||||
# | _ _ |
|
||||
# | | |__ ___| |_ __ ___ _ __ |
|
||||
# | | '_ \ / _ \ | '_ \ / _ \ '__| |
|
||||
# | | | | | __/ | |_) | __/ | |
|
||||
# | |_| |_|\___|_| .__/ \___|_| |
|
||||
# | |_| |
|
||||
# '----------------------------------------------------------------------'
|
||||
|
||||
# BEGIN COMMON PLUGIN CODE
|
||||
|
||||
# check that no users other than root can change the file
|
||||
only_root_can_modify() {
|
||||
permissions=$1
|
||||
owner=$2
|
||||
group=$3
|
||||
|
||||
group_write_perm=$(echo "$permissions" | cut -c 6)
|
||||
other_write_perm=$(echo "$permissions" | cut -c 9)
|
||||
|
||||
if [ "$owner" != "root" ] || [ "$other_write_perm" != "-" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
[ "$group" = "root" ] || [ "$group_write_perm" = "-" ]
|
||||
}
|
||||
|
||||
get_binary_owner() {
|
||||
BINARY_PATH=$1
|
||||
stat -c '%U' "${BINARY_PATH}"
|
||||
}
|
||||
|
||||
get_binary_execution_mode() {
|
||||
BINARY_PATH=$1
|
||||
BINARY_USER=$2
|
||||
|
||||
# if the executable belongs to someone besides root, do not execute it as root
|
||||
if needs_user_switch_before_executing "$BINARY_PATH"; then
|
||||
echo "su ${BINARY_USER} -c"
|
||||
return
|
||||
fi
|
||||
echo "bash -c"
|
||||
}
|
||||
|
||||
needs_user_switch_before_executing() {
|
||||
BINARY_PATH=$1
|
||||
|
||||
[ "$(whoami)" = "root" ] && ! only_root_can_modify "$(stat -c '%A' "$BINARY_PATH")" "$(stat -c '%U' "$BINARY_PATH")" "$(stat -c '%G' "$BINARY_PATH")"
|
||||
}
|
||||
|
||||
# END COMMON PLUGIN CODE
|
||||
|
||||
set_env() {
|
||||
# set environment variables given in the form VARNAME1=value1;VARNAME2=value2;...
|
||||
while IFS=';' read -ra parts; do
|
||||
for part in "${parts[@]}"; do
|
||||
var_name="${part%%=*}"
|
||||
var_value="${part#*=}"
|
||||
export "$var_name"="$var_value"
|
||||
done
|
||||
done <<<"$1"
|
||||
}
|
||||
|
||||
|
||||
#.
|
||||
# .--sqls----------------------------------------------------------------.
|
||||
# | _ |
|
||||
# | ___ __ _| |___ |
|
||||
# | / __|/ _` | / __| |
|
||||
# | \__ \ (_| | \__ \ |
|
||||
# | |___/\__, |_|___/ |
|
||||
# | |_| |
|
||||
# '----------------------------------------------------------------------'
|
||||
|
||||
informix_transactions() {
|
||||
echo "<<<informix_transactions>>>"
|
||||
echo "[[[$INFORMIXSERVER/$SERVERNUM]]]"
|
||||
$EXECUTION_MODE "\"$INFORMIXDIR\"/bin/onstat -l" | grep C | tail -n 1
|
||||
$EXECUTION_MODE "\"$INFORMIXDIR\"/bin/onstat -x" | egrep -v 'IBM|maximum|Transactions|est.|userthread|logpos' | sed 's/:[^:]*$//'
|
||||
}
|
||||
|
||||
|
||||
#.
|
||||
# .--config--------------------------------------------------------------.
|
||||
# | __ _ |
|
||||
# | ___ ___ _ __ / _(_) __ _ |
|
||||
# | / __/ _ \| '_ \| |_| |/ _` | |
|
||||
# | | (_| (_) | | | | _| | (_| | |
|
||||
# | \___\___/|_| |_|_| |_|\__, | |
|
||||
# | |___/ |
|
||||
# '----------------------------------------------------------------------'
|
||||
|
||||
# Config opts:
|
||||
# - oninit-path; Default is empty, which means autodetection:
|
||||
# ONINIT_PATH=<path to oninit-binary>
|
||||
# - Excluding sections ("status sessions locks tabextents dbspaces logusage"):
|
||||
# EXCLUDES="SECTION SECTION ..."
|
||||
# EXCLUDES=ALL
|
||||
|
||||
# shellcheck source=agents/cfg_examples/informix.cfg
|
||||
. "$MK_CONFDIR/informix.cfg" 2>/dev/null
|
||||
|
||||
if [ -z "$ONINIT_PATH" ] || [ ! -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=$(readlink "/proc/$ONINIT_PID/exe")
|
||||
;;
|
||||
esac
|
||||
|
||||
# If not set in config or not found we end up here
|
||||
if [ -z "$ONINIT_PATH" ] || [ ! -f "$ONINIT_PATH" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
#.
|
||||
# .--main----------------------------------------------------------------.
|
||||
# | _ |
|
||||
# | _ __ ___ __ _(_)_ __ |
|
||||
# | | '_ ` _ \ / _` | | '_ \ |
|
||||
# | | | | | | | (_| | | | | | |
|
||||
# | |_| |_| |_|\__,_|_|_| |_| |
|
||||
# | |
|
||||
# '----------------------------------------------------------------------'
|
||||
|
||||
INFORMIXDIR=${ONINIT_PATH%/bin*}
|
||||
|
||||
if [ ! -f "$INFORMIXDIR/bin/onstat" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
EXECUTION_MODE="$(get_binary_execution_mode "$INFORMIXDIR/bin/onstat" "$(get_binary_owner "$INFORMIXDIR/bin/onstat")")"
|
||||
|
||||
for IDSENV in $(
|
||||
$EXECUTION_MODE "$INFORMIXDIR/bin/onstat -g dis" |
|
||||
grep -E '^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'
|
||||
|
||||
); do
|
||||
(
|
||||
set_env "$IDSENV"
|
||||
|
||||
# try to set them via 'onstat -g env' otherwise
|
||||
# DB HAS TO BE RUNNING
|
||||
if [ -z "$INFORMIXSQLHOSTS" ] || [ -z "$ONCONFIG" ]; then
|
||||
$EXECUTION_MODE "$INFORMIXDIR/bin/onstat -g env" | grep -E -e '^INFORMIXSQLHOSTS' \
|
||||
-e '^ONCONFIG' |
|
||||
sed -e 's/[ ][ ]*/=/'
|
||||
fi
|
||||
|
||||
informix_transactions
|
||||
)
|
||||
done
|
||||
Loading…
x
Reference in New Issue
Block a user