Skip to content

介绍

  1. 统一logback日志输出格式,简化日志配置
  2. 统一行为日志记录方式
  3. 对接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方式

  1. 注解方式
    以@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详情
businessType0其它 1新增 2修改 3删除 4授权 5导出 6导入 7登录 8退出登录
method请求方式
operName操作人员
deptName部门名称
operUrl请求url
operIp操作地址
operParam请求参数
jsonResult返回参数
status操作状态(0正常 1异常)
msg提示消息
createTime操作时间
auditDataList数据审计数据 类型为 AuditData
  1. Api方式
    有些情况下无法使用注解,可以采用api方式进行行为日志的记录,LoggingUtil 类提供了两个静态方法
名称参数描述
doBefore记录日志之前调用的方法
doAfterString 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 记录