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); } }