logback運行時動態建立日誌文件

package com.example.demo.config;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;


@Component
public class LoggerBuilder {
    private ConcurrentHashMap<String, Logger> container = new ConcurrentHashMap<>();

    public Logger getLogger(String name,Class<?> clazz) {
        Logger logger = container.get(name);
        if (logger != null) {
            return logger;
        }
        synchronized (LoggerBuilder.class) {
            logger = container.get(name);
            if (logger != null) {
                return logger;
            }
            logger = build(name,clazz);
            container.put(name, logger);
        }
        return logger;
    }

    private Logger build(String name,Class<?> clazz) {
        RollingFileAppender errorAppender = new AppenderFactory().createRollingFileAppender(name, Level.ERROR);
        RollingFileAppender infoAppender = new AppenderFactory().createRollingFileAppender(name, Level.INFO);
        ConsoleAppender consoleAppender = new AppenderFactory().createConsoleAppender();
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger logger = context.getLogger(clazz + " [" + name + "]");
        //設置不向上級打印信息
        logger.setAdditive(false);
        logger.addAppender(errorAppender);
        logger.addAppender(infoAppender);
        logger.addAppender(consoleAppender);

        return logger;
    }

}

  

package com.example.demo.config;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.filter.LevelFilter;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
import ch.qos.logback.core.util.FileSize;
import ch.qos.logback.core.util.OptionHelper;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import static ch.qos.logback.core.spi.FilterReply.ACCEPT;
import static ch.qos.logback.core.spi.FilterReply.DENY;

public class AppenderFactory {
    public RollingFileAppender createRollingFileAppender(String name, Level level) {

        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

        RollingFileAppender appender = new RollingFileAppender();
        //這裏設置級別過濾器
        appender.addFilter(createLevelFilter(level));

        //設置上下文,每一個logger都關聯到logger上下文,默認上下文名稱爲default。
        // 但可使用<contextName>設置成其餘名字,用於區分不一樣應用程序的記錄。一旦設置,不能修改。
        appender.setContext(context);
        //appender的name屬性
        appender.setName("file-" + level.levelStr.toLowerCase());
        //設置文件名
        appender.setFile(OptionHelper.substVars("${LOG_HOME}/" + name + "/" + level.levelStr.toLowerCase() + ".log", context));

        appender.setAppend(true);

        appender.setPrudent(false);

        //加入下面兩個節點
        appender.setRollingPolicy(createSizeAndTimeBasedRollingPolicy(name,level,context,appender));
        appender.setEncoder(createEncoder(context));
        appender.start();
        return appender;
    }

    public ConsoleAppender createConsoleAppender(){
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        ConsoleAppender appender = new ConsoleAppender();
        appender.setContext(context);
        appender.setName("file-console");
        appender.addFilter(createLevelFilter(Level.DEBUG));
        appender.setEncoder(createEncoder(context));
        appender.start();
        return appender;
    }

    private SizeAndTimeBasedRollingPolicy createSizeAndTimeBasedRollingPolicy(String name, Level level, LoggerContext context, FileAppender appender) {
        //設置文件建立時間及大小的類
        SizeAndTimeBasedRollingPolicy policy = new SizeAndTimeBasedRollingPolicy();
        //文件名格式
        String fp = OptionHelper.substVars("${LOG_HOME}/" + name + "/backup/" + level.levelStr.toLowerCase() + "-%d{yyyy-MM-dd}.log.%i", context);
        //最大日誌文件大小
        policy.setMaxFileSize(FileSize.valueOf("5MB"));
        //設置文件名模式
        policy.setFileNamePattern(fp);
        //設置最大歷史記錄爲30條
        policy.setMaxHistory(30);
        //總大小限制
        policy.setTotalSizeCap(FileSize.valueOf("32GB"));
        //設置父節點是appender
        policy.setParent(appender);
        //設置上下文,每一個logger都關聯到logger上下文,默認上下文名稱爲default。
        // 但可使用<contextName>設置成其餘名字,用於區分不一樣應用程序的記錄。一旦設置,不能修改。
        policy.setContext(context);
        policy.start();
        return policy;
    }

    private PatternLayoutEncoder createEncoder(LoggerContext context) {
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        //設置上下文,每一個logger都關聯到logger上下文,默認上下文名稱爲default。
        // 但可使用<contextName>設置成其餘名字,用於區分不一樣應用程序的記錄。一旦設置,不能修改。
        encoder.setContext(context);
        //設置格式
        encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} %msg%n");
        encoder.start();
        return encoder;
    }

    private LevelFilter createLevelFilter(Level level) {
        LevelFilter levelFilter = new LevelFilter();
        levelFilter.setLevel(level);
        levelFilter.setOnMatch(ACCEPT);
        levelFilter.setOnMismatch(DENY);
        levelFilter.start();
        return levelFilter;
    }

}
${LOG_HOME} 是 logback-spring.xml中的變量 ,以下
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
  <!--spring.application.name 是 application.yml 中設置--> 
  <springProperty scope="context" name="app_name" source="spring.application.name"/> 
  <property scope="context" name="LOG_HOME" value="logs/${app_name}"/> 
</configuration>

 

  測試代碼以下,使用了swaggerjava

@RestController
@RequestMapping("/test")
@Api(tags = "Test", description = "測試接口")
public class controller {

    @Autowired
    private LoggerBuilder loggerBuilder;

    @ApiOperation("測試")
    @PostMapping("/test")
    public ResultVO test(String name) {
        Logger logger = loggerBuilder.getLogger(name,controller.class);

        logger.info("測試...我係{}",name);

        return ResultVO.success();
    }
}

  以上代碼運行在 springboot(2.2.2.RELEASE) + logback、springboot(1.5.8.RELEASE) + logback  均有效spring

相關文章
相關標籤/搜索