在项目复杂业务当中,可能回遇到logbook.xml配置还不能够满足需要的情况。需要自定义实现log组件,在不更改任何配置的情况下,需要根据业务入口类(可以时controller,或是接口组件的的接口等)去分离日志内容。
下面我逐步介绍如何实现。
package com.iflytek.mea.job.api.log;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
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.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.spi.FilterReply;
import ch.qos.logback.core.util.FileSize;
import org.slf4j.LoggerFactory;
import java.util.Hashtable;
import java.util.Map;
public class LoggerFactory {
public static ThreadLocal LOGGER = new ThreadLocal<>();
private static Hashtable loggerTable = new Hashtable<>();
public static Logger getLogger() {
return LOGGER_FACTORY.get();
}
public static void initLoggers(Map jobMap, String level) {
for (Map.Entry entry : jobMap.entrySet()) {
Class aClass = entry.getValue();
String className = aClass.getClass().getName();
Logger logger = (Logger) LoggerFactory.getLogger(className);
infoAppender(logger, entry.getKey());
errorAppender(logger, entry.getKey());
debugAppender(logger, entry.getKey());
switch (level) {
case "error":
logger.setLevel(Level.ERROR);
break;
case "info":
logger.setLevel(Level.INFO);
break;
case "debug":
logger.setLevel(Level.DEBUG);
break;
default:
logger.setLevel(Level.INFO);
break;
}
loggerTable.put(className, logger);
}
}
public synchronized static Logger createLogger(String className) {
if (loggerTable.containsKey(className)) {
return loggerTable.get(className);
}
Logger logger = (Logger) LoggerFactory.getLogger(className);
String jobName = className.substring(className.lastIndexOf(".") + 1);
infoAppender(logger, jobName);
errorAppender(logger, jobName);
debugAppender(logger, jobName);
logger.setLevel(Level.INFO);
loggerTable.put(className, logger);
return logger;
}
public static void debugAppender(Logger logger, String jobName) {
LoggerContext loggerContext = logger.getLoggerContext();
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext);
encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%C] [%M] - %msg%n");
encoder.start();
RollingFileAppender appender = new RollingFileAppender();
appender.setContext(loggerContext);
TimeBasedRollingPolicy rollingPolicyBase = new TimeBasedRollingPolicy<>();
rollingPolicyBase.setContext(loggerContext);
rollingPolicyBase.setParent(appender);
rollingPolicyBase.setFileNamePattern((String.format("logs/jobs/%s/%s", jobName, jobName) + "-debug.%d{yyyy-MM-dd}.%i.log"));
SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP();
sizeAndTimeBasedFNATP.setMaxFileSize(new FileSize(10 * FileSize.MB_COEFFICIENT));
rollingPolicyBase.setTimeBasedFileNamingAndTriggeringPolicy(sizeAndTimeBasedFNATP);
rollingPolicyBase.setMaxHistory(10);
rollingPolicyBase.start();
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(Level.DEBUG);
levelFilter.setOnMatch(FilterReply.ACCEPT);
levelFilter.setOnMismatch(FilterReply.DENY);
levelFilter.start();
appender.addFilter(levelFilter);
appender.setEncoder(encoder);
appender.setRollingPolicy(rollingPolicyBase);
appender.start();
logger.setAdditive(false);
logger.addAppender(appender);
}
public static void errorAppender(Logger logger, String jobName) {
LoggerContext loggerContext = logger.getLoggerContext();
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext);
encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%C] [%M] - %msg%n");
encoder.start();
RollingFileAppender appender = new RollingFileAppender();
appender.setContext(loggerContext);
TimeBasedRollingPolicy rollingPolicyBase = new TimeBasedRollingPolicy<>();
rollingPolicyBase.setContext(loggerContext);
rollingPolicyBase.setParent(appender);
rollingPolicyBase.setFileNamePattern((String.format("logs/jobs/%s/%s", jobName, jobName) + "-error.%d{yyyy-MM-dd}.%i.log"));
SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP();
sizeAndTimeBasedFNATP.setMaxFileSize(new FileSize(10 * FileSize.MB_COEFFICIENT));
rollingPolicyBase.setTimeBasedFileNamingAndTriggeringPolicy(sizeAndTimeBasedFNATP);
rollingPolicyBase.setMaxHistory(10);
rollingPolicyBase.start();
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(Level.ERROR);
levelFilter.setOnMatch(FilterReply.ACCEPT);
levelFilter.setOnMismatch(FilterReply.DENY);
levelFilter.start();
appender.addFilter(levelFilter);
appender.setEncoder(encoder);
appender.setRollingPolicy(rollingPolicyBase);
appender.start();
logger.setAdditive(false);
logger.addAppender(appender);
}
public static void infoAppender(Logger logger, String jobName) {
LoggerContext loggerContext = logger.getLoggerContext();
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext);
encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%C] [%M] - %msg%n");
encoder.start();
RollingFileAppender appender = new RollingFileAppender();
appender.setContext(loggerContext);
TimeBasedRollingPolicy rollingPolicyBase = new TimeBasedRollingPolicy<>();
rollingPolicyBase.setContext(loggerContext);
rollingPolicyBase.setParent(appender);
rollingPolicyBase.setFileNamePattern((String.format("logs/jobs/%s/%s", jobName, jobName) + "-info.%d{yyyy-MM-dd}.%i.log"));
SizeAndTimeBasedFNATP sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP();
sizeAndTimeBasedFNATP.setMaxFileSize(new FileSize(10 * FileSize.MB_COEFFICIENT));
rollingPolicyBase.setTimeBasedFileNamingAndTriggeringPolicy(sizeAndTimeBasedFNATP);
rollingPolicyBase.setMaxHistory(10);
rollingPolicyBase.start();
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(Level.INFO);
levelFilter.setOnMatch(FilterReply.ACCEPT);
levelFilter.setOnMismatch(FilterReply.DENY);
levelFilter.start();
appender.addFilter(levelFilter);
appender.setEncoder(encoder);
appender.setRollingPolicy(rollingPolicyBase);
appender.start();
logger.setAdditive(false);
logger.addAppender(appender);
}
}
方法说明:
详解:
%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%C] [%M] - %msg%n
,输出的是logger调用的类的路径,有别于传统的配置。