介绍
- 统一logback日志输出格式,简化日志配置
- 统一行为日志记录方式
- 对接sentry (sentry是日志记录和查询平台)
依赖库
名称 | 描述 |
---|---|
sentry-spring-boot-starter | |
spring-boot-starter-aop | |
sentry-logback | |
janino | |
tlog | |
commons-lang | |
commons-beanutils | |
fastjson | |
commons-lang3 | |
zebra-common-util | |
tlog-web-spring-boot-starter |
快速开始
引入
xml
<dependency>
<groupId>io.github.zhanghongbin</groupId>
<artifactId>zebra-spring-boot-starter-logging</artifactId>
</dependency>
统一日志输出
采用logback实现,此配置已集成在此功能模块中,具体日志配置如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.path" value="./logs"/>
<!-- 环境标识 -->
<springProperty name="spring.profiles.active" source="spring.profiles.active"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,,,, -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<appender name="info"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<OnMatch>DENY</OnMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
<pattern>${log.pattern}</pattern>
</encoder>
<!--当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/info/info.%d.log</fileNamePattern>
<!--最多保留day天log -->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
<appender name="error"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
<pattern>${log.pattern}</pattern>
</encoder>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 路径 -->
<fileNamePattern>${log.path}/error/error.%d.log</fileNamePattern>
<!--最多保留day天log -->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
<!-- 也可以指定多个环境用,分割如: test,fix -->
<springProfile name="!prod">
<root level="INFO">
<appender-ref ref="stdout"/>
<appender-ref ref="info"/>
<appender-ref ref="error"/>
</root>
</springProfile>
<springProfile name="prod">
<root level="ERROR">
<appender-ref ref="error"/>
</root>
</springProfile>
</configuration>
行为日志
提供两种方式进行日志的记录分别为:注解方式和Api方式
- 注解方式
以@Log注解形式,用事件发布的形式输出,在controller注解示例
java
@Log(module = "角色管理", title = "测试dealGet userName=#{userName} ,password=#{password} ", businessType = BusinessType.INSERT)
@GetMapping(value = "/dealGet")
public String dealGet(@RequestParam("userName") String userName, @RequestParam("password") String password) throws Exception {
log.info("userName=" + userName + "------password=" + password);
return "hello";
}
@Log(module = "用户管理", title = "测试dealPost userName=#{userInfo.userName} ,password=#{userInfo.password}", businessType = BusinessType.INSERT)
@PostMapping(value = "/dealPost")
public String dealPost(@RequestBody UserInfo userInfo) throws Exception {
log.info("userName=" + userInfo.getUserName() + "------password=" + userInfo.getPassword());
return "hello";
}
Log注解参数
名称 | 描述 | 是否必填 |
---|---|---|
module | 模块名称 | 是 |
title | 操作结果主要是显示用,可以写参数的spel表达式获取参数值,如果不进行配置内容为操作类型加上操作结果 列如:删除成功 | 否 |
businessType | 业务类型 默认是其它 0其它,1新增,2修改,3删除,4授权,5导出,6导入,7登录,8退出 | 否 |
isSaveRequestData | 是否记录请求参数,默认为 false | 否 |
isSaveResponseData | 是否记录返回值 ,默认为 false | 否 |
行为日志接收,需要设置用户相关信息,需要设置用户id,用户账号,用户名,及部门,如果 OperLogEvent 对象里auditDataList 不为empty 可以对审计数据进行保存,示例如下:
java
@Async
@EventListener
public void recordOper(OperLogEvent operLogEvent) {
OperationLog operLog = new OperationLog();
BeanUtils.copyProperties(operLogEvent, operLog);
operLog.setUserId("用户id");
operLog.setUserName("用户账号");
operLog.setOperName("用户昵称");
operLog.setDeptName("部门名称");
baseMapper.insert(operLog);
}
OperLogEvent 类属性介绍
名称 | 描述 |
---|---|
Id | 主键 |
userId | 用户id |
userName | 用户账号 |
module | 模块名称 |
title | 详情 |
businessType | 0其它 1新增 2修改 3删除 4授权 5导出 6导入 7登录 8退出登录 |
method | 请求方式 |
operName | 操作人员 |
deptName | 部门名称 |
operUrl | 请求url |
operIp | 操作地址 |
operParam | 请求参数 |
jsonResult | 返回参数 |
status | 操作状态(0正常 1异常) |
msg | 提示消息 |
createTime | 操作时间 |
auditDataList | 数据审计数据 类型为 AuditData |
- Api方式
有些情况下无法使用注解,可以采用api方式进行行为日志的记录,LoggingUtil 类提供了两个静态方法
名称 | 参数 | 描述 |
---|---|---|
doBefore | 无 | 记录日志之前调用的方法 |
doAfter | String title String module BusinessType businessType Object currentObject Method method Object[] args Object result boolean isSaveRequestData boolean isSaveResponseData String[] excludeParamNames Exception exception | 记录日志之后调用的方法,参数title,module,businessType, isSaveRequestData,isSaveResponseData 同注解 currentObject 当前对象,一般填写this,method 当前方法,args 为方法参数,result 方法返回对象 |
以继承CrudController为示例示:
java
package org.iam.controller;
import org.iam.service.impl.BaseClassesServiceImpl;
import org.iam.domain.vo.BaseClassesQuery;
import org.iam.domain.vo.BaseClassesPageQuery;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zebra.logging.enums.BusinessType;
import org.zebra.logging.util.LoggingUtil;
import org.zebra.mybatis.plus.curd.CrudController;
import java.lang.reflect.Method;
@RestController
@RequestMapping("/iam/baseClasses")
@Api(tags = "班组班别接口")
public class BaseClassesController extends CrudController<BaseClassesServiceImpl, BaseClassesQuery, BaseClassesQuery, BaseClassesPageQuery, BaseClassesQuery> {
@Override
protected void before(Method method, Object params) {
LoggingUtil.doBefore();
}
@Override
protected void after(Method method, Object params, Object result) {
if (method.getName().equals("add")) {
LoggingUtil.doAfter("增加班级信息", "班级模块", BusinessType.INSERT, this, method, new Object[]{params}, result
, false, false, null, null);
} else if (method.getName().equals("edit")) {
LoggingUtil.doAfter("编辑班级信息", "班级模块", BusinessType.INSERT, this, method, new Object[]{params}, result
, false, false, null, null);
} else if (method.getName().equals("removeById")) {
LoggingUtil.doAfter("删除班级信息", "班级模块", BusinessType.INSERT, this, method, new Object[]{params}, result
, false, false, null, null);
}
}
}
日志结果和使用注解方式一样用 spring 事件发布的形式输出
随着时间的增长,日志记录会越来越多,以下配置提供了定期清理日志的参数:
参数名称 | 描述 |
---|---|
cleaned | 是否对日志数据进行清理,默认为 false |
reserve-time | 日志保留时间,月为单位(默认6),可以不进行配置 |
table | 日志记录表日志表名(默认sys_operation_log,sys_audit_log),如果存在多个表用,分割 |
cron | 日志删除执行策略 (默认0 0 2 1 * ?) |
yml
zebra:
log:
cleaned: true
reserve-time: 6
table: t_operation_log
cron: 0/5 * * * * ?
http日志输出配置
参数名称 | 描述 |
---|---|
http.enabled | 是否开启http请求和响应日志 默认为 false |
yml
zebra:
log:
http:
enabled: true
sentry接入
yml文件配置
yml
zebra:
log:
sentry:
dsn: http://4bb37d2ad9b487dffda1bbc5ef222031@sentry.jinma.tech/2
enabled: true
diagnostic-level: debug #diagnostic-level 参数可以设置为不同的日志级别,常见的日志级别包括 DEBUG、INFO、WARNING、ERROR 等。具体的级别代表了生成的诊断日志的详细程度,例如 DEBUG 级别会生成最详细的日志信息,而 ERROR 级别只会生成错误信息。
minimum-event-level: error #这个参数用来设置事件日志的最低级别。 事件日志是指应用程序中产生的错误、异常、警告等日志信息,会被 Sentry 收集和记录。通过设置 minimumEventLevel,你可以控制只有达到指定级别及以上的事件日志才会被 Sentry 记录和报告。
minimum-breadcrumb-level: error #这个参数用来设置面包屑日志的最低级别。面包屑是指记录应用程序运行过程中的关键操作和事件的日志信息,用来帮助追踪问题和分析应用程序的行为。通过设置 minimumBreadcrumbLevel,你可以控制只有达到指定级别及以上的面包屑日志才会被 Sentry 记录