# 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`收集的信息,可能还需要进行适配调整