168 lines
6.0 KiB
Java
168 lines
6.0 KiB
Java
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|