【log】整理log模块引用,根据配置文件初始化不同的日记记录器

pull/3/head
liuhq 2020-12-20 15:16:07 +08:00 committed by fengshuonan
parent 983c909aad
commit ac94d92218
7 changed files with 659 additions and 557 deletions

View File

@ -0,0 +1,22 @@
package cn.stylefeng.roses.kernel.log.api.pojo.log;
import lombok.Data;
/**
*
*
* @author liuhanqing
* @date 2020-12-20 13:53
**/
@Data
public class SysLogProperties {
/**
* db-file-
*/
private String type = "db";
/**
* file
*/
private String fileSavePath = "_sys_log";
}

View File

@ -16,6 +16,7 @@ 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;
@ -30,130 +31,131 @@ 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 AOPkeyv
* @param result AOP
* @author fengshuonan
* @date 2020/10/28 17:38
*/
private void recordLog(Map<String, Object> params, Object result) {
/**
*
*
* @param params AOPkeyv
* @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, Vkeyv
* @author majianguo
* @date 2020/11/2 10:40
*/
private Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {
/**
* AOP
*
* @param joinPoint joinPoint
* @return K, Vkeyv
* @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;
}
}
}

View File

@ -14,6 +14,7 @@ import cn.stylefeng.roses.kernel.log.db.entity.SysLog;
import cn.stylefeng.roses.kernel.log.db.service.SysLogService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
@ -27,258 +28,260 @@ import java.util.stream.Collectors;
* @author luojie
* @date 2020/11/2 15:50
*/
@Service
//@Service
public class DbLogRecordServiceImpl implements LogRecordApi {
/**
* Hutool
*/
private final Log log = LogFactory.get();
/**
* 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, 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) {
this.logManagerThreadPool = logManagerThreadPool;
this.sysLogService = sysLogService;
this.logRefreshManager = new LogRefreshManager();
this.logRefreshManager.start();
}
@Override
public void recordLog(LogRecordDTO logRecordDTO) {
if (logRecordDTO == null) {
return;
}
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();
}
// 输出日志
recordLogByList(CollectionUtil.list(false, logRecordDTO));
}
@Override
public void recordLog(LogRecordDTO logRecordDTO) {
if (logRecordDTO == null) {
return;
}
@Override
public void recordLogByList(List<LogRecordDTO> logRecords) {
// 输出日志
recordLogByList(CollectionUtil.list(false, logRecordDTO));
}
if (ObjectUtil.isEmpty(logRecords)) {
return;
}
@Override
public void recordLogByList(List<LogRecordDTO> logRecords) {
List<SysLog> sysLogList = logRecords.stream().map(logRecordDTO -> {
SysLog sysLog = new SysLog();
// 复制logRecordDTO对象属性到sysLog
BeanUtil.copyProperties(logRecordDTO, sysLog);
if (ObjectUtil.isEmpty(logRecords)) {
return;
}
// 日志名称为空的话则获取默认日志名称
if (StrUtil.isEmpty(sysLog.getLogName())) {
sysLog.setLogName(LogConstants.LOG_DEFAULT_NAME);
}
List<SysLog> sysLogList = logRecords.stream().map(logRecordDTO -> {
SysLog sysLog = new SysLog();
// 复制logRecordDTO对象属性到sysLog
BeanUtil.copyProperties(logRecordDTO, sysLog);
// 服务名称为空的话则获取默认服务名称
if (StrUtil.isEmpty(sysLog.getAppName())) {
sysLog.setAppName(LogConstants.LOG_DEFAULT_APP_NAME);
}
// 日志名称为空的话则获取默认日志名称
if (StrUtil.isEmpty(sysLog.getLogName())) {
sysLog.setLogName(LogConstants.LOG_DEFAULT_NAME);
}
// 如果操作时间为空的话插入当前时间
if (sysLog.getCreateTime() == null) {
sysLog.setCreateTime(new Date());
}
// 服务名称为空的话则获取默认服务名称
if (StrUtil.isEmpty(sysLog.getAppName())) {
sysLog.setAppName(LogConstants.LOG_DEFAULT_APP_NAME);
}
return sysLog;
}).collect(Collectors.toList());
// 如果操作时间为空的话插入当前时间
if (sysLog.getCreateTime() == null) {
sysLog.setCreateTime(new Date());
}
// 插入到数据库
sysLogService.saveBatch(sysLogList);
}
return sysLog;
}).collect(Collectors.toList());
@Override
public void recordLogAsync(LogRecordDTO logRecordDTO) {
logManagerThreadPool.executeLog(new TimerTask() {
@Override
public void run() {
logRefreshManager.putLog(logRecordDTO);
}
});
}
// 插入到数据库
sysLogService.saveBatch(sysLogList);
}
/**
*
* <p>
* 使IO
* <p>
*
*
* @author majianguo
* @date 2020/10/31 15:05
*/
class LogRefreshManager extends Thread {
@Override
public void recordLogAsync(LogRecordDTO logRecordDTO) {
logManagerThreadPool.executeLog(new TimerTask() {
@Override
public void run() {
logRefreshManager.putLog(logRecordDTO);
}
});
}
/**
* (3),
*/
private final long sleepTime;
/**
*
* <p>
* 使IO
* <p>
*
*
* @author majianguo
* @date 2020/10/31 15:05
*/
class LogRefreshManager extends Thread {
/**
* 300,
*/
private final int maxCount;
/**
* (3),
*/
private final long sleepTime;
/**
* ,便
*/
private final AtomicLong refreshMark = new AtomicLong();
/**
* 300,
*/
private final int maxCount;
public LogRefreshManager() {
this.sleepTime = 3000;
this.maxCount = 300;
}
/**
* ,便
*/
private final AtomicLong refreshMark = new AtomicLong();
public LogRefreshManager(long sleepTime) {
this.sleepTime = sleepTime;
this.maxCount = 300;
}
public LogRefreshManager() {
this.sleepTime = 3000;
this.maxCount = 300;
}
public LogRefreshManager(int maxCount) {
this.sleepTime = 3000;
this.maxCount = maxCount;
}
public LogRefreshManager(long sleepTime) {
this.sleepTime = sleepTime;
this.maxCount = 300;
}
public LogRefreshManager(long sleepTime, int maxCount) {
this.sleepTime = sleepTime;
this.maxCount = maxCount;
}
public LogRefreshManager(int maxCount) {
this.sleepTime = 3000;
this.maxCount = maxCount;
}
/**
*
*/
private final Queue<LogRecordDTO> queue = new ConcurrentLinkedQueue<>();
public LogRefreshManager(long sleepTime, int maxCount) {
this.sleepTime = sleepTime;
this.maxCount = maxCount;
}
/**
* ,size
*/
public AtomicInteger count = new AtomicInteger(0);
/**
*
*/
private final Queue<LogRecordDTO> queue = new ConcurrentLinkedQueue<>();
/**
*
*
* @param logRecordDTO
* @author majianguo
* @date 2020/10/31 14:59
*/
public void putLog(LogRecordDTO logRecordDTO) {
/**
* ,size
*/
public AtomicInteger count = new AtomicInteger(0);
int queueDataCount = count.get();
/**
*
*
* @param logRecordDTO
* @author majianguo
* @date 2020/10/31 14:59
*/
public void putLog(LogRecordDTO logRecordDTO) {
// 如果是第一条消息刷新一次refreshMark
if (queueDataCount == 0) {
refreshMark.getAndSet(System.currentTimeMillis());
}
int queueDataCount = count.get();
// 如果后续写入磁盘的操作有异常(磁盘满了)为了防止日志刷不出去导致OOM,内存中最大只保留maxCount数一倍的日志后续日志将丢弃
if (queueDataCount >= (maxCount * 2)) {
return;
}
// 如果是第一条消息刷新一次refreshMark
if (queueDataCount == 0) {
refreshMark.getAndSet(System.currentTimeMillis());
}
queue.offer(logRecordDTO);
count.incrementAndGet();
}
// 如果后续写入磁盘的操作有异常(磁盘满了)为了防止日志刷不出去导致OOM,内存中最大只保留maxCount数一倍的日志后续日志将丢弃
if (queueDataCount >= (maxCount * 2)) {
return;
}
/**
*
*
* @author majianguo
* @date 2020/10/31 15:48
*/
private void refresh() {
queue.offer(logRecordDTO);
count.incrementAndGet();
}
// 让睡眠线程本次不要再调本方法睡眠至下次看refreshMark的值再决定要不要调用本方法
refreshMark.getAndSet(System.currentTimeMillis());
/**
*
*
* @author majianguo
* @date 2020/10/31 15:48
*/
private void refresh() {
// 获取总数
int num = count.getAndSet(0);
// 让睡眠线程本次不要再调本方法睡眠至下次看refreshMark的值再决定要不要调用本方法
refreshMark.getAndSet(System.currentTimeMillis());
// 再队列中读取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);
}
// 获取总数
int num = count.getAndSet(0);
// 调用方法刷新到磁盘
recordLogByList(cacheAll);
}
// 再队列中读取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);
}
/**
*
* <p>
*
*
* @author majianguo
* @date 2020/10/31 15:57
*/
private void timing() {
long currentTimeMillis = System.currentTimeMillis();
// 调用方法刷新到磁盘
recordLogByList(cacheAll);
}
// 如果是激活状态且消息数大于零且符合上次调用refresh方法到目前时间的间隔那就调用一次refresh方法
if ((refreshMark.get() + sleepTime) <= currentTimeMillis && count.get() > 0) {
refresh();
}
}
/**
*
* <p>
*
*
* @author majianguo
* @date 2020/10/31 15:57
*/
private void timing() {
long currentTimeMillis = System.currentTimeMillis();
/**
*
* <p>
*
*
* @author majianguo
* @date 2020/11/2 9:32
*/
private void listener() {
// 判断如果队列里面的数据大于等于设定的最大消息数就调用refresh方法刷新一次数据
if (count.get() >= maxCount) {
refresh();
}
}
// 如果是激活状态且消息数大于零且符合上次调用refresh方法到目前时间的间隔那就调用一次refresh方法
if ((refreshMark.get() + sleepTime) <= currentTimeMillis && count.get() > 0) {
refresh();
}
}
@Override
@SuppressWarnings("InfiniteLoopStatement")
public void run() {
try {
for (; ; ) {
// 消息监听器
listener();
// 定时任务监听器
timing();
TimeUnit.MILLISECONDS.sleep(10);
}
} catch (InterruptedException e) {
/**
*
* <p>
*
*
* @author majianguo
* @date 2020/11/2 9:32
*/
private void listener() {
// 判断如果队列里面的数据大于等于设定的最大消息数就调用refresh方法刷新一次数据
if (count.get() >= maxCount) {
refresh();
}
}
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());
}
}
}
}

