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>
测试代码如下,使用了swagger
@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 均有效
logback运行时动态创建日志文件的更多相关文章
- C# 在运行时动态创建类型
C# 在运行时动态的创建类型,这里是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型 public static Assembly NewAssembly() { //创建编译 ...
- [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤
作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...
- [转] Java运行时动态生成class的方法
[From] http://www.liaoxuefeng.com/article/0014617596492474eea2227bf04477e83e6d094683e0536000 廖雪峰 / 编 ...
- Java 运行时动态生成class
转载 http://www.liaoxuefeng.com/article/0014617596492474eea2227bf04477e83e6d094683e0536000 Java是一门静态语言 ...
- 利用log4net创建日志文件时过滤日志,这是坑还是?
前言 网上貌似没有太多关于log4net过滤日志的资料,在研究过程中发现一点小问题,这里做下记录,希望对后续有用到的童鞋起到一丢丢帮助作用. log4net日志过滤 由于是在.NET Core中使用, ...
- LINQ to SQL 运行时动态构建查询条件
在进行数据查询时,经常碰到需要动态构建查询条件.使用LINQ实现这个需求可能会比以前拼接SQL语句更麻烦一些.本文介绍了3种运行时动态构建查询条件的方法.本文中的例子最终实现的都是同一个功能,从Nor ...
- 使用javassist运行时动态重新加载java类及其他替换选择
在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...
- 解决 Retrofit 多 BaseUrl 及运行时动态改变 BaseUrl ?
原文地址: juejin.im/post/597856- 解决Retrofit多BaseUrl及运行时动态改变BaseUrl(一) 解决Retrofit多BaseUrl及运行时动态改变BaseUrl( ...
- .NET6运行时动态更新限流阈值
昨天博客园撑不住流量又崩溃了,很巧正在编写这篇文章,于是产生一个假想:如果博客园用上我这个限流组件会怎么样呢? 用户会收到几个429错误,并且多刷新几次就看到了内容,不会出现完全不可用. 还可以降低查 ...
随机推荐
- PyQt(Python+Qt)学习随笔:containers容器类部件QMdiArea多文档界面的QMdiSubWindow子窗口相关属性和操作方法
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 1.增加子窗口 QMdiArea中的子窗口类型是QMdiSubWind ...
- PyQt(Python+Qt)学习随笔:toolButton的popupMode属性
属性介绍 toolButton的popupMode属性为设有菜单集或Action列表的toolButton指定菜单弹出模式,类型为枚举类型ToolButtonPopupMode,有如下三种模式: 1. ...
- tornado 作业 简单首页 登录页 个人中心
s4 index.py 1 import tornado.ioloop 2 import tornado.web 3 import time 4 5 6 class IndexHandler(torn ...
- 移动端和PC端区分
1.移动端包括:浏览器.ios/android.qq端.微信端 九度数据官网源码.修改,要跳转的链接即可. function browserRedirect() { var sUserAgent = ...
- 用正则怎么将html文件中文字取出进行ASCII码转换?
用正则怎么将html文件中文字取出?今天碰到这个问题,思来想去尝试了好几种方法,历经一阵头脑风暴,最后终于还是解决了,想想还是来记录一下.一共定义了三个函数,包含正则切割.正则判断对象开头.ASCII ...
- RocketMQ(六):nameserver队列存储定位解析
在rocketmq中,nameserver充当了一个配置管理者的角色,看起来好似不太重要.然而它是一个不或缺的角色,没有了它的存在,各个broker就是一盘散沙,各自为战. 所以,实际上,在rocke ...
- 求求你,别再用wait和notify了!
Condition 是 JDK 1.5 中提供的用来替代 wait 和 notify 的线程通讯方法,那么一定会有人问:为什么不能用 wait 和 notify 了? 哥们我用的好好的.老弟别着急,听 ...
- 自顶向下redis4.0(4)时间事件与expire
redis4.0的时间事件与expire 目录 redis4.0的时间事件与expire 简介 正文 时间事件注册 时间事件触发 expire命令 删除过期键值 被动删除 主动删除/定期删除 参考文献 ...
- glances linux资源使用监控
安装 yum install glances -y 界面 介绍 命令选项 -b:显示网络连接速度 Byte/ 秒 -B @IP|host :绑定服务器端 IP 地址或者主机名称 -c @IP|host ...
- 单身狗福利!利用java实现每天给对象发情话,脱单指日可待!
引言 最近看到一篇用js代码实现表白的文章,深有感触. 然后发现自己也可以用java代码实现,然后就开始写代码了,发现还挺有意思的,话不多说开搞 实现思路: 使用HttpClient远程获取彩虹屁生成 ...