LogUtils.java 2.3 KB
package com.yoho.search.common.utils;


import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

/**
 * Created by ginozhang on 2017/3/30.
 */
public final class LogUtils {

    @SuppressWarnings("static-access")
	private static final Logger ROOT_LOGGER = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);

    private static final Map<String, Level> sourceLevelMap = new ConcurrentHashMap<>();

    // 最大支持打开五分钟
    private static final int MAX_EXPIRE_SECONDS = 300;

    // 默认打开一分钟
    private static final int DEFAULT_EXPIRE_SECONDS = 60;

    private static final ScheduledExecutorService POOL = Executors.newScheduledThreadPool(1);

    public static synchronized String changeLogLevel(String loggerName, String levelStr, int expireSeconds) {
        // 1. 判断参数是否合法 以及是否需要变更日志级别
        final Level level = Level.toLevel(levelStr);
        if (level == null) {
            return "The level string [" + levelStr + "] is invalid.";
        }

        final Logger logger = (Logger) LoggerFactory.getLogger(loggerName);
        if (logger == null) {
            return "The logger [" + loggerName + "] is not found.";
        }

        final Level srcLevel = logger.getLevel() != null ? logger.getLevel() : ROOT_LOGGER.getLevel();
        if (level == srcLevel) {
            return "The logger [" + loggerName + "] is [" + levelStr + "] already.";
        }

        // 2. 将该logger原始的日志级别放入到map缓存 用于恢复
        sourceLevelMap.computeIfAbsent(loggerName, name -> srcLevel);

        // 3. 启动异步线程确保在指定时间之后失效
        long delay = expireSeconds > 0 && expireSeconds < MAX_EXPIRE_SECONDS ? expireSeconds : DEFAULT_EXPIRE_SECONDS;
        POOL.schedule(() -> logger.setLevel(sourceLevelMap.getOrDefault(loggerName, srcLevel)), delay, TimeUnit.SECONDS);

        // 4. 变更日志级别
        logger.setLevel(level);
        return "The logger [" + loggerName + "] has changed log level from [" + srcLevel + "] to [" + level + "] succeed.";
    }
}