init
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package cn.fateverse.common.log;
|
||||
|
||||
import cn.fateverse.common.log.aspect.LogAspect;
|
||||
import cn.fateverse.common.log.config.OperationProperties;
|
||||
import cn.fateverse.common.log.service.OperationService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2023-05-21
|
||||
*/
|
||||
@ConditionalOnWebApplication
|
||||
@EnableConfigurationProperties({OperationProperties.class})
|
||||
public class LogAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public LogAspect logAspect(){
|
||||
return new LogAspect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OperationService operationService(OperationProperties properties) {
|
||||
return new OperationService(properties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.fateverse.common.log.annotation;
|
||||
|
||||
import cn.fateverse.common.log.enums.BusinessType;
|
||||
import cn.fateverse.common.log.enums.OperateType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义操作日志记录注解
|
||||
*
|
||||
* @author Clay
|
||||
* @date 2022/11/1
|
||||
*/
|
||||
@Target({ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Log {
|
||||
/**
|
||||
* 日志记录名称
|
||||
*/
|
||||
String title() default "";
|
||||
|
||||
/**
|
||||
* 功能
|
||||
*/
|
||||
BusinessType businessType() default BusinessType.OTHER;
|
||||
|
||||
/**
|
||||
* 操作人类别
|
||||
*/
|
||||
OperateType operatorType() default OperateType.MANAGE;
|
||||
|
||||
/**
|
||||
* 是否保存请求的参数
|
||||
*/
|
||||
boolean isSaveRequestData() default true;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package cn.fateverse.common.log.aspect;
|
||||
|
||||
import cn.fateverse.common.core.utils.HttpServletUtils;
|
||||
import cn.fateverse.common.core.utils.IpUtils;
|
||||
import cn.fateverse.common.log.annotation.Log;
|
||||
import cn.fateverse.common.log.config.OperationProperties;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.fateverse.common.core.constant.UserConstants;
|
||||
import cn.fateverse.common.core.utils.ReflectUserUtils;
|
||||
import cn.fateverse.common.log.enums.LogLeve;
|
||||
import cn.fateverse.common.log.enums.OperateType;
|
||||
import cn.fateverse.common.log.service.OperationService;
|
||||
import cn.fateverse.log.entity.OperationLog;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2022/11/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
public class LogAspect {
|
||||
|
||||
@Autowired
|
||||
private OperationService operationService;
|
||||
|
||||
@Autowired
|
||||
private OperationProperties operationProperties;
|
||||
|
||||
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
|
||||
|
||||
|
||||
|
||||
@Around("@within(log) || @annotation(log)")
|
||||
public Object before(ProceedingJoinPoint point, Log log) throws Throwable {
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
Object proceed = point.proceed(point.getArgs());
|
||||
HttpServletRequest request = HttpServletUtils.getRequest();
|
||||
handleLog(point, proceed, request, null, log, true, startTime);
|
||||
return proceed;
|
||||
}catch (Throwable e){
|
||||
HttpServletRequest request = HttpServletUtils.getRequest();
|
||||
handleLog(point, null, request, e, log, false, startTime);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected Boolean check(Boolean success) {
|
||||
if (!operationProperties.getEnabled()) {
|
||||
return false;
|
||||
}
|
||||
if (operationProperties.getLevel().equals(LogLeve.ALL)) {
|
||||
return true;
|
||||
}
|
||||
if (success & operationProperties.getLevel().equals(LogLeve.SUCCESS)) {
|
||||
return true;
|
||||
}
|
||||
return !success & operationProperties.getLevel().equals(LogLeve.ERROR);
|
||||
}
|
||||
|
||||
|
||||
protected void handleLog(JoinPoint point, Object jsonResult, HttpServletRequest request, Throwable e, Log controllerLog, Boolean success, Long time) {
|
||||
if (!check(success)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
controllerLog = chickLog(point, controllerLog);
|
||||
OperationLog operationLog = new OperationLog();
|
||||
//请求地址
|
||||
operationLog.setOperIp(IpUtils.getIpAdder(request));
|
||||
operationLog.setOperUrl(request.getRequestURI());
|
||||
// 设置请求方式
|
||||
operationLog.setRequestMethod(request.getMethod());
|
||||
//处理设置注解上的参数
|
||||
getControllerMethodDescription(point, controllerLog, operationLog, request);
|
||||
// 设置操作人
|
||||
setOperName(operationLog);
|
||||
// 设置方法名称
|
||||
String className = point.getTarget().getClass().getName();
|
||||
String methodName = point.getSignature().getName();
|
||||
operationLog.setMethod(className + "." + methodName + "()");
|
||||
operationService.asyncExecute(operationLog,jsonResult,e,time);
|
||||
} catch (Exception exp) {
|
||||
// 记录本地异常日志
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置操作人
|
||||
*
|
||||
* @param operationLog
|
||||
*/
|
||||
public void setOperName(OperationLog operationLog) {
|
||||
try {
|
||||
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
if (null != principal && !UserConstants.ANONYMOUS_USER.equals(principal)) {
|
||||
String userName = ReflectUserUtils.getUsername(principal);
|
||||
operationLog.setOperName(userName);
|
||||
String userId = ReflectUserUtils.getUserId(principal);
|
||||
operationLog.setUserId(Long.valueOf(userId));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("当前接口不是由登录后的用户触发的!");
|
||||
operationLog.setOperatorType(OperateType.OTHER.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取控制前方法上的描述
|
||||
*
|
||||
* @param point
|
||||
* @param log
|
||||
* @param operationLog
|
||||
* @param request
|
||||
* @throws Exception
|
||||
*/
|
||||
public void getControllerMethodDescription(JoinPoint point, Log log, OperationLog operationLog, HttpServletRequest request) throws Exception {
|
||||
//设置action动作
|
||||
operationLog.setBusinessType(log.businessType().ordinal());
|
||||
//设置标题
|
||||
operationLog.setTitle(log.title());
|
||||
//设置操作人类型
|
||||
operationLog.setOperatorType(log.operatorType().ordinal());
|
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData()) {
|
||||
// 获取参数的信息,传入到数据库中
|
||||
setRequestValue(point, operationLog, request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
* @param operationLog 操作日志
|
||||
* @param request
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
private void setRequestValue(JoinPoint joinPoint, OperationLog operationLog, HttpServletRequest request) throws Exception {
|
||||
String requestMethod = operationLog.getRequestMethod();
|
||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
||||
String params = argsArrayToString(joinPoint.getArgs());
|
||||
operationLog.setOperParam(StrUtil.sub(params, 0, 2000));
|
||||
} else {
|
||||
Map<?, ?> paramsMap = (Map<?, ?>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
operationLog.setOperParam(StrUtil.sub(paramsMap.toString(), 0, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 参数拼装
|
||||
*/
|
||||
private String argsArrayToString(Object[] paramsArray) {
|
||||
StringBuilder params = new StringBuilder();
|
||||
if (paramsArray != null && paramsArray.length > 0) {
|
||||
for (Object object : paramsArray) {
|
||||
if (!isFilterObject(object)) {
|
||||
Object jsonObj = JSON.toJSON(object);
|
||||
params.append(jsonObj.toString()).append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
return params.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要过滤的对象。
|
||||
*
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
public boolean isFilterObject(final Object o) {
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Log相关信息
|
||||
*
|
||||
* @param point
|
||||
* @param log
|
||||
* @return
|
||||
*/
|
||||
public Log chickLog(JoinPoint point, Log log) {
|
||||
if (log == null) {
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
if (method != null) {
|
||||
log = method.getAnnotation(Log.class);
|
||||
}
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package cn.fateverse.common.log.config;
|
||||
|
||||
import cn.fateverse.common.log.enums.LogLeve;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2023-05-25
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "operation-log")
|
||||
public class OperationProperties {
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
// all success error
|
||||
private LogLeve level;
|
||||
|
||||
private Integer cacheSize;
|
||||
|
||||
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled == null || enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public LogLeve getLevel() {
|
||||
if (null == level){
|
||||
return LogLeve.ALL;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(LogLeve level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public Integer getCacheSize() {
|
||||
if (null == cacheSize){
|
||||
cacheSize = 8;
|
||||
}
|
||||
return cacheSize;
|
||||
}
|
||||
|
||||
public void setCacheSize(Integer cacheSize) {
|
||||
|
||||
this.cacheSize = cacheSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.fateverse.common.log.enums;
|
||||
|
||||
/**
|
||||
* 操作状态
|
||||
*
|
||||
* @author Clay
|
||||
*/
|
||||
public enum BusinessState {
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
SUCCESS,
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
FAIL,
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package cn.fateverse.common.log.enums;
|
||||
|
||||
/**
|
||||
* 业务操作类型
|
||||
* @author Clay
|
||||
* @date 2022/11/1
|
||||
*/
|
||||
public enum BusinessType {
|
||||
/**
|
||||
* 其它
|
||||
*/
|
||||
OTHER,
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
INSERT,
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
UPDATE,
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
DELETE,
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
GRANT,
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*/
|
||||
EXPORT,
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*/
|
||||
IMPORT,
|
||||
|
||||
/**
|
||||
* 强退
|
||||
*/
|
||||
FORCE,
|
||||
|
||||
/**
|
||||
* 执行代码
|
||||
*/
|
||||
EXECUTE_CODE,
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
*/
|
||||
GENCODE,
|
||||
|
||||
/**
|
||||
* 清空数据
|
||||
*/
|
||||
CLEAN,
|
||||
/**
|
||||
* 解除绑定
|
||||
*/
|
||||
BIND,
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.fateverse.common.log.enums;
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2023-05-25
|
||||
*/
|
||||
public enum LogLeve {
|
||||
|
||||
ALL("all"),
|
||||
SUCCESS("success"),
|
||||
ERROR("error"),
|
||||
;
|
||||
|
||||
final String value;
|
||||
|
||||
LogLeve(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.fateverse.common.log.enums;
|
||||
|
||||
/**
|
||||
* 操作人类别
|
||||
*
|
||||
* @author Clay
|
||||
* @date 2022/11/1
|
||||
*/
|
||||
public enum OperateType {
|
||||
/**
|
||||
* 其它
|
||||
*/
|
||||
OTHER,
|
||||
|
||||
/**
|
||||
* 后台用户
|
||||
*/
|
||||
MANAGE,
|
||||
|
||||
/**
|
||||
* 手机端用户
|
||||
*/
|
||||
MOBILE
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package cn.fateverse.common.log.service;
|
||||
|
||||
import cn.fateverse.common.core.enums.ResultEnum;
|
||||
import cn.fateverse.common.core.exception.BaseException;
|
||||
import cn.fateverse.common.core.result.Result;
|
||||
import cn.fateverse.common.log.config.OperationProperties;
|
||||
import cn.fateverse.common.log.enums.BusinessState;
|
||||
import cn.fateverse.log.dubbo.DubboLogService;
|
||||
import cn.fateverse.log.entity.OperationLog;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2023-08-03
|
||||
*/
|
||||
@Slf4j
|
||||
public class OperationService {
|
||||
|
||||
private final ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
|
||||
|
||||
@DubboReference
|
||||
private DubboLogService logService;
|
||||
|
||||
private final OperationProperties properties;
|
||||
|
||||
|
||||
private final List<OperationLog> operationLogListCache;
|
||||
|
||||
public OperationService(OperationProperties properties) {
|
||||
this.properties = properties;
|
||||
this.operationLogListCache = new ArrayList<>(properties.getCacheSize());
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
service.scheduleAtFixedRate(() -> {
|
||||
synchronized (operationLogListCache) {
|
||||
if (!operationLogListCache.isEmpty()) {
|
||||
logService.batchSaveLog(operationLogListCache);
|
||||
operationLogListCache.clear();
|
||||
}
|
||||
}
|
||||
}, 1, 1, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
|
||||
@Async
|
||||
public void asyncExecute(OperationLog operationLog, Object jsonResult, Throwable e, Long time) {
|
||||
operationLog.setState(BusinessState.SUCCESS.ordinal());
|
||||
// 返回参数
|
||||
if (jsonResult instanceof Result) {
|
||||
Result<Object> result = (Result<Object>) jsonResult;
|
||||
operationLog.setJsonResult(JSON.toJSONString(jsonResult));
|
||||
if (result.getCode() != ResultEnum.SUCCESS.code) {
|
||||
operationLog.setState(1);
|
||||
}
|
||||
operationLog.setJsonResult(JSON.toJSONString(result));
|
||||
} else {
|
||||
operationLog.setState(1);
|
||||
operationLog.setJsonResult(JSON.toJSONString(jsonResult));
|
||||
}
|
||||
if (null != e) {
|
||||
operationLog.setState(BusinessState.FAIL.ordinal());
|
||||
if (!(e instanceof BaseException)) {
|
||||
//将错误栈打印到错误信息中
|
||||
String trace = ExceptionUtils.getStackTrace(e);
|
||||
if (!ObjectUtils.isEmpty(trace)) {
|
||||
operationLog.setErrorStackTrace(trace);
|
||||
}
|
||||
}
|
||||
operationLog.setErrorMsg(e.getMessage());
|
||||
}
|
||||
if (null != time) {
|
||||
operationLog.setConsumeTime(System.currentTimeMillis() - time);
|
||||
}
|
||||
operationLog.setOperTime(new Date());
|
||||
saveLog(operationLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志,先存入到缓存之中
|
||||
*
|
||||
* @param operationLog 操作日志
|
||||
*/
|
||||
private void saveLog(OperationLog operationLog) {
|
||||
synchronized (operationLogListCache) {
|
||||
operationLogListCache.add(operationLog);
|
||||
if (operationLogListCache.size() >= properties.getCacheSize()) {
|
||||
logService.batchSaveLog(operationLogListCache);
|
||||
operationLogListCache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "operation-log",
|
||||
"type": "cn.fateverse.log.config.OperationProperties",
|
||||
"sourceType": "cn.fateverse.log.config.OperationProperties"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "operation-log.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"sourceType": "cn.fateverse.log.config.OperationProperties"
|
||||
},
|
||||
{
|
||||
"name": "operation-log.level",
|
||||
"type": "cn.fateverse.common.log.enums.LogLeve",
|
||||
"sourceType": "cn.fateverse.log.config.OperationProperties"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cn.fateverse.common.log.LogAutoConfiguration
|
||||
4
common/common-log/src/main/resources/log4j.properties
Normal file
4
common/common-log/src/main/resources/log4j.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
log4j.rootLogger=WARN, stdout
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
|
||||
33
common/common-log/src/main/resources/logback-dev.xml
Normal file
33
common/common-log/src/main/resources/logback-dev.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration scan="false">
|
||||
<property name="LOG_HOME" value="/home/clay/logs"/><!-- 上线阶段修改 -->
|
||||
<!-- 日志输出到控制台 -->
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<pattern>%green(%d{yyyy-MM-dd HH:mm:ss.SSS}) %highlight(%-5level) %cyan([%thread] %60.60logger) -
|
||||
%highlight(%msg%n)
|
||||
</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- 日志输出到文件 -->
|
||||
<appender name="alllog" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/spring.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/backup/%d{yyyy-MM-dd}/Loyalty.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 根Logger -->
|
||||
<root level="debug">
|
||||
<appender-ref ref="stdout"/>
|
||||
<appender-ref ref="alllog"/>
|
||||
</root>
|
||||
|
||||
|
||||
</configuration>
|
||||
|
||||
32
common/common-log/src/main/resources/logback-pro.xml
Normal file
32
common/common-log/src/main/resources/logback-pro.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration scan="false">
|
||||
<property name="LOG_HOME" value="/home/clay/logs"/><!-- 上线阶段修改 -->
|
||||
<!-- 日志输出到控制台 -->
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<pattern>%green(%d{yyyy-MM-dd HH:mm:ss.SSS}) %highlight(%-5level) %cyan([%thread] %60.60logger) -
|
||||
%highlight(%msg%n)
|
||||
</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- 日志输出到文件 -->
|
||||
<appender name="alllog" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/spring.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/backup/%d{yyyy-MM}/%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 根Logger -->
|
||||
<root level="info">
|
||||
<appender-ref ref="alllog"/>
|
||||
</root>
|
||||
|
||||
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user