# log-alarm
**Repository Path**: lvjinlin/log-alarm
## Basic Information
- **Project Name**: log-alarm
- **Description**: 接口日志收集和报警
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2025-08-06
- **Last Updated**: 2025-08-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 接口日志收集和报警SDK项目
接口日志收集和报警SDK的主要功能是集成到项目中进行接口日志收集、接口异常钉钉报警、接口超时钉钉报警。
主要实现方案是:借助注解处理器在项目编译期生成aop类,aop类中对controller层接口方法进行环绕通知以收集接口信息,并根据收集到的接口信息进行相应的日志输出和报警处理。
### 使用方法
#### 1、引用本地maven仓库log-alarm依赖方式
①将项目拉取到本地
②依次执行以下maven命令对项目进行打包并添加到本地maven仓库
```bash
mvn clean
mvn package
mvn install
```
③从maven本次仓库的com.dapeng目录下复制`log-alarm-xxx-xxxx.jar`到springboot项目resources\lib目录下
④引入log-alarm依赖
```xml
com.dapeng
log-alarm
0.0.1-SNAPSHOT
system
${project.basedir}/src/main/resources/lib/log-alarm-xxx-xxxx.jar
```
#### 2、直接引用log-alarm依赖方式
(还未推送至远程仓库)
#### 3、引入其它必要依赖
```xml
org.springframework.boot
spring-boot-starter-aop
com.alibaba
fastjson
1.2.61
org.apache.httpcomponents
httpclient
4.5.13
```
#### 4、主要注解及其使用
**(1)@EnableLogAndAlarm**
该注解用于启用接口日志收集和报警功能,是使用接口日志收集和报警功能的前提。
该注解修饰于类或者接口,但是只能使用1次,否则将会编译不通过,建议修饰于启动类。
该注解只有一个必填属性 pointcut 用于定义切点。
代码编译后会在该注解所修饰的类的同目录下生成LogAndAlarmAspect.class文件,也就是aop类编译后的文件。
**(2)@ExcludeAlarm**
该注解用于排除异常报警,即被此注解修饰的异常可以从接口异常报警机制中排除。
该注解只有在`@EnableLogAndAlarm`被使用后才生效,且只应当注解于异常类。
需要注意的是此注解可以被继承,即如果你在某异常类上使用了该注解,那么继承于该类的异常将都会被过滤。
**(3)@OperationLog**
该注解用于记录接口操作日志,只有在`@EnableLogAndAlarm`被使用后才生效,且只应当注解于controller层接口方法
当接口方法使用该注解修饰之后会将接口请求情况的简要信息以json格式记录在日志中
#### 5、在application.yml文件配置alarm
```yml
alarm:
# 运行环境名,在报警信息的报文中会体现
env-name: SDK测试环境
# 是否启用接口日志,默认启用
enable-log: true
# 是否启用接口异常报警,默认启用
open-error-alarm: true
# 全局钉钉机器人地址(如设置则会默认覆盖异常报警、超时报警中的机器人地址配置项)
webhook: https://oapi.dingtalk.com/robot/send?access_token=****
# 全局机器人密匙(如设置则会默认覆盖异常报警、超时报警中的机器人密匙配置项)
secret: ******
# 自定义异常报文、超时报文模板类的全类名,如不配置默认使用默认消息模板
template-class-name: com.dapeng.cloud.service.****.****
# 接口异常报警报文信息配置
error-message:
# 报警钉钉机器人地址(如启用报警则必填)
webhook: https://oapi.dingtalk.com/robot/send?access_token=****
# 报警钉钉机器人验签码(如启用报警则必填)
secret: ******
# 报文头部指示图片
image: https://****.com/***.png
# 报文标题(如启用报警则必填)
title: 接口异常报警测试
# 是否@群内所有人,默认为否
at-all: false
# 需要@通知的群内人的手机号(注册钉钉手机号),如@所有人则不必填
at-mobiles: ******,*****
# 是否开启接口超时报警,默认开启
open-overtime-alarm: true
# 接口超时时间(单位:ms),默认为2000ms
overtime: 1000
# 接口超时报警报文信息配置
overtime-message:
# 报警钉钉机器人地址(如启用报警则必填)
webhook: https://oapi.dingtalk.com/robot/send?access_token=******
# 报警钉钉机器人验签码(如启用报警则必填)
secret: ******
# 报文头部指示图片
image: https://*****.com/*****.png
# 报文标题(如启用报警则必填)
title: 接口超时报警测试
# 是否@群内所有人,默认为否
at-all: false
# 需要@通知的群内人的手机号(注册钉钉手机号),如@所有人则不必填
at-mobiles: ******,*****
```
#### 6、怎样自定义报文模板
(1)创建类并实现`com.dapeng.application.DingTalkTemplate`接口类
(2)重写`errorTalk()`方法和`overtimeTalk()`方法,返回的`DingTalkModel`即为自定义的消息模板
(3)在yml中配置`alarm.template-class-name`其值为`DingTalkTemplate`实现类的全类名
#### 7、一些问题
(1)如果项目中使用feign对接其它项目,当被调用者抛出一个异常且被解析为`HystrixBadRequestException`,那么你无法在这个异常类上加上`@ExcludeAlarm`注解(因为你无法修改hystrix源码),但是又想要过滤这些异常,或者是这些异常的一部分,那该怎么办呢?
解决方案如下:
首先,自定义一个异常类并用`@ExcludeAlarm`修饰
(可以继承自`RuntimeException`也可以继承自`HystrixBadRequestException`),例如:
```java
package com.dapeng.cloud.service.cultivation.infrastructure.exceptions;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import com.dapeng.annotation.ExcludeAlarm;
/**
* @author guoqing_li
* @create 2021-05-08 16:30:15
* @description 自定义异常
**/
@ExcludeAlarm
public class MyHystrixBadRequestException extends HystrixBadRequestException {
public MyHystrixBadRequestException(String message) {
super(message);
}
public MyHystrixBadRequestException(String message, Throwable cause) {
super(message, cause);
}
}
```
然后,继承`ErrorDecoder.Default`类重写其decode方法
```java
package com.dapeng.cloud.service.cultivation.client;
import com.dapeng.cloud.service.cultivation.infrastructure.exceptions.MyHystrixBadRequestException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
/**
* 返回4xx的状态码,解析成自己想要的异常。这些异常不应该走断路器。参考:大鹏微服务接口设计规范
*/
@Slf4j
public class BadRequestErrorDecoder extends ErrorDecoder.Default {
@Override
public Exception decode(String methodKey, Response response) {
if (400 <= response.status() && response.status() < 500) {
String message = String.format("status %s reading %s", response.status(), methodKey);
try {
if (response.body() != null) {
String body = Util.toString(response.body().asReader(StandardCharsets.UTF_8));
ObjectMapper objectMapper = new ObjectMapper();
message = objectMapper
.writeValueAsString(new HystrixBadResponse(message, body, response.status()));
}
} catch (IOException var4) {
log.error(var4.getMessage(), var4);
}
// 这里可以写一些自定义的过滤规则,鉴于不同服务间的情况不同,这里不做实现
// 这里将这些异常抛出为你自定义的 MyHystrixBadRequestException ,这样就会被报警忽略
throw new MyHystrixBadRequestException(message);
} else {
return super.decode(methodKey, response);
}
}
}
```
总而言之,对于那些非自定义的异常如想要过滤报警,那么你可以想方设法将其转换为你自定义的异常,或者你可以考虑是否需要关闭接口异常报警功能。
(2)如果想要自己发送钉钉消息
使用如下方式即可发送自己的钉钉消息
```java
String webhook = "****";
String secret = "****";
DingTalkModel model = new DingTalkModel();
DingTalk.sendDingTalk(webhook,secret, model);
```
(3)异常信息规范模型
`ExceptionModel`这个实体类主要是用来规范化的收集某些不想要通过`ApiLogModel`收集的信息,可能还需要进行适配调整