java代码实现LogBack动态输出日志【无配置文件纯代码】
程序员文章站
2022-05-12 11:33:43
...
需求:
需要传入某一个文件或者类或者方法的名字,生成对应日志文件,且每一个传入名字的文件单独有一个文件夹,子文件夹为日期,日期文件夹里面包含warn.log,error.log,debug.log,info.log。通过过滤器实现只打印对应级别的日志。
遇到的问题:
度娘了很久,网上关于logback的几乎都是xml进行配置的,但是经过尝试,xml配置的方式不能直接进行动态的输出,故此方法暂时淘汰,遂想到用纯代码的方式,尝试了许多次才得到正确的结果,所以记录下来,以免今后少走弯路。
内容:
1.创建LoggerBuilder类,这个类相当于一个日志工具类,之后其他类需要用日志的时候,直接调用它的方法就好了。
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.rolling.RollingFileAppender;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author Wzy525110
*/
@Component
public class LoggerBuilder {
private static final Map<String,Logger> container = new HashMap<>();
public Logger getLogger(String name) {
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);
container.put(name,logger);
}
return logger;
}
private static Logger build(String name) {
RollingFileAppender errorAppender =new AppenderTest().getAppender(name,Level.ERROR);
RollingFileAppender infoAppender =new AppenderTest().getAppender(name,Level.INFO);
RollingFileAppender warnAppender =new AppenderTest().getAppender(name,Level.WARN);
RollingFileAppender debugAppender =new AppenderTest().getAppender(name,Level.DEBUG);
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = context.getLogger("FILE-" + name);
//设置不向上级打印信息
logger.setAdditive(false);
logger.addAppender(errorAppender);
logger.addAppender(infoAppender);
logger.addAppender(warnAppender);
logger.addAppender(debugAppender);
return logger;
}
}
2.创建AppenderTest类,这个类给LoggerBuilder动态提供appender
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.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 java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
/**
* 这个类是给日志动态提供appender
* @author Wzy525110
*/
@Component
public class GetTheAppender {
/**
* 通过传入的名字和级别,动态设置appender
* @param name
* @param level
* @return
*/
public RollingFileAppender getAppender(String name, Level level){
DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.SIMPLIFIED_CHINESE);
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
//这里是可以用来设置appender的,在xml配置文件里面,是这种形式:
// <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
RollingFileAppender appender = new RollingFileAppender();
// ConsoleAppender consoleAppender = new ConsoleAppender();
//这里设置级别过滤器
LevelController levelController = new LevelController();
LevelFilter levelFilter = levelController.getLevelFilter(level);
levelFilter.start();
appender.addFilter(levelFilter);
//设置上下文,每个logger都关联到logger上下文,默认上下文名称为default。
// 但可以使用<contextName>设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
appender.setContext(context);
//appender的name属性
appender.setName("FILE-" + name);
//设置文件名
appender.setFile(OptionHelper.substVars("E:/eppLog/"+ name+"/" + format.format(new Date())+"/"+ level.levelStr + ".log",context));
appender.setAppend(true);
appender.setPrudent(false);
//设置文件创建时间及大小的类
SizeAndTimeBasedRollingPolicy policy = new SizeAndTimeBasedRollingPolicy();
//文件名格式
String fp = OptionHelper.substVars("E:/eppLog/"+ name +"/" + format.format(new Date())+"/"+ level.levelStr + "/.%d{yyyy-MM-dd}.%i.log",context);
//最大日志文件大小
policy.setMaxFileSize(FileSize.valueOf("128MB"));
//设置文件名模式
policy.setFileNamePattern(fp);
//设置最大历史记录为15条
policy.setMaxHistory(15);
//总大小限制
policy.setTotalSizeCap(FileSize.valueOf("32GB"));
//设置父节点是appender
policy.setParent(appender);
//设置上下文,每个logger都关联到logger上下文,默认上下文名称为default。
// 但可以使用<contextName>设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
policy.setContext(context);
policy.start();
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
//设置上下文,每个logger都关联到logger上下文,默认上下文名称为default。
// 但可以使用<contextName>设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
encoder.setContext(context);
//设置格式
encoder.setPattern("%d %p (%file:%line\\)- %m%n");
encoder.start();
//加入下面两个节点
appender.setRollingPolicy(policy);
appender.setEncoder(encoder);
appender.start();
return appender;
}
}
注意:每一个节点都需要.start(),才能加入到这个类拼凑出来的格式中。
3.创建LevelController类,这个类主要是通过level动态的给日志生成过滤器
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.filter.LevelFilter;
import static ch.qos.logback.core.spi.FilterReply.ACCEPT;
import static ch.qos.logback.core.spi.FilterReply.DENY;
/**
* 这个类的作用是给日志通过level设置过滤器
* @author Wzy525110
*/
public class LevelController {
/**
* 通过level设置过滤器
* @param level
* @return
*/
public LevelFilter getLevelFilter(Level level){
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(level);
levelFilter.setOnMatch(ACCEPT);
levelFilter.setOnMismatch(DENY);
return levelFilter;
}
}
这样,logback的工具类就OK了,可以正常在其他类进行使用了!
测试类如下:
import com.wzy.common.LoggerBuilder;
import ch.qos.logback.classic.Logger;
/**
* @author Wzy525110
*/
public class LogTest {
public static void main(String[] args) {
LoggerBuilder loggerBuilder =new LoggerBuilder();
Logger logger = loggerBuilder.getLogger("test");
logger.debug("shuai1 +++++++++++++++++++++++++++++++++++++debug");
logger.warn("shuai2 +++++++++++++++++++++++++++++++++++++warn");
logger.info("shuai3 +++++++++++++++++++++++++++++++++++++info");
logger.error("shuai4 +++++++++++++++++++++++++++++++++++++error");
}
}
输出:
上一篇: 2020-12-02
下一篇: IOS 纯代码实现界面