Files
ai-security-xdr/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/AlarmHealthCheckService.java
T
2026-05-06 17:54:59 +08:00

168 lines
6.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.common.service;
import com.common.entity.WecomNotification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 告警健康检查服务
* 巡检告警表和告警日志表是否有数据
*/
@Service
public class AlarmHealthCheckService {
private static final Logger logger = LoggerFactory.getLogger(AlarmHealthCheckService.class);
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private WecomNotificationService wecomNotificationService;
@Value("${alarm.health-check.alarm-hours:2}")
private int alarmHoursThreshold;
@Value("${alarm.health-check.alarm-visit-hours:4}")
private int alarmVisitHoursThreshold;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
/**
* 执行告警健康检查
* @return 是否有异常
*/
public boolean performHealthCheck() {
boolean hasAlarm = false;
// 1. 检查告警表 alarm
boolean alarmTableNormal = checkAlarmTable();
if (!alarmTableNormal) {
hasAlarm = true;
generateAlarmNotification("alarm", alarmHoursThreshold);
}
// 2. 检查告警日志表 alarm_visit
boolean alarmVisitTableNormal = checkAlarmVisitTable();
if (!alarmVisitTableNormal) {
hasAlarm = true;
generateAlarmNotification("alarm_visit", alarmVisitHoursThreshold);
}
return hasAlarm;
}
/**
* 检查告警表 alarm_yyyyMMdd 最近是否无数据
* @return true=正常有数据, false=异常无数据
*/
public boolean checkAlarmTable() {
String partitionDate = LocalDateTime.now().format(DATE_FORMATTER);
String tableName = "alarm_" + partitionDate;
String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE created_at >= NOW() - INTERVAL '" + alarmHoursThreshold + " hours'";
try {
Long count = jdbcTemplate.queryForObject(sql, Long.class);
boolean hasData = count != null && count > 0;
logger.info("告警表 {} 健康检查: {}小时内数据量={}, 状态={}",
tableName, alarmHoursThreshold, count, hasData ? "正常" : "异常");
return hasData;
} catch (Exception e) {
logger.error("检查告警表 {} 失败: {}", tableName, e.getMessage());
// 表不存在或查询失败,认为异常
return false;
}
}
/**
* 检查告警日志表 alarm_visit_yyyyMMdd 最近是否无数据
* @return true=正常有数据, false=异常无数据
*/
public boolean checkAlarmVisitTable() {
String partitionDate = LocalDateTime.now().format(DATE_FORMATTER);
String tableName = "alarm_visit_" + partitionDate;
String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE created_at >= NOW() - INTERVAL '" + alarmVisitHoursThreshold + " hours'";
try {
Long count = jdbcTemplate.queryForObject(sql, Long.class);
boolean hasData = count != null && count > 0;
logger.info("告警日志表 {} 健康检查: {}小时内数据量={}, 状态={}",
tableName, alarmVisitHoursThreshold, count, hasData ? "正常" : "异常");
return hasData;
} catch (Exception e) {
logger.error("检查告警日志表 {} 失败: {}", tableName, e.getMessage());
// 表不存在或查询失败,认为异常
return false;
}
}
/**
* 生成告警通知并插入微信通知表
*
* @param tableType 表类型(alarm 或 alarm_visit
* @param hoursThreshold 小时阈值
*/
public void generateAlarmNotification(String tableType, int hoursThreshold) {
String tableName = tableType + "_" + LocalDateTime.now().format(DATE_FORMATTER);
String content = String.format(
"【数据巡检告警】%n" +
"表名: %s%n" +
"告警时间: %s%n" +
"告警描述: 最近%d小时内无新数据%n" +
"建议: 请检查数据采集服务是否正常运行%n" +
"状态: 需要人工介入检查",
tableName,
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
hoursThreshold
);
WecomNotification notification = wecomNotificationService.sendAlert(
"数据巡检告警-" + tableName,
"alarm_health_check",
"3", // 高危
content,
null
);
logger.warn("生成告警通知: 表={}, 通知ID={}", tableName, notification.getWecomNotificationId());
}
/**
* 微信通知告警数据插入函数方法
* 提供给其他模块在运行有异常的情况下调用
*
* @param alertName 告警名称
* @param alertType 告警类型
* @param alertLevel 告警等级(1:低, 2:中, 3:高, 4:紧急)
* @param alertContent 告警内容
* @return 通知实体
*/
public WecomNotification insertWecomAlert(String alertName, String alertType,
String alertLevel, String alertContent) {
return wecomNotificationService.sendAlert(alertName, alertType, alertLevel, alertContent, null);
}
/**
* 快速插入告警通知(简化版)
*
* @param alertType 告警类型
* @param alertContent 告警内容
* @return 通知实体
*/
public WecomNotification insertWecomAlert(String alertType, String alertContent) {
return wecomNotificationService.sendAlert(alertType, alertContent);
}
}