View File

@ -31,299 +31,299 @@ import static cn.stylefeng.roses.kernel.log.api.constants.LogFileConstants.FILE_
* @author fengshuonan
* @date 2020/10/28 14:52
*/
@Service
//@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());
}
}
}
}
}

View File

@ -37,6 +37,11 @@
<artifactId>log-sdk-db</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>log-sdk-file</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>

View File

@ -1,9 +1,20 @@
package cn.stylefeng.roses.kernel.log.starter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.SystemUtil;
import cn.stylefeng.roses.kernel.log.api.expander.LogConfigExpander;
import cn.stylefeng.roses.kernel.log.api.pojo.log.SysLogProperties;
import cn.stylefeng.roses.kernel.log.api.threadpool.LogManagerThreadPool;
import cn.stylefeng.roses.kernel.log.db.DbLogRecordServiceImpl;
import cn.stylefeng.roses.kernel.log.db.service.impl.SysLogServiceImpl;
import cn.stylefeng.roses.kernel.log.file.FileLogRecordServiceImpl;
import cn.stylefeng.roses.kernel.log.modular.requestapi.aop.RequestApiLogRecordAop;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
*
*
* @author fengshuonan
* @date 2020/12/1 17:12
@ -11,4 +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";
/**
*
*
* @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()));
}
}

View File

@ -330,6 +330,23 @@ 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();