package com.yanzuoguang.log; import com.yanzuoguang.util.cache.MemoryCache; import com.yanzuoguang.util.helper.StringHelper; import com.yanzuoguang.util.thread.ThreadNext; import com.yanzuoguang.util.vo.CloudConfig; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import static com.yanzuoguang.log.LogInfoVo.STATUS_WAIT; /** * 当前线程日志编写 * * @author 颜佐光 */ @Component public class LogLocal implements ThreadNext.Next, InitializingBean { private final LogBase logBase; private final CloudConfig cloudConfig; private final List logFilters; private final LogCountTime logCountTime; /** * 缓存队列,一个请求最多保留60分钟 */ public static final int CLEAR_CACHE = 60 * 60; protected volatile MemoryCache> cache = new MemoryCache<>(CLEAR_CACHE); public LogLocal(LogBase logBase, CloudConfig cloudConfig, List logFilters, LogCountTime logCountTime) { this.logBase = logBase; this.cloudConfig = cloudConfig; this.logFilters = logFilters; this.logCountTime = logCountTime; } @Override public void afterPropertiesSet() { ThreadNext.start(this, "save log error"); } /** * 开始记录日志 * * @param log 日志对象 */ public void startLog(LogInfoVo log) { // 声明超时对象 Timeout time = new Timeout<>(log); cache.put(log.getLogId(), time); } /** * 写入状态 * * @param log 日志对象 */ public void result(LogInfoVo log) { // 日志不存在或已处理 if (log == null || StringHelper.isEmpty(log.getLogId()) || cache.get(log.getLogId()) == null) { return; } // 获取是否已处理 boolean isWait = log.getStatus() == STATUS_WAIT; if (!isWait) { cache.remove(log.getLogId()); } // 获取当前使用时间 long useTime; if (log.getEnd() == 0) { useTime = System.currentTimeMillis() - log.getStart(); log.setUseTime(useTime); } else { useTime = log.getUseTime(); } // 获取当前请求的级别 int level = 0; if (useTime > cloudConfig.getLockTime()) { level = -1; } else { // 这里需要时间按照升序排序 List times = cloudConfig.getLogTimeMax(); for (Integer time : times) { if (time < useTime) { level = time; } } } log.setLevel(level); // 记录请求时间 logCountTime.finish(log); // 日志详情请求不记录,防止死循环递归 boolean isLog = isLog(log.getTag(), log.getUrl()); // 并判断是否达到记录的时间标准 if (isLog && useTime >= this.cloudConfig.getLogWriteTime()) { logBase.addLog(log); } } /** * 是否属于日志服务 * * @param keys 是否需要写入 * @return 是否属于日志服务 */ public boolean isLog(String... keys) { List list = new ArrayList<>(); list.add(this.cloudConfig.getApplicationName()); list.addAll(Arrays.asList(keys)); for (LogFilter k : logFilters) { if (k.logExpect(list)) { return true; } } for (LogFilter k : logFilters) { if (k.logFilter(list)) { return false; } } return true; } /** * 执行下一个函数,出现异常会继续执行 * * @return 是否继续执行 */ @Override public boolean next() { // 正在处理的任务 List notHandles = new ArrayList<>(); Collection> values = cache.getValues(); for (Timeout timeout : values) { if (timeout == null) { continue; } LogInfoVo log = timeout.getData(); boolean isLog = isLog(log.getTag(), log.getUrl()); if (isLog) { notHandles.add(log); } // 判断是否达到超时时间 if (timeout.isMaxTime(this.cloudConfig.getLockTime(), this.cloudConfig.getLogTimeSplit())) { this.result(log); } } // 通知正在处理中的任务队列 logBase.notifyNotHandle(notHandles); return true; } /** * 沉睡时间 * * @return 下次执行时间 */ @Override public int getNextTime() { return 1000; } }