LogLocal.java 3.97 KB
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;

/**
 * 当前线程日志编写
 *
 * @author 颜佐光
 */
@Component
public class LogLocal implements ThreadNext.Next, InitializingBean {
    /**
     * 一个请求最多保留60分钟
     */
    public static final int CLEAR_CACHE = 60 * 60;
    /**
     * 超时状态
     */
    public static final String MAX_TIME = "MAX_TIME";
    public static final String MAX_TIME_NAME = "执行超时";
    /**
     * 日志基础
     */
    private final LogBase logBase;
    private final CloudConfig cloudConfig;
    private final List<LogFilter> logFilters;
    private final LogCountTime logCountTime;
    /**
     * 缓存队列
     */
    protected volatile MemoryCache<Timeout<LogInfoVo>> cache = new MemoryCache<>(CLEAR_CACHE);

    public LogLocal(LogBase logBase, CloudConfig cloudConfig, List<LogFilter> 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<LogInfoVo> time = new Timeout<>(log);
        cache.put(log.getLogId(), time);
    }

    /**
     * 写入状态
     *
     * @param log 日志对象
     */
    public void result(LogInfoVo log) {
        if (log == null || StringHelper.isEmpty(log.getLogId())) {
            return;
        }
        // 日志请求不记录,防止死循环递归
        boolean isLog = isLog(log.getTag(), log.getUrl());
        // 全路径
        String fullUrl = String.format("%s:%s", tag, url);
        // 执行时间
        long time = System.currentTimeMillis() - log.getStart();
        // 记录请求时间
        logCountTime.finish(log);
        Timeout<LogInfoVo> timeout;
        // 判断是否延时结果
        boolean isMaxTime = StringHelper.compare(status, MAX_TIME);
        if (isMaxTime) {
            timeout = cache.get(log.getLogId());
        } else {
            timeout = cache.remove(log.getLogId());
        }
        logBase.addLog(log);
    }


    /**
     * 是否属于日志服务
     *
     * @param keys 是否需要写入
     * @return 是否属于日志服务
     */
    public boolean isLog(String... keys) {
        List<String> 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() {
        Collection<Timeout<LogInfoVo>> values = cache.getValues();
        for (Timeout<LogInfoVo> timeout : values) {
            if (timeout == null) {
                continue;
            }
            // 判断是否达到超时时间
            if (timeout.isMaxTime(this.cloudConfig.getLogTimeMax(), this.cloudConfig.getLogTimeSplit())) {
                this.result(timeout.getData());
            }
        }
        return true;
    }

    /**
     * 沉睡时间
     *
     * @return 下次执行时间
     */
    @Override
    public int getNextTime() {
        return 1000;
    }
}