fix: уведомления сервисов и исправление порогов
- Уведомления сервисов: разные цвета и тексты для остановки (🛑) и запуска (✅) - Фикс порядка действий: SELECT статуса ДО UPDATE для корректного отслеживания изменений - Фильтр алертов: только для сервисов в списке мониторинга - NotificationService: разделение на sendThresholdNotification/sendRecoveryNotification/sendServiceNotification - Исправление сохранения порогов (приведение типов для duration/warning/critical) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
c6e400ad32
commit
d35ce3a022
|
|
@ -100,6 +100,12 @@ class MetricsController extends Model
|
|||
continue;
|
||||
}
|
||||
|
||||
// Сначала читаем старый статус (ДО обновления)
|
||||
$stmtOld = $this->pdo->prepare("SELECT status FROM service_status WHERE server_id = :server_id AND service_name = :service_name");
|
||||
$stmtOld->execute([':server_id' => $serverId, ':service_name' => $serviceName]);
|
||||
$oldStatusRow = $stmtOld->fetch();
|
||||
$oldStatus = $oldStatusRow ? $oldStatusRow['status'] : null;
|
||||
|
||||
// Обновляем статус сервиса (INSERT OR UPDATE)
|
||||
$stmt = $this->pdo->prepare("
|
||||
INSERT INTO service_status (server_id, service_name, status, load_state, active_state, sub_state, updated_at)
|
||||
|
|
@ -121,9 +127,19 @@ class MetricsController extends Model
|
|||
':sub_state' => $subState
|
||||
]);
|
||||
|
||||
// Если сервис остановлен - создаем алерт
|
||||
if ($serviceStatus === 'stopped') {
|
||||
$this->createServiceAlert($serverId, $serviceName, $serviceStatus, $serverName);
|
||||
// Если статус изменился И сервис в мониторинге - шлем алерт
|
||||
if ($oldStatus !== null && $oldStatus !== $serviceStatus) {
|
||||
$stmtMon = $this->pdo->prepare("SELECT monitor_services FROM agent_configs WHERE server_id = :server_id");
|
||||
$stmtMon->execute([':server_id' => $serverId]);
|
||||
$monConfig = $stmtMon->fetch();
|
||||
$monitoredServices = [];
|
||||
if ($monConfig && !empty($monConfig['monitor_services'])) {
|
||||
$monitoredServices = json_decode($monConfig['monitor_services'], true) ?? [];
|
||||
}
|
||||
if (in_array($serviceName, $monitoredServices)) {
|
||||
$this->notificationService->sendServiceNotification($serverName, $serviceName, $serviceStatus);
|
||||
$this->createServiceAlert($serverId, $serviceName, $serviceStatus, $serverName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +244,7 @@ class MetricsController extends Model
|
|||
':severity' => $severity
|
||||
]);
|
||||
|
||||
$this->notificationService->sendAlertNotification(
|
||||
$this->notificationService->sendThresholdNotification(
|
||||
$serverName,
|
||||
$metricName,
|
||||
$value,
|
||||
|
|
@ -270,12 +286,10 @@ class MetricsController extends Model
|
|||
");
|
||||
$stmt->execute([':id' => $existingAlert['id']]);
|
||||
|
||||
$this->notificationService->sendAlertNotification(
|
||||
$this->notificationService->sendRecoveryNotification(
|
||||
$serverName,
|
||||
$metricName,
|
||||
$value,
|
||||
'resolved',
|
||||
'Порог более не превышен'
|
||||
$value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,14 +300,14 @@ class ServerDetailController extends Model
|
|||
foreach ($metricTypes as $metricType) {
|
||||
$warning = $params[$metricType['name'] . '_warning'] ?? '';
|
||||
$critical = $params[$metricType['name'] . '_critical'] ?? '';
|
||||
$duration = $params[$metricType['name'] . '_duration'] ?? 0;
|
||||
$duration = (int)($params[$metricType['name'] . '_duration'] ?? 0);
|
||||
|
||||
if ($warning !== '' && $critical !== '') {
|
||||
$insertStmt->execute([
|
||||
':server_id' => $id,
|
||||
':metric_name_id' => $metricType['id'],
|
||||
':warning_threshold' => $warning,
|
||||
':critical_threshold' => $critical,
|
||||
':warning_threshold' => (float)$warning,
|
||||
':critical_threshold' => (float)$critical,
|
||||
':duration' => $duration
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,31 +24,77 @@ class NotificationService
|
|||
}
|
||||
|
||||
/**
|
||||
* Отправить уведомление о алерте
|
||||
* Отправить уведомление о превышении порога
|
||||
*/
|
||||
public function sendAlertNotification($serverName, $metricName, $value, $severity, $threshold)
|
||||
public function sendThresholdNotification($serverName, $metricName, $value, $severity, $threshold)
|
||||
{
|
||||
if ($severity === 'resolved') {
|
||||
$severityText = 'ВОССТАНОВЛЕНИЕ';
|
||||
$emoji = '✅';
|
||||
$subject = "{$emoji} {$severityText}: {$metricName} в норме";
|
||||
$message = "Сервер: {$serverName}\n";
|
||||
$message .= "Метрика: {$metricName}\n";
|
||||
$message .= "Текущее значение: {$value}\n";
|
||||
$message .= "Статус: Порог более не превышен\n";
|
||||
$message .= "Время: " . date('d.m.Y H:i:s');
|
||||
if ($severity === 'warning') {
|
||||
$severityText = 'ПРЕДУПРЕЖДЕНИЕ';
|
||||
$emoji = '⚠️';
|
||||
} else {
|
||||
$severityText = $severity === 'critical' ? 'КРИТИЧЕСКИЙ' : 'ПРЕДУПРЕЖДЕНИЕ';
|
||||
$severityText = 'КРИТИЧЕСКИЙ';
|
||||
$emoji = '🚨';
|
||||
$subject = "{$emoji} {$severityText}: Превышение порога {$metricName}";
|
||||
$message = "Сервер: {$serverName}\n";
|
||||
$message .= "Метрика: {$metricName}\n";
|
||||
$message .= "Значение: {$value}\n";
|
||||
$message .= "Порог: {$threshold}\n";
|
||||
$message .= "Время: " . date('d.m.Y H:i:s') . "\n";
|
||||
$message .= "Серьёзность: {$severityText}";
|
||||
}
|
||||
|
||||
$subject = "{$emoji} {$severityText}: {$metricName}";
|
||||
$message = "🖥 Сервер: {$serverName}\n";
|
||||
$message .= "📊 Метрика: {$metricName}\n";
|
||||
$message .= "📈 Значение: {$value}\n";
|
||||
$message .= "📏 Порог: {$threshold}\n";
|
||||
$message .= "🕒 Время: " . date('d.m.Y H:i:s') . "\n";
|
||||
$message .= "🏷 Серьёзность: {$severityText}";
|
||||
|
||||
$this->sendNotification($subject, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправить уведомление о восстановлении (порог в норме)
|
||||
*/
|
||||
public function sendRecoveryNotification($serverName, $metricName, $value)
|
||||
{
|
||||
$subject = "✅ Восстановление: {$metricName} в норме";
|
||||
$message = "🖥 Сервер: {$serverName}\n";
|
||||
$message .= "📊 Метрика: {$metricName}\n";
|
||||
$message .= "📈 Текущее значение: {$value}\n";
|
||||
$message .= "🟢 Статус: Порог более не превышен\n";
|
||||
$message .= "🕒 Время: " . date('d.m.Y H:i:s');
|
||||
|
||||
$this->sendNotification($subject, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправить уведомление о сервисе (остановка/запуск)
|
||||
*/
|
||||
public function sendServiceNotification($serverName, $serviceName, $action)
|
||||
{
|
||||
// $action: 'stopped' или 'running'
|
||||
if ($action === 'running') {
|
||||
$emoji = '✅';
|
||||
$actionText = 'Запуск сервиса';
|
||||
$descText = "Сервис {$serviceName} запущен";
|
||||
$severityText = 'ВОССТАНОВЛЕНИЕ';
|
||||
} else {
|
||||
$emoji = '🛑';
|
||||
$actionText = 'Остановка сервиса';
|
||||
$descText = "Сервис {$serviceName} остановлен";
|
||||
$severityText = 'ОСТАНОВЛЕН';
|
||||
}
|
||||
|
||||
$subject = "{$emoji} {$actionText}: {$serviceName}";
|
||||
$message = "🖥 Сервер: {$serverName}\n";
|
||||
$message .= "⚙️ Сервис: {$serviceName}\n";
|
||||
$message .= "📝 Действие: {$descText}\n";
|
||||
$message .= "🏷 Статус: {$severityText}\n";
|
||||
$message .= "🕒 Время: " . date('d.m.Y H:i:s');
|
||||
|
||||
$this->sendNotification($subject, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Внутренний метод отправки (Email + Telegram)
|
||||
*/
|
||||
private function sendNotification($subject, $message)
|
||||
{
|
||||
// Отправка Email
|
||||
if (!empty($this->settings['email_enabled']) && !empty($this->settings['smtp_host'])) {
|
||||
$this->sendEmail($subject, $message);
|
||||
|
|
@ -60,6 +106,19 @@ class NotificationService
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправить уведомление о алерте (для обратной совместимости)
|
||||
* @deprecated Используйте sendThresholdNotification или sendServiceNotification
|
||||
*/
|
||||
public function sendAlertNotification($serverName, $metricName, $value, $severity, $threshold)
|
||||
{
|
||||
if ($severity === 'resolved') {
|
||||
$this->sendRecoveryNotification($serverName, $metricName, $value);
|
||||
} else {
|
||||
$this->sendThresholdNotification($serverName, $metricName, $value, $severity, $threshold);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправить тестовое уведомление
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue