mirror of https://gitee.com/stylefeng/roses
【log】整理代码
parent
ac94d92218
commit
89c378807f
|
@ -3,20 +3,22 @@ package cn.stylefeng.roses.kernel.log.api.pojo.log;
|
|||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 日志配置信息
|
||||
* 日志配置信息
|
||||
*
|
||||
* @author liuhanqing
|
||||
* @date 2020-12-20 13:53
|
||||
* @author liuhanqing
|
||||
* @date 2020-12-20 13:53
|
||||
**/
|
||||
@Data
|
||||
public class SysLogProperties {
|
||||
/**
|
||||
* 日志存储类型:db-数据库,file-文件,默认存储在数据库中
|
||||
*/
|
||||
private String type = "db";
|
||||
|
||||
/**
|
||||
* file存储类型日志文件的存储位置
|
||||
*/
|
||||
private String fileSavePath = "_sys_log";
|
||||
/**
|
||||
* 日志存储类型:db-数据库,file-文件,默认存储在数据库中
|
||||
*/
|
||||
private String type = "db";
|
||||
|
||||
/**
|
||||
* file存储类型日志文件的存储位置
|
||||
*/
|
||||
private String fileSavePath = "_sys_log";
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.aspectj.lang.annotation.Pointcut;
|
|||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
|
@ -31,131 +30,130 @@ import java.util.Map;
|
|||
* @date 2020/10/28 17:06
|
||||
*/
|
||||
@Aspect
|
||||
//@Component
|
||||
@Slf4j
|
||||
public class RequestApiLogRecordAop implements Ordered {
|
||||
|
||||
/**
|
||||
* 日志记录的api
|
||||
*/
|
||||
private final LogRecordApi logRecordApi;
|
||||
/**
|
||||
* 日志记录的api
|
||||
*/
|
||||
private final LogRecordApi logRecordApi;
|
||||
|
||||
public RequestApiLogRecordAop(LogRecordApi logRecordApi) {
|
||||
this.logRecordApi = logRecordApi;
|
||||
}
|
||||
public RequestApiLogRecordAop(LogRecordApi logRecordApi) {
|
||||
this.logRecordApi = logRecordApi;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切所有controller包
|
||||
*/
|
||||
@Pointcut("execution(* *..controller.*.*(..))")
|
||||
public void cutService() {
|
||||
/**
|
||||
* 切所有controller包
|
||||
*/
|
||||
@Pointcut("execution(* *..controller.*.*(..))")
|
||||
public void cutService() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Around("cutService()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
Object result = point.proceed();
|
||||
@Around("cutService()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
Object result = point.proceed();
|
||||
|
||||
try {
|
||||
Map<String, Object> args = getFieldsName(point);
|
||||
recordLog(args, result);
|
||||
} catch (Exception e) {
|
||||
log.error("日志记录没有记录成功!", e);
|
||||
}
|
||||
try {
|
||||
Map<String, Object> args = getFieldsName(point);
|
||||
recordLog(args, result);
|
||||
} catch (Exception e) {
|
||||
log.error("日志记录没有记录成功!", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将请求方法记录日志的过程
|
||||
*
|
||||
* @param params AOP拦截方法的参数封装,key是参数名称,v是参数值
|
||||
* @param result AOP拦截方法的返回值
|
||||
* @author fengshuonan
|
||||
* @date 2020/10/28 17:38
|
||||
*/
|
||||
private void recordLog(Map<String, Object> params, Object result) {
|
||||
/**
|
||||
* 将请求方法记录日志的过程
|
||||
*
|
||||
* @param params AOP拦截方法的参数封装,key是参数名称,v是参数值
|
||||
* @param result AOP拦截方法的返回值
|
||||
* @author fengshuonan
|
||||
* @date 2020/10/28 17:38
|
||||
*/
|
||||
private void recordLog(Map<String, Object> params, Object result) {
|
||||
|
||||
// 创建日志对象
|
||||
LogRecordDTO logRecordDTO = LogRecordFactory.createLogRecord(LogConstants.LOG_DEFAULT_NAME, null);
|
||||
// 创建日志对象
|
||||
LogRecordDTO logRecordDTO = LogRecordFactory.createLogRecord(LogConstants.LOG_DEFAULT_NAME, null);
|
||||
|
||||
// 填充用户登录信息
|
||||
AuthedLogAppender.appendAuthedHttpLog(logRecordDTO);
|
||||
// 填充用户登录信息
|
||||
AuthedLogAppender.appendAuthedHttpLog(logRecordDTO);
|
||||
|
||||
// 填充http接口请求信息
|
||||
HttpLogAppender.appendHttpLog(logRecordDTO);
|
||||
// 填充http接口请求信息
|
||||
HttpLogAppender.appendHttpLog(logRecordDTO);
|
||||
|
||||
// 追加参数信息
|
||||
ParamsLogAppender.appendAuthedHttpLog(logRecordDTO, params, result);
|
||||
// 追加参数信息
|
||||
ParamsLogAppender.appendAuthedHttpLog(logRecordDTO, params, result);
|
||||
|
||||
// 异步记录日志
|
||||
logRecordApi.recordLogAsync(logRecordDTO);
|
||||
}
|
||||
// 异步记录日志
|
||||
logRecordApi.recordLogAsync(logRecordDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return LogConfigExpander.getRequestApiLogAopSort();
|
||||
}
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return LogConfigExpander.getRequestApiLogAopSort();
|
||||
}
|
||||
|
||||
/**
|
||||
* AOP获取参数名称和参数值
|
||||
*
|
||||
* @param joinPoint joinPoint对象
|
||||
* @return 返回K, V格式的参数,key是参数名称,v是参数值
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 10:40
|
||||
*/
|
||||
private Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {
|
||||
/**
|
||||
* AOP获取参数名称和参数值
|
||||
*
|
||||
* @param joinPoint joinPoint对象
|
||||
* @return 返回K, V格式的参数,key是参数名称,v是参数值
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 10:40
|
||||
*/
|
||||
private Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {
|
||||
|
||||
// 获取被拦截方法的所有参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
// 获取被拦截方法的所有参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
|
||||
// 通过map封装参数和参数值,key参数名,value是参数值
|
||||
Map<String, Object> paramMap = new HashMap<>(args.length);
|
||||
try {
|
||||
String classType = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
// 通过map封装参数和参数值,key参数名,value是参数值
|
||||
Map<String, Object> paramMap = new HashMap<>(args.length);
|
||||
try {
|
||||
String classType = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
|
||||
// 处理基本类型
|
||||
Class<?>[] classes = new Class[args.length];
|
||||
for (int k = 0; k < args.length; k++) {
|
||||
classes[k] = args[k].getClass();
|
||||
}
|
||||
// 处理基本类型
|
||||
Class<?>[] classes = new Class[args.length];
|
||||
for (int k = 0; k < args.length; k++) {
|
||||
classes[k] = args[k].getClass();
|
||||
}
|
||||
|
||||
ParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
ParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
// 获取指定的方法,第二个参数可以不传,但是为了防止有重载的现象,还是需要传入参数的类型
|
||||
Method method = Class.forName(classType).getMethod(methodName, classes);
|
||||
// 获取指定的方法,第二个参数可以不传,但是为了防止有重载的现象,还是需要传入参数的类型
|
||||
Method method = Class.forName(classType).getMethod(methodName, classes);
|
||||
|
||||
// 参数名
|
||||
String[] parameterNames = defaultParameterNameDiscoverer.getParameterNames(method);
|
||||
// 参数名
|
||||
String[] parameterNames = defaultParameterNameDiscoverer.getParameterNames(method);
|
||||
|
||||
// 为空直接返回
|
||||
if (null == parameterNames) {
|
||||
return new HashMap<>(1);
|
||||
}
|
||||
// 为空直接返回
|
||||
if (null == parameterNames) {
|
||||
return new HashMap<>(1);
|
||||
}
|
||||
|
||||
// 装载参数名称和参数值
|
||||
for (int i = 0; i < parameterNames.length; i++) {
|
||||
paramMap.put(parameterNames[i], args[i]);
|
||||
}
|
||||
// 装载参数名称和参数值
|
||||
for (int i = 0; i < parameterNames.length; i++) {
|
||||
paramMap.put(parameterNames[i], args[i]);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
|
||||
// 打印日志
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
// 打印日志
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
|
||||
// 有异常则不显示参数名称直接返回参数
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
paramMap.put("args" + i, args[i]);
|
||||
}
|
||||
// 有异常则不显示参数名称直接返回参数
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
paramMap.put("args" + i, args[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return paramMap;
|
||||
}
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,17 +4,14 @@ import cn.hutool.core.bean.BeanUtil;
|
|||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.log.Log;
|
||||
import cn.hutool.log.LogFactory;
|
||||
import cn.stylefeng.roses.kernel.log.api.LogRecordApi;
|
||||
import cn.stylefeng.roses.kernel.log.api.constants.LogConstants;
|
||||
import cn.stylefeng.roses.kernel.log.api.pojo.record.LogRecordDTO;
|
||||
import cn.stylefeng.roses.kernel.log.api.threadpool.LogManagerThreadPool;
|
||||
import cn.stylefeng.roses.kernel.log.db.entity.SysLog;
|
||||
import cn.stylefeng.roses.kernel.log.db.service.SysLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -23,265 +20,259 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 数据库存储方式的日志记录器 todo 有问题
|
||||
* 数据库存储方式的日志记录器
|
||||
*
|
||||
* @author luojie
|
||||
* @date 2020/11/2 15:50
|
||||
*/
|
||||
//@Service
|
||||
@Slf4j
|
||||
public class DbLogRecordServiceImpl implements LogRecordApi {
|
||||
|
||||
/**
|
||||
* Hutool日志对象
|
||||
*/
|
||||
private final Log log = LogFactory.get();
|
||||
/**
|
||||
* 日志记录 service接口
|
||||
*/
|
||||
private final SysLogService sysLogService;
|
||||
|
||||
/**
|
||||
* 日志记录 service接口
|
||||
*/
|
||||
@Resource
|
||||
private SysLogService sysLogService;
|
||||
/**
|
||||
* 异步记录日志用的线程池
|
||||
*/
|
||||
private final LogManagerThreadPool logManagerThreadPool;
|
||||
|
||||
/**
|
||||
* 异步记录日志用的线程池
|
||||
*/
|
||||
private final LogManagerThreadPool logManagerThreadPool;
|
||||
|
||||
/**
|
||||
* 日志刷新管理器
|
||||
*/
|
||||
private final LogRefreshManager logRefreshManager;
|
||||
/**
|
||||
* 日志刷新管理器
|
||||
*/
|
||||
private final LogRefreshManager logRefreshManager;
|
||||
|
||||
|
||||
public DbLogRecordServiceImpl(LogManagerThreadPool logManagerThreadPool, SysLogService sysLogService) {
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.sysLogService = sysLogService;
|
||||
this.logRefreshManager = new LogRefreshManager();
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
public DbLogRecordServiceImpl(LogManagerThreadPool logManagerThreadPool, SysLogService sysLogService) {
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.sysLogService = sysLogService;
|
||||
this.logRefreshManager = new LogRefreshManager();
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
|
||||
public DbLogRecordServiceImpl(LogManagerThreadPool logManagerThreadPool, SysLogService sysLogService, long sleepTime, int maxCount) {
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.sysLogService = sysLogService;
|
||||
this.logRefreshManager = new LogRefreshManager(sleepTime, maxCount);
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
public DbLogRecordServiceImpl(LogManagerThreadPool logManagerThreadPool, SysLogService sysLogService, long sleepTime, int maxCount) {
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.sysLogService = sysLogService;
|
||||
this.logRefreshManager = new LogRefreshManager(sleepTime, maxCount);
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLog(LogRecordDTO logRecordDTO) {
|
||||
if (logRecordDTO == null) {
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void recordLog(LogRecordDTO logRecordDTO) {
|
||||
if (logRecordDTO == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 输出日志
|
||||
recordLogByList(CollectionUtil.list(false, logRecordDTO));
|
||||
}
|
||||
// 输出日志
|
||||
recordLogByList(CollectionUtil.list(false, logRecordDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLogByList(List<LogRecordDTO> logRecords) {
|
||||
@Override
|
||||
public void recordLogByList(List<LogRecordDTO> logRecords) {
|
||||
|
||||
if (ObjectUtil.isEmpty(logRecords)) {
|
||||
return;
|
||||
}
|
||||
if (ObjectUtil.isEmpty(logRecords)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<SysLog> sysLogList = logRecords.stream().map(logRecordDTO -> {
|
||||
SysLog sysLog = new SysLog();
|
||||
// 复制logRecordDTO对象属性到sysLog
|
||||
BeanUtil.copyProperties(logRecordDTO, sysLog);
|
||||
List<SysLog> sysLogList = logRecords.stream().map(logRecordDTO -> {
|
||||
SysLog sysLog = new SysLog();
|
||||
// 复制logRecordDTO对象属性到sysLog
|
||||
BeanUtil.copyProperties(logRecordDTO, sysLog);
|
||||
|
||||
// 日志名称为空的话则获取默认日志名称
|
||||
if (StrUtil.isEmpty(sysLog.getLogName())) {
|
||||
sysLog.setLogName(LogConstants.LOG_DEFAULT_NAME);
|
||||
}
|
||||
// 日志名称为空的话则获取默认日志名称
|
||||
if (StrUtil.isEmpty(sysLog.getLogName())) {
|
||||
sysLog.setLogName(LogConstants.LOG_DEFAULT_NAME);
|
||||
}
|
||||
|
||||
// 服务名称为空的话则获取默认服务名称
|
||||
if (StrUtil.isEmpty(sysLog.getAppName())) {
|
||||
sysLog.setAppName(LogConstants.LOG_DEFAULT_APP_NAME);
|
||||
}
|
||||
// 服务名称为空的话则获取默认服务名称
|
||||
if (StrUtil.isEmpty(sysLog.getAppName())) {
|
||||
sysLog.setAppName(LogConstants.LOG_DEFAULT_APP_NAME);
|
||||
}
|
||||
|
||||
// 如果操作时间为空的话插入当前时间
|
||||
if (sysLog.getCreateTime() == null) {
|
||||
sysLog.setCreateTime(new Date());
|
||||
}
|
||||
// 如果操作时间为空的话插入当前时间
|
||||
if (sysLog.getCreateTime() == null) {
|
||||
sysLog.setCreateTime(new Date());
|
||||
}
|
||||
|
||||
return sysLog;
|
||||
}).collect(Collectors.toList());
|
||||
return sysLog;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 插入到数据库
|
||||
sysLogService.saveBatch(sysLogList);
|
||||
}
|
||||
// 插入到数据库
|
||||
sysLogService.saveBatch(sysLogList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLogAsync(LogRecordDTO logRecordDTO) {
|
||||
logManagerThreadPool.executeLog(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
logRefreshManager.putLog(logRecordDTO);
|
||||
}
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void recordLogAsync(LogRecordDTO logRecordDTO) {
|
||||
logManagerThreadPool.executeLog(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
logRefreshManager.putLog(logRecordDTO);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志刷新管理器
|
||||
* <p>
|
||||
* 该类暂存所有将要写出到磁盘的日志,使用内存缓冲区减少对磁盘IO的操作
|
||||
* <p>
|
||||
* 该类维护一个最大日志数和一个刷新日志间隔,满足任意一个条件即可触发从内存写出日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:05
|
||||
*/
|
||||
class LogRefreshManager extends Thread {
|
||||
/**
|
||||
* 日志刷新管理器
|
||||
* <p>
|
||||
* 该类暂存所有将要写出到磁盘的日志,使用内存缓冲区减少对磁盘IO的操作
|
||||
* <p>
|
||||
* 该类维护一个最大日志数和一个刷新日志间隔,满足任意一个条件即可触发从内存写出日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:05
|
||||
*/
|
||||
class LogRefreshManager extends Thread {
|
||||
|
||||
/**
|
||||
* 刷新日志间隔(默认3秒),单位毫秒
|
||||
*/
|
||||
private final long sleepTime;
|
||||
/**
|
||||
* 刷新日志间隔(默认3秒),单位毫秒
|
||||
*/
|
||||
private final long sleepTime;
|
||||
|
||||
/**
|
||||
* 满足多少条就强制刷新一次(默认300条),该值只是一个大约值,实际记录并不会一定等于该值(可能会大于该值,不可能小于该值)
|
||||
*/
|
||||
private final int maxCount;
|
||||
/**
|
||||
* 满足多少条就强制刷新一次(默认300条),该值只是一个大约值,实际记录并不会一定等于该值(可能会大于该值,不可能小于该值)
|
||||
*/
|
||||
private final int maxCount;
|
||||
|
||||
/**
|
||||
* 刷新数据时间标志,每次刷新都记录当前的时间戳,方便定时刷新准确判断上次刷新和本次刷新的时间间隔
|
||||
*/
|
||||
private final AtomicLong refreshMark = new AtomicLong();
|
||||
/**
|
||||
* 刷新数据时间标志,每次刷新都记录当前的时间戳,方便定时刷新准确判断上次刷新和本次刷新的时间间隔
|
||||
*/
|
||||
private final AtomicLong refreshMark = new AtomicLong();
|
||||
|
||||
public LogRefreshManager() {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
public LogRefreshManager() {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
|
||||
public LogRefreshManager(long sleepTime) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
public LogRefreshManager(long sleepTime) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
|
||||
public LogRefreshManager(int maxCount) {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
public LogRefreshManager(int maxCount) {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
public LogRefreshManager(long sleepTime, int maxCount) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
public LogRefreshManager(long sleepTime, int maxCount) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 未处理日志的消息队列
|
||||
*/
|
||||
private final Queue<LogRecordDTO> queue = new ConcurrentLinkedQueue<>();
|
||||
/**
|
||||
* 未处理日志的消息队列
|
||||
*/
|
||||
private final Queue<LogRecordDTO> queue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/**
|
||||
* 消息总数,队列的size方法会遍历一遍队列,所以自己维护大小
|
||||
*/
|
||||
public AtomicInteger count = new AtomicInteger(0);
|
||||
/**
|
||||
* 消息总数,队列的size方法会遍历一遍队列,所以自己维护大小
|
||||
*/
|
||||
public AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* 往队列内新增一条日志数据
|
||||
*
|
||||
* @param logRecordDTO 日志对象
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 14:59
|
||||
*/
|
||||
public void putLog(LogRecordDTO logRecordDTO) {
|
||||
/**
|
||||
* 往队列内新增一条日志数据
|
||||
*
|
||||
* @param logRecordDTO 日志对象
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 14:59
|
||||
*/
|
||||
public void putLog(LogRecordDTO logRecordDTO) {
|
||||
|
||||
int queueDataCount = count.get();
|
||||
int queueDataCount = count.get();
|
||||
|
||||
// 如果是第一条消息,刷新一次refreshMark
|
||||
if (queueDataCount == 0) {
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
}
|
||||
// 如果是第一条消息,刷新一次refreshMark
|
||||
if (queueDataCount == 0) {
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
// 如果后续写入磁盘的操作有异常(磁盘满了),为了防止日志刷不出去导致OOM,内存中最大只保留maxCount数一倍的日志,后续日志将丢弃
|
||||
if (queueDataCount >= (maxCount * 2)) {
|
||||
return;
|
||||
}
|
||||
// 如果后续写入磁盘的操作有异常(磁盘满了),为了防止日志刷不出去导致OOM,内存中最大只保留maxCount数一倍的日志,后续日志将丢弃
|
||||
if (queueDataCount >= (maxCount * 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue.offer(logRecordDTO);
|
||||
count.incrementAndGet();
|
||||
}
|
||||
queue.offer(logRecordDTO);
|
||||
count.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:48
|
||||
*/
|
||||
private void refresh() {
|
||||
/**
|
||||
* 刷新日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:48
|
||||
*/
|
||||
private void refresh() {
|
||||
|
||||
// 让睡眠线程本次不要再调本方法,睡眠至下次看refreshMark的值再决定要不要调用本方法
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
// 让睡眠线程本次不要再调本方法,睡眠至下次看refreshMark的值再决定要不要调用本方法
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
|
||||
// 获取总数
|
||||
int num = count.getAndSet(0);
|
||||
// 获取总数
|
||||
int num = count.getAndSet(0);
|
||||
|
||||
// 再队列中读取num条数据,放入list
|
||||
List<LogRecordDTO> cacheAll = new ArrayList<>(num);
|
||||
for (int i = 0; i < num; i++) {
|
||||
LogRecordDTO item = queue.poll();
|
||||
if (null == item) {
|
||||
break;
|
||||
}
|
||||
cacheAll.add(item);
|
||||
}
|
||||
// 再队列中读取num条数据,放入list
|
||||
List<LogRecordDTO> cacheAll = new ArrayList<>(num);
|
||||
for (int i = 0; i < num; i++) {
|
||||
LogRecordDTO item = queue.poll();
|
||||
if (null == item) {
|
||||
break;
|
||||
}
|
||||
cacheAll.add(item);
|
||||
}
|
||||
|
||||
// 调用方法刷新到磁盘
|
||||
recordLogByList(cacheAll);
|
||||
}
|
||||
// 调用方法刷新到磁盘
|
||||
recordLogByList(cacheAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志数据定时执行器
|
||||
* <p>
|
||||
* 用于定时检测日志数据是否可以写入数据
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:57
|
||||
*/
|
||||
private void timing() {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
/**
|
||||
* 日志数据定时执行器
|
||||
* <p>
|
||||
* 用于定时检测日志数据是否可以写入数据
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:57
|
||||
*/
|
||||
private void timing() {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
|
||||
// 如果是激活状态,且消息数大于零,且符合上次调用refresh方法到目前时间的间隔,那就调用一次refresh方法
|
||||
if ((refreshMark.get() + sleepTime) <= currentTimeMillis && count.get() > 0) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
// 如果是激活状态,且消息数大于零,且符合上次调用refresh方法到目前时间的间隔,那就调用一次refresh方法
|
||||
if ((refreshMark.get() + sleepTime) <= currentTimeMillis && count.get() > 0) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志数据监听器
|
||||
* <p>
|
||||
* 用于监听日志消息队列,达到设定的数就开始执行刷入硬盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 9:32
|
||||
*/
|
||||
private void listener() {
|
||||
// 判断如果队列里面的数据大于等于设定的最大消息数,就调用refresh方法刷新一次数据
|
||||
if (count.get() >= maxCount) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 日志数据监听器
|
||||
* <p>
|
||||
* 用于监听日志消息队列,达到设定的数就开始执行刷入硬盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 9:32
|
||||
*/
|
||||
private void listener() {
|
||||
// 判断如果队列里面的数据大于等于设定的最大消息数,就调用refresh方法刷新一次数据
|
||||
if (count.get() >= maxCount) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
// 消息监听器
|
||||
listener();
|
||||
// 定时任务监听器
|
||||
timing();
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@Override
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
// 消息监听器
|
||||
listener();
|
||||
// 定时任务监听器
|
||||
timing();
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,12 +7,11 @@ import cn.hutool.core.util.ObjectUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.log.Log;
|
||||
import cn.hutool.log.LogFactory;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import cn.stylefeng.roses.kernel.log.api.LogRecordApi;
|
||||
import cn.stylefeng.roses.kernel.log.api.constants.LogFileConstants;
|
||||
import cn.stylefeng.roses.kernel.log.api.pojo.record.LogRecordDTO;
|
||||
import cn.stylefeng.roses.kernel.log.api.threadpool.LogManagerThreadPool;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -31,299 +30,298 @@ import static cn.stylefeng.roses.kernel.log.api.constants.LogFileConstants.FILE_
|
|||
* @author fengshuonan
|
||||
* @date 2020/10/28 14:52
|
||||
*/
|
||||
//@Service
|
||||
public class FileLogRecordServiceImpl implements LogRecordApi {
|
||||
|
||||
private final LogManagerThreadPool logManagerThreadPool;
|
||||
private final LogManagerThreadPool logManagerThreadPool;
|
||||
|
||||
private final LogRefreshManager logRefreshManager;
|
||||
private final LogRefreshManager logRefreshManager;
|
||||
|
||||
private final String fileSavePath;
|
||||
private final String fileSavePath;
|
||||
|
||||
public FileLogRecordServiceImpl(String fileSavePath, LogManagerThreadPool logManagerThreadPool) {
|
||||
this.fileSavePath = fileSavePath;
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.logRefreshManager = new LogRefreshManager();
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
public FileLogRecordServiceImpl(String fileSavePath, LogManagerThreadPool logManagerThreadPool) {
|
||||
this.fileSavePath = fileSavePath;
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.logRefreshManager = new LogRefreshManager();
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
|
||||
public FileLogRecordServiceImpl(String fileSavePath, LogManagerThreadPool logManagerThreadPool, long sleepTime, int maxCount) {
|
||||
this.fileSavePath = fileSavePath;
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.logRefreshManager = new LogRefreshManager(sleepTime, maxCount);
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
public FileLogRecordServiceImpl(String fileSavePath, LogManagerThreadPool logManagerThreadPool, long sleepTime, int maxCount) {
|
||||
this.fileSavePath = fileSavePath;
|
||||
this.logManagerThreadPool = logManagerThreadPool;
|
||||
this.logRefreshManager = new LogRefreshManager(sleepTime, maxCount);
|
||||
this.logRefreshManager.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志文件的组成形式应为appName-年-月-日.log
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/10/28 15:53
|
||||
*/
|
||||
@Override
|
||||
public void recordLog(LogRecordDTO logRecordDTO) {
|
||||
/**
|
||||
* 日志文件的组成形式应为appName-年-月-日.log
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/10/28 15:53
|
||||
*/
|
||||
@Override
|
||||
public void recordLog(LogRecordDTO logRecordDTO) {
|
||||
|
||||
if (logRecordDTO == null) {
|
||||
return;
|
||||
}
|
||||
if (logRecordDTO == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 输出日志
|
||||
recordLogByList(CollectionUtil.list(false, logRecordDTO));
|
||||
}
|
||||
// 输出日志
|
||||
recordLogByList(CollectionUtil.list(false, logRecordDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量输出日志
|
||||
*
|
||||
* @param list 待输出日志列表
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 下午2:59
|
||||
*/
|
||||
@Override
|
||||
public void recordLogByList(List<LogRecordDTO> list) {
|
||||
/**
|
||||
* 批量输出日志
|
||||
*
|
||||
* @param list 待输出日志列表
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 下午2:59
|
||||
*/
|
||||
@Override
|
||||
public void recordLogByList(List<LogRecordDTO> list) {
|
||||
|
||||
if (ObjectUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
if (ObjectUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取appName
|
||||
String appName = list.get(0).getAppName();
|
||||
if (StrUtil.isBlank(appName)) {
|
||||
appName = LogFileConstants.DEFAULT_LOG_FILE_NAME;
|
||||
}
|
||||
// 获取appName
|
||||
String appName = list.get(0).getAppName();
|
||||
if (StrUtil.isBlank(appName)) {
|
||||
appName = LogFileConstants.DEFAULT_LOG_FILE_NAME;
|
||||
}
|
||||
|
||||
// 获取日志记录的日期
|
||||
Date dateTime = list.get(0).getDateTime();
|
||||
if (dateTime == null) {
|
||||
dateTime = new Date();
|
||||
}
|
||||
String dateStr = DateUtil.formatDate(dateTime);
|
||||
// 获取日志记录的日期
|
||||
Date dateTime = list.get(0).getDateTime();
|
||||
if (dateTime == null) {
|
||||
dateTime = new Date();
|
||||
}
|
||||
String dateStr = DateUtil.formatDate(dateTime);
|
||||
|
||||
// 拼接文件名
|
||||
String fileName = appName + FILE_CONTRACT_SYMBOL + dateStr + FILE_SUFFIX;
|
||||
// 拼接文件名
|
||||
String fileName = appName + FILE_CONTRACT_SYMBOL + dateStr + FILE_SUFFIX;
|
||||
|
||||
// 文件绝对路径生成,带文件名的完整路径
|
||||
String fileAbsolutePath = fileSavePath + File.separator + fileName;
|
||||
// 文件绝对路径生成,带文件名的完整路径
|
||||
String fileAbsolutePath = fileSavePath + File.separator + fileName;
|
||||
|
||||
// 判断文件是否存在,不存在则创建
|
||||
boolean existFlag = FileUtil.exist(fileAbsolutePath);
|
||||
if (!existFlag) {
|
||||
FileUtil.touch(fileAbsolutePath);
|
||||
}
|
||||
// 判断文件是否存在,不存在则创建
|
||||
boolean existFlag = FileUtil.exist(fileAbsolutePath);
|
||||
if (!existFlag) {
|
||||
FileUtil.touch(fileAbsolutePath);
|
||||
}
|
||||
|
||||
// 将对象转换成JSON输出
|
||||
List<String> outList = new ArrayList<>();
|
||||
for (LogRecordDTO recordDTO : list) {
|
||||
outList.add(JSON.toJSONString(recordDTO));
|
||||
}
|
||||
// 将对象转换成JSON输出
|
||||
List<String> outList = new ArrayList<>();
|
||||
for (LogRecordDTO recordDTO : list) {
|
||||
outList.add(JSON.toJSONString(recordDTO));
|
||||
}
|
||||
|
||||
// 追加日志内容
|
||||
FileUtil.appendLines(outList, fileAbsolutePath, StandardCharsets.UTF_8);
|
||||
}
|
||||
// 追加日志内容
|
||||
FileUtil.appendLines(outList, fileAbsolutePath, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLogAsync(LogRecordDTO logRecordDTO) {
|
||||
logManagerThreadPool.executeLog(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
logRefreshManager.putLog(logRecordDTO);
|
||||
}
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void recordLogAsync(LogRecordDTO logRecordDTO) {
|
||||
logManagerThreadPool.executeLog(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
logRefreshManager.putLog(logRecordDTO);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志刷新管理器
|
||||
* <p>
|
||||
* 该类暂存所有将要写出到磁盘的日志,使用内存缓冲区减少对磁盘IO的操作
|
||||
* <p>
|
||||
* 该类维护一个最大日志数和一个刷新日志间隔,满足任意一个条件即可触发从内存写出日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:05
|
||||
*/
|
||||
class LogRefreshManager extends Thread {
|
||||
/**
|
||||
* 日志刷新管理器
|
||||
* <p>
|
||||
* 该类暂存所有将要写出到磁盘的日志,使用内存缓冲区减少对磁盘IO的操作
|
||||
* <p>
|
||||
* 该类维护一个最大日志数和一个刷新日志间隔,满足任意一个条件即可触发从内存写出日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:05
|
||||
*/
|
||||
class LogRefreshManager extends Thread {
|
||||
|
||||
/**
|
||||
* Hutool日志对象
|
||||
*/
|
||||
private final Log log = LogFactory.get();
|
||||
/**
|
||||
* Hutool日志对象
|
||||
*/
|
||||
private final Log log = LogFactory.get();
|
||||
|
||||
/**
|
||||
* 刷新日志间隔(默认3秒),单位毫秒
|
||||
*/
|
||||
private final long sleepTime;
|
||||
/**
|
||||
* 刷新日志间隔(默认3秒),单位毫秒
|
||||
*/
|
||||
private final long sleepTime;
|
||||
|
||||
/**
|
||||
* 满足多少条就强制刷新一次(默认300条),该值只是一个大约值,实际记录并不会一定等于该值(可能会大于该值,不可能小于该值)
|
||||
*/
|
||||
private final int maxCount;
|
||||
/**
|
||||
* 满足多少条就强制刷新一次(默认300条),该值只是一个大约值,实际记录并不会一定等于该值(可能会大于该值,不可能小于该值)
|
||||
*/
|
||||
private final int maxCount;
|
||||
|
||||
/**
|
||||
* 刷新数据时间标志,每次刷新都记录当前的时间戳,方便定时刷新准确判断上次刷新和本次刷新的时间间隔
|
||||
*/
|
||||
private final AtomicLong refreshMark = new AtomicLong();
|
||||
/**
|
||||
* 刷新数据时间标志,每次刷新都记录当前的时间戳,方便定时刷新准确判断上次刷新和本次刷新的时间间隔
|
||||
*/
|
||||
private final AtomicLong refreshMark = new AtomicLong();
|
||||
|
||||
public LogRefreshManager() {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
public LogRefreshManager() {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
|
||||
public LogRefreshManager(long sleepTime) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
public LogRefreshManager(long sleepTime) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = 300;
|
||||
}
|
||||
|
||||
public LogRefreshManager(int maxCount) {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
public LogRefreshManager(int maxCount) {
|
||||
this.sleepTime = 3000;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
public LogRefreshManager(long sleepTime, int maxCount) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
public LogRefreshManager(long sleepTime, int maxCount) {
|
||||
this.sleepTime = sleepTime;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 未处理日志的消息队列
|
||||
*/
|
||||
private final Queue<LogRecordDTO> queue = new ConcurrentLinkedQueue<>();
|
||||
/**
|
||||
* 未处理日志的消息队列
|
||||
*/
|
||||
private final Queue<LogRecordDTO> queue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/**
|
||||
* 消息总数,队列的size方法会遍历一遍队列,所以自己维护大小
|
||||
*/
|
||||
public AtomicInteger count = new AtomicInteger(0);
|
||||
/**
|
||||
* 消息总数,队列的size方法会遍历一遍队列,所以自己维护大小
|
||||
*/
|
||||
public AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* 往队列内新增一条日志数据
|
||||
*
|
||||
* @param logRecordDTO 日志对象
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 14:59
|
||||
*/
|
||||
public void putLog(LogRecordDTO logRecordDTO) {
|
||||
/**
|
||||
* 往队列内新增一条日志数据
|
||||
*
|
||||
* @param logRecordDTO 日志对象
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 14:59
|
||||
*/
|
||||
public void putLog(LogRecordDTO logRecordDTO) {
|
||||
|
||||
int queueDataCount = count.get();
|
||||
int queueDataCount = count.get();
|
||||
|
||||
// 如果是第一条消息,刷新一次refreshMark
|
||||
if (queueDataCount == 0) {
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
}
|
||||
// 如果是第一条消息,刷新一次refreshMark
|
||||
if (queueDataCount == 0) {
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
// 如果后续写入磁盘的操作有异常(磁盘满了),为了防止日志刷不出去导致OOM,内存中最大只保留maxCount数一倍的日志,后续日志将丢弃
|
||||
if (queueDataCount >= (maxCount * 2)) {
|
||||
return;
|
||||
}
|
||||
// 如果后续写入磁盘的操作有异常(磁盘满了),为了防止日志刷不出去导致OOM,内存中最大只保留maxCount数一倍的日志,后续日志将丢弃
|
||||
if (queueDataCount >= (maxCount * 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue.offer(logRecordDTO);
|
||||
count.incrementAndGet();
|
||||
}
|
||||
queue.offer(logRecordDTO);
|
||||
count.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:48
|
||||
*/
|
||||
private void refresh() {
|
||||
// 让睡眠线程本次不要再调本方法,睡眠至下次看refreshMark的值再决定要不要调用本方法
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
/**
|
||||
* 刷新日志到磁盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:48
|
||||
*/
|
||||
private void refresh() {
|
||||
// 让睡眠线程本次不要再调本方法,睡眠至下次看refreshMark的值再决定要不要调用本方法
|
||||
refreshMark.getAndSet(System.currentTimeMillis());
|
||||
|
||||
// 获取总数
|
||||
int num = count.getAndSet(0);
|
||||
// 获取总数
|
||||
int num = count.getAndSet(0);
|
||||
|
||||
// 缓冲队列中所有的数据
|
||||
List<LogRecordDTO> cacheAll = new ArrayList<>(num);
|
||||
// 缓冲队列中所有的数据
|
||||
List<LogRecordDTO> cacheAll = new ArrayList<>(num);
|
||||
|
||||
try {
|
||||
// 在队列中读取num条数据,放入list
|
||||
for (int i = 0; i < num; i++) {
|
||||
LogRecordDTO item = queue.poll();
|
||||
if (null == item) {
|
||||
break;
|
||||
}
|
||||
cacheAll.add(item);
|
||||
}
|
||||
try {
|
||||
// 在队列中读取num条数据,放入list
|
||||
for (int i = 0; i < num; i++) {
|
||||
LogRecordDTO item = queue.poll();
|
||||
if (null == item) {
|
||||
break;
|
||||
}
|
||||
cacheAll.add(item);
|
||||
}
|
||||
|
||||
// 调用方法刷新到磁盘
|
||||
recordLogByList(cacheAll);
|
||||
// 调用方法刷新到磁盘
|
||||
recordLogByList(cacheAll);
|
||||
|
||||
} catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
|
||||
// 有异常把日志刷回队列,不要丢掉(这里可能会导致日志顺序错乱)
|
||||
for (LogRecordDTO recordDTO : cacheAll) {
|
||||
queue.offer(recordDTO);
|
||||
}
|
||||
// 有异常把日志刷回队列,不要丢掉(这里可能会导致日志顺序错乱)
|
||||
for (LogRecordDTO recordDTO : cacheAll) {
|
||||
queue.offer(recordDTO);
|
||||
}
|
||||
|
||||
// 打印日志
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
// 打印日志
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志数据定时执行器
|
||||
* <p>
|
||||
* 用于定时检测日志数据是否可以写入数据
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:57
|
||||
*/
|
||||
private void timing() {
|
||||
try {
|
||||
// 如果是激活状态,且消息数大于零,且符合上次调用refresh方法到目前时间的间隔,那就调用一次refresh方法
|
||||
if ((refreshMark.get() + sleepTime) <= System.currentTimeMillis() && count.get() > 0) {
|
||||
refresh();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 日志数据定时执行器
|
||||
* <p>
|
||||
* 用于定时检测日志数据是否可以写入数据
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/10/31 15:57
|
||||
*/
|
||||
private void timing() {
|
||||
try {
|
||||
// 如果是激活状态,且消息数大于零,且符合上次调用refresh方法到目前时间的间隔,那就调用一次refresh方法
|
||||
if ((refreshMark.get() + sleepTime) <= System.currentTimeMillis() && count.get() > 0) {
|
||||
refresh();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志数据监听器
|
||||
* <p>
|
||||
* 用于监听日志消息队列,达到设定的数就开始执行刷入硬盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 9:32
|
||||
*/
|
||||
private void listener() {
|
||||
try {
|
||||
// 判断如果队列里面的数据大于等于设定的最大消息数,就调用refresh方法刷新一次数据
|
||||
if (count.get() >= maxCount) {
|
||||
refresh();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 日志数据监听器
|
||||
* <p>
|
||||
* 用于监听日志消息队列,达到设定的数就开始执行刷入硬盘的操作
|
||||
*
|
||||
* @author majianguo
|
||||
* @date 2020/11/2 9:32
|
||||
*/
|
||||
private void listener() {
|
||||
try {
|
||||
// 判断如果队列里面的数据大于等于设定的最大消息数,就调用refresh方法刷新一次数据
|
||||
if (count.get() >= maxCount) {
|
||||
refresh();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
// 消息监听器
|
||||
listener();
|
||||
// 定时任务监听器
|
||||
timing();
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
// 消息监听器
|
||||
listener();
|
||||
// 定时任务监听器
|
||||
timing();
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,46 +22,46 @@ import org.springframework.context.annotation.Configuration;
|
|||
@Configuration
|
||||
public class GunsLogAutoConfiguration {
|
||||
|
||||
public static final String SYS_LOG_PREFIX = "sys-log";
|
||||
public static final String SYS_LOG_TYPE_DEFAULT = "db";
|
||||
public static final String SYS_LOG_PREFIX = "sys-log";
|
||||
public static final String SYS_LOG_TYPE_DEFAULT = "db";
|
||||
|
||||
/**
|
||||
* 系统日志的的配置
|
||||
*
|
||||
* @author liuhanqing
|
||||
* @date 2020/12/20 14:17
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = SYS_LOG_PREFIX)
|
||||
public SysLogProperties sysLogProperties() {
|
||||
return new SysLogProperties();
|
||||
}
|
||||
/**
|
||||
* 系统日志的的配置
|
||||
*
|
||||
* @author liuhanqing
|
||||
* @date 2020/12/20 14:17
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = SYS_LOG_PREFIX)
|
||||
public SysLogProperties sysLogProperties() {
|
||||
return new SysLogProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每个请求接口记录日志的AOP
|
||||
* 根据配置文件初始化日志记录器
|
||||
* 日志存储类型:db-数据库,file-文件,默认存储在数据库中
|
||||
*
|
||||
* @author liuhanqing
|
||||
* @date 2020/12/20 13:02
|
||||
*/
|
||||
@Bean
|
||||
public RequestApiLogRecordAop requestApiLogRecordAop(SysLogProperties sysLogProperties) {
|
||||
if (StrUtil.isBlank(sysLogProperties.getType())) {
|
||||
return new RequestApiLogRecordAop(new DbLogRecordServiceImpl(new LogManagerThreadPool(), new SysLogServiceImpl()));
|
||||
}else{
|
||||
if(!SYS_LOG_TYPE_DEFAULT.equals(sysLogProperties.getType())){
|
||||
//修改为从sys_config中获取日志存储位置
|
||||
String fileSavePath = "";
|
||||
if (SystemUtil.getOsInfo().isWindows()) {
|
||||
fileSavePath = LogConfigExpander.getLogFileSavePathWindows();
|
||||
}else{
|
||||
fileSavePath = LogConfigExpander.getLogFileSavePathLinux();
|
||||
}
|
||||
//sysLogProperties.getFileSavePath()
|
||||
return new RequestApiLogRecordAop(new FileLogRecordServiceImpl(fileSavePath, new LogManagerThreadPool()));
|
||||
}
|
||||
}
|
||||
return new RequestApiLogRecordAop(new DbLogRecordServiceImpl(new LogManagerThreadPool(), new SysLogServiceImpl()));
|
||||
}
|
||||
/**
|
||||
* 每个请求接口记录日志的AOP
|
||||
* 根据配置文件初始化日志记录器
|
||||
* 日志存储类型:db-数据库,file-文件,默认存储在数据库中
|
||||
*
|
||||
* @author liuhanqing
|
||||
* @date 2020/12/20 13:02
|
||||
*/
|
||||
@Bean
|
||||
public RequestApiLogRecordAop requestApiLogRecordAop(SysLogProperties sysLogProperties) {
|
||||
if (StrUtil.isBlank(sysLogProperties.getType())) {
|
||||
return new RequestApiLogRecordAop(new DbLogRecordServiceImpl(new LogManagerThreadPool(), new SysLogServiceImpl()));
|
||||
} else {
|
||||
if (!SYS_LOG_TYPE_DEFAULT.equals(sysLogProperties.getType())) {
|
||||
//修改为从sys_config中获取日志存储位置
|
||||
String fileSavePath = "";
|
||||
if (SystemUtil.getOsInfo().isWindows()) {
|
||||
fileSavePath = LogConfigExpander.getLogFileSavePathWindows();
|
||||
} else {
|
||||
fileSavePath = LogConfigExpander.getLogFileSavePathLinux();
|
||||
}
|
||||
//sysLogProperties.getFileSavePath()
|
||||
return new RequestApiLogRecordAop(new FileLogRecordServiceImpl(fileSavePath, new LogManagerThreadPool()));
|
||||
}
|
||||
}
|
||||
return new RequestApiLogRecordAop(new DbLogRecordServiceImpl(new LogManagerThreadPool(), new SysLogServiceImpl()));
|
||||
}
|
||||
}
|
|
@ -330,23 +330,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
return this.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID获取用户
|
||||
*
|
||||
* @param userId
|
||||
* @return java.lang.String
|
||||
* @author wangle
|
||||
* @date 2020/12/17 18:11
|
||||
*/
|
||||
@Override
|
||||
public String getNameByUserId(Long userId) {
|
||||
SysUser sysUser = this.getById(userId);
|
||||
if (ObjectUtil.isNull(sysUser)) {
|
||||
throw new SystemModularException(SysUserExceptionEnum.USER_NOT_EXIST);
|
||||
}
|
||||
return sysUser.getRealName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserLoginInfoDTO getUserLoginInfo(String account) {
|
||||
UserLoginInfoDTO userLoginInfoDTO = new UserLoginInfoDTO();
|
||||
|
|
Loading…
Reference in New Issue