166 lines
4.8 KiB
PHP
166 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* Monitoring Library - PHP Version
|
|
* Copyright (C) 2026 Cédric Abonnel
|
|
* License: GNU Affero General Public License v3
|
|
*/
|
|
|
|
// --- Chemins et Constantes ---
|
|
$MONITORING_LIB_DIR = __DIR__;
|
|
$MONITORING_BASE_DIR = dirname($MONITORING_LIB_DIR);
|
|
$MONITORING_CONF_DIR = $MONITORING_BASE_DIR . '/conf';
|
|
|
|
// États globaux
|
|
$STATUS_OK = 0;
|
|
$STATUS_WARNING = 1;
|
|
$STATUS_ERROR = 2;
|
|
$STATUS_INTERNAL = 3;
|
|
|
|
$CURRENT_STATUS = $STATUS_OK;
|
|
|
|
// --- Chargement de la Config ---
|
|
$CONFIG = [
|
|
'LOG_FILE' => '/var/log/monitoring/events.jsonl',
|
|
'MONITORING_LOCK_DIR' => '/var/lock/monitoring',
|
|
'LOG_LEVEL' => 'INFO'
|
|
];
|
|
|
|
// 1. On charge la configuration GLOBALE (La vérité est ici)
|
|
$global_conf = $MONITORING_CONF_DIR . "/monitoring.local.conf.php";
|
|
if (file_exists($global_conf)) {
|
|
$CONFIG = array_replace_recursive($CONFIG, include $global_conf);
|
|
}
|
|
|
|
// 2. On charge ensuite la config spécifique au script (si besoin de surcharger)
|
|
// $specific_conf est défini par le script qui appelle la lib
|
|
if (isset($specific_conf) && file_exists($specific_conf)) {
|
|
$CONFIG = array_replace_recursive($CONFIG, include $specific_conf);
|
|
}
|
|
|
|
// Variables d'exécution
|
|
$SCRIPT_NAME = basename($_SERVER['SCRIPT_FILENAME'] ?? $argv[0]);
|
|
$SCRIPT_PATH = realpath($_SERVER['SCRIPT_FILENAME'] ?? $argv[0]);
|
|
|
|
// --- Fonctions de Log ---
|
|
|
|
/**
|
|
* Log un événement au format JSONL
|
|
*/
|
|
function log_event(string $level, string $event, string $message, array $extra_kv = []) {
|
|
global $CONFIG, $SCRIPT_NAME;
|
|
|
|
$ts = date('c'); // ISO-8601
|
|
|
|
// Détection Hostname
|
|
$host = getenv('HOSTNAME_FQDN') ?: (gethostname() ?: 'unknown');
|
|
|
|
$log_data = [
|
|
"ts" => $ts,
|
|
"host" => $host,
|
|
"app" => $SCRIPT_NAME,
|
|
"level" => $level,
|
|
"event" => $event,
|
|
"message" => $message
|
|
];
|
|
|
|
// Fusion des paires clé=valeur supplémentaires
|
|
foreach ($extra_kv as $kv) {
|
|
if (strpos($kv, '=') !== false) {
|
|
list($k, $v) = explode('=', $kv, 2);
|
|
$log_data[$k] = $v;
|
|
}
|
|
}
|
|
|
|
$json_line = json_encode($log_data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
|
|
$log_file = $CONFIG['LOG_FILE'];
|
|
ensure_parent_dir($log_file);
|
|
|
|
file_put_contents($log_file, $json_line . "\n", FILE_APPEND | LOCK_EX);
|
|
}
|
|
|
|
function set_status(int $new_status) {
|
|
global $CURRENT_STATUS;
|
|
if ($new_status > $CURRENT_STATUS) {
|
|
$CURRENT_STATUS = $new_status;
|
|
}
|
|
}
|
|
|
|
// Helpers de logs
|
|
function log_debug($e, $m, $x = []) { log_event("DEBUG", $e, $m, $x); }
|
|
function log_info($e, $m, $x = []) { log_event("INFO", $e, $m, $x); }
|
|
function log_notice($e, $m, $x = []) { log_event("NOTICE", $e, $m, $x); }
|
|
function log_warning($e, $m, $x = []) { log_event("WARNING", $e, $m, $x); set_status(1); }
|
|
function log_error($e, $m, $x = []) { log_event("ERROR", $e, $m, $x); set_status(2); }
|
|
function log_critical($e, $m, $x = []) { log_event("CRITICAL", $e, $m, $x); set_status(2); }
|
|
|
|
function fail_internal(string $msg) {
|
|
log_event("ERROR", "internal_error", $msg);
|
|
exit(3); // STATUS_INTERNAL
|
|
}
|
|
|
|
function exit_with_status() {
|
|
global $CURRENT_STATUS;
|
|
exit($CURRENT_STATUS);
|
|
}
|
|
|
|
// --- Utilitaires Système ---
|
|
|
|
/**
|
|
* Vérifie la présence de commandes système
|
|
*/
|
|
function require_cmd(...$cmds) {
|
|
foreach ($cmds as $cmd) {
|
|
$output = [];
|
|
$res = 0;
|
|
exec("command -v " . escapeshellarg($cmd), $output, $res);
|
|
if ($res !== 0) {
|
|
fail_internal("Commande requise absente: $cmd");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gestion du verrouillage (Lock)
|
|
*/
|
|
function lock_or_exit(?string $lock_name = null) {
|
|
global $CONFIG, $SCRIPT_NAME;
|
|
$name = $lock_name ?: $SCRIPT_NAME;
|
|
$lock_file = ($CONFIG['MONITORING_LOCK_DIR'] ?? '/var/lock/monitoring') . "/{$name}.lock";
|
|
|
|
ensure_parent_dir($lock_file);
|
|
$fp = fopen($lock_file, "w+");
|
|
|
|
if (!$fp || !flock($fp, LOCK_EX | LOCK_NB)) {
|
|
log_notice("already_running", "Une autre instance est déjà en cours", ["lock=$lock_file"]);
|
|
exit(0);
|
|
}
|
|
// On garde le descripteur ouvert pour maintenir le lock
|
|
return $fp;
|
|
}
|
|
|
|
/**
|
|
* Évalue un niveau selon des seuils
|
|
*/
|
|
function threshold_level($value, $warning, $critical) {
|
|
if ($value >= $critical) return 'CRITICAL';
|
|
if ($value >= $warning) return 'WARNING';
|
|
return 'INFO';
|
|
}
|
|
|
|
function ensure_parent_dir(string $file) {
|
|
$dir = dirname($file);
|
|
if (!is_dir($dir)) {
|
|
if (!mkdir($dir, 0755, true)) {
|
|
// Ici on ne peut pas appeler log_event si c'est le répertoire de log qui échoue
|
|
error_log("Impossible de créer le répertoire : $dir");
|
|
exit(3);
|
|
}
|
|
}
|
|
}
|
|
|
|
function safe_mv(string $src, string $dst) {
|
|
if (!rename($src, $dst)) {
|
|
fail_internal("Échec du déplacement de $src vers $dst");
|
|
}
|
|
} |