Files
scripts-bash/servers/linux/monitoring/lib/monitoring-lib.sh
2026-03-16 13:42:53 +01:00

141 lines
3.8 KiB
Bash

#!/bin/bash
# Copyright (C) 2026 Cédric Abonnel
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
MONITORING_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MONITORING_BASE_DIR="$(cd "${MONITORING_LIB_DIR}/.." && pwd)"
MONITORING_CONF_DIR="${MONITORING_BASE_DIR}/conf"
# Chargement config globale
if [ -f "${MONITORING_CONF_DIR}/monitoring.conf" ]; then
# shellcheck source=/dev/null
. "${MONITORING_CONF_DIR}/monitoring.conf"
fi
SCRIPT_NAME="${SCRIPT_NAME:-$(basename "$0")}"
SCRIPT_PATH="${SCRIPT_PATH:-$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")}"
STATUS_OK=0
STATUS_WARNING=1
STATUS_ERROR=2
STATUS_INTERNAL=3
CURRENT_STATUS=$STATUS_OK
LOG_LEVEL=${LOG_LEVEL:-INFO}
json_escape() {
local s="${1:-}"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//$'\n'/\\n}"
s="${s//$'\r'/\\r}"
s="${s//$'\t'/\\t}"
printf '%s' "$s"
}
log_event() {
local level="$1"
local event="$2"
local message="$3"
shift 3
local ts extra key value kv
ts="$(date --iso-8601=seconds)"
extra=""
for kv in "$@"; do
key="${kv%%=*}"
value="${kv#*=}"
extra="${extra},\"$(json_escape "$key")\":\"$(json_escape "$value")\""
done
printf '{"ts":"%s","host":"%s","app":"%s","level":"%s","event":"%s","message":"%s"%s}\n' \
"$(json_escape "$ts")" \
"$(json_escape "${HOSTNAME_FQDN:-unknown}")" \
"$(json_escape "$SCRIPT_NAME")" \
"$(json_escape "$level")" \
"$(json_escape "$event")" \
"$(json_escape "$message")" \
"$extra" >> "${LOG_FILE:-/var/log/monitoring/events.jsonl}"
}
set_status() {
local new_status="$1"
if [ "$new_status" -gt "$CURRENT_STATUS" ]; then
CURRENT_STATUS="$new_status"
fi
}
log_debug() { log_event "DEBUG" "$@"; }
log_info() { log_event "INFO" "$@"; }
log_notice() { log_event "NOTICE" "$@"; }
log_warning() { log_event "WARNING" "$@"; set_status "$STATUS_WARNING"; }
log_error() { log_event "ERROR" "$@"; set_status "$STATUS_ERROR"; }
log_critical() { log_event "CRITICAL" "$@"; set_status "$STATUS_ERROR"; }
fail_internal() {
log_event "ERROR" "internal_error" "$1"
exit "$STATUS_INTERNAL"
}
exit_with_status() {
exit "$CURRENT_STATUS"
}
require_cmd() {
local cmd
for cmd in "$@"; do
command -v "$cmd" >/dev/null 2>&1 || fail_internal "Commande requise absente: $cmd"
done
}
load_conf_if_exists() {
local conf="$1"
[ -f "$conf" ] && . "$conf"
}
lock_or_exit() {
local lock_name="${1:-$SCRIPT_NAME}"
local lock_file="${MONITORING_LOCK_DIR:-/var/lock/monitoring}/${lock_name}.lock"
exec 9>"$lock_file" || fail_internal "Impossible d'ouvrir le lock $lock_file"
flock -n 9 || {
log_notice "already_running" "Une autre instance est déjà en cours" "lock=$lock_file"
exit 0
}
}
threshold_level() {
local value="$1"
local warning="$2"
local critical="$3"
if [ "$value" -ge "$critical" ]; then
printf 'CRITICAL'
elif [ "$value" -ge "$warning" ]; then
printf 'WARNING'
else
printf 'INFO'
fi
}
safe_mv() {
local src="$1"
local dst="$2"
mv -f "$src" "$dst" || fail_internal "Échec du déplacement de $src vers $dst"
}
ensure_parent_dir() {
local file="$1"
mkdir -p "$(dirname "$file")" || fail_internal "Impossible de créer le répertoire parent de $file"
}