异常告警模块与错误处理模块集成,当异常发生时自动触发告警通知。模块提供统一的告警信息模型 AlarmInfo、告警级别 AlarmLevel 以及可扩展的告警处理器接口 ErrorAlarmHandler,支持注册多个处理器同时发送钉钉、企微、邮件、日志等多种告警。
核心接口
ErrorAlarmHandler
实现 com.luamas.thinkbridge.common.alarm.ErrorAlarmHandler 接口,自定义告警处理逻辑:
public interface ErrorAlarmHandler {
/**
* 处理告警信息
*
* @param alarmInfo 告警信息
* @return 处理成功返回 true,处理失败返回 false
*/
boolean handle(AlarmInfo<?> alarmInfo);
}
自定义处理器只需实现该接口并注册为 Spring Bean,框架会自动收集所有 ErrorAlarmHandler 并在异常发生时依次调用:
@Component
public class MyAlarmHandler implements ErrorAlarmHandler {
@Override
public boolean handle(AlarmInfo<?> alarmInfo) {
Throwable exception = alarmInfo.getException();
Object response = alarmInfo.getObj();
AlarmLevel level = alarmInfo.getLevel();
String type = alarmInfo.getType();
// 自定义告警逻辑,如发送钉钉/企微/邮件通知
return true;
}
}
可以注册多个 ErrorAlarmHandler,如同时发送钉钉和邮件告警。返回 true 表示告警处理成功,返回 false 表示处理失败,框架会记录警告日志。
|
AlarmInfo
com.luamas.thinkbridge.common.alarm.AlarmInfo<T> 是告警信息模型,泛型 T 表示关联的业务对象类型(通常为错误响应体)。
字段说明
字段 |
类型 |
说明 |
exception |
|
触发告警的异常对象,可能为 null |
obj |
|
关联的业务对象,通常为错误响应体 |
level |
|
告警级别(WARN / ERROR / FATAL) |
type |
|
告警类型,见下方类型常量 |
extend |
|
扩展数据,默认初始化为空 |
类型常量
AlarmInfo 内置以下告警类型常量:
常量 |
值 |
说明 |
|
|
客户端 HTTP 请求告警(如 Feign 调用) |
|
|
访问 HTTP 请求告警(服务端入口) |
|
|
消息消费者告警 |
|
|
消息生产者告警 |
扩展数据
extend 字段用于存储自定义业务数据,默认已初始化为空 HashMap,可直接使用:
AlarmInfo<?> alarmInfo = new AlarmInfo<>(exception, response, AlarmLevel.ERROR, AlarmInfo.TYPE_ACCESS_HTTP);
// 逐个添加扩展字段
alarmInfo.addExtend("userId", "1001");
alarmInfo.addExtend("tenantId", "thinkbridge");
// 一次性替换整个扩展字段(传入 null 会自动初始化为空 Map)
Map<String, Object> extend = new HashMap<>();
extend.put("orderId", "ORD-2026-001");
alarmInfo.setExtend(extend);
AlarmLevel 枚举
com.luamas.thinkbridge.common.alarm.AlarmLevel
枚举值 |
数值 |
说明 |
WARN |
0 |
警告,已知业务异常触发 |
ERROR |
1 |
普通错误,未知异常触发 |
FATAL |
2 |
致命错误 |
ErrorAlarmManager
com.luamas.thinkbridge.common.alarm.ErrorAlarmManager 是告警分发管理器,负责将告警信息分发给所有注册的处理器。错误处理模块内部直接遍历 ErrorAlarmHandler 列表进行分发,如需在非异常场景下手动触发告警,可使用 ErrorAlarmManager:
@Component
@RequiredArgsConstructor
public class MyService {
private final List<ErrorAlarmHandler> errorAlarmHandlers;
public void doSomething() {
try {
// 业务逻辑
} catch (Exception e) {
// 手动构建告警信息并触发告警
ErrorAlarmManager manager = new ErrorAlarmManager(errorAlarmHandlers);
AlarmInfo<?> alarmInfo = new AlarmInfo<>(e, null, AlarmLevel.ERROR, AlarmInfo.TYPE_CLIENT_HTTP);
manager.handle(alarmInfo);
throw e;
}
}
}
ErrorAlarmManager.handle() 会依次调用所有处理器,单个处理器抛出异常不会影响其他处理器的执行,处理器返回 false 会记录警告日志。
|
告警触发机制
告警由错误处理模块的 ErrorExceptionManager 自动触发,流程如下:
-
错误处理模块在处理异常时,自动创建
AlarmInfo -
如果异常被某个
ErrorExceptionHandler成功处理(匹配到对应处理器),告警级别为WARN -
如果异常未被任何
ErrorExceptionHandler处理(走默认处理),告警级别为ERROR -
如果异常实现了
ThinkBridgeException接口,且isAlarmEnabled()返回false,则跳过告警 -
遍历所有
ErrorAlarmHandler,调用handle()方法 -
如果
handle()返回false,记录警告日志
处理器示例
打印告警
最简单的处理器,将告警信息序列化后打印:
@Component
@Slf4j
public class PrintErrorAlarmHandler implements ErrorAlarmHandler {
private final ObjectMapper objectMapper = JsonMapper.builder().build();
@Override
public boolean handle(AlarmInfo<?> alarmInfo) {
log.info("触发告警: {}", objectMapper.writeValueAsString(alarmInfo));
return true;
}
}
日志收集告警
将告警信息通过日志系统收集(可配合 logback 收集到 Kafka/RabbitMQ):
@Component
@Slf4j
@RequiredArgsConstructor
public class LogBackErrorAlarmHandler implements ErrorAlarmHandler {
private final ThinkBridgeLogProperties properties;
private final ObjectMapper objectMapper = JsonMapper.builder().build();
@Override
public boolean handle(AlarmInfo<?> alarmInfo) {
Map<String, Object> map = new HashMap<>(alarmInfo.getExtend());
map.put("obj", alarmInfo.getObj());
map.put("level", alarmInfo.getLevel());
map.put("type", alarmInfo.getType());
map.put("traceId", MDC.get(properties.getTraceIdTag()));
log.error(objectMapper.writeValueAsString(map));
return true;
}
}
邮件告警
根据告警级别发送邮件通知,ERROR 级别才发送:
@Component
@Slf4j
@RequiredArgsConstructor
public class EmailAlarmHandler implements ErrorAlarmHandler {
private final EmailService emailService;
private final ApplicationContext applicationContext;
@Override
public boolean handle(AlarmInfo<?> alarmInfo) {
if (alarmInfo == null || alarmInfo.getLevel() != AlarmLevel.ERROR) {
return true;
}
String subject = "[" + alarmInfo.getLevel() + "][" + alarmInfo.getType() + "]"
+ applicationContext.getId();
String content = buildContent(alarmInfo);
try {
emailService.sendHtmlEmail(new String[]{"admin@example.com"}, null, subject, content);
} catch (Exception e) {
log.warn("邮件告警发送失败", e);
return false;
}
return true;
}
private String buildContent(AlarmInfo<?> alarmInfo) {
// 构建邮件内容
return "<h3>告警信息</h3>" + alarmInfo.getException().getMessage();
}
}
完整示例可参考 sample/integration/integration-demo 模块下的 alarm 包,通过 alarm profile 激活。
|