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错误,并且多刷新几次就看到了内容,不会出现完全不可用. 还可以降低查 ...
随机推荐
- moviepy音视频剪辑:使用fl_time进行诸如快播、慢播、倒序播放等时间特效处理的原理和可能遇到的坑
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...
- PyQt(Python+Qt)学习随笔:QTreeView树形视图的headerHiden属性
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTreeView树形视图的headerHiden属性用于控制视图中是否隐藏标题,为True隐藏,否 ...
- PyQt(Python+Qt)学习随笔:窗口的布局设置及访问
老猿Python博文目录 老猿Python博客地址 在Qt Designer中,可以在一个窗体上拖拽左边的布局部件,在窗口中进行布局管理,但除了基于窗体之上进行布局之外,还需要窗体本身也进行布局管理才 ...
- python——pandas技巧(处理dataframe每个元素,不用for,而用apply)
用apply处理pandas比用for循环,快了无数倍,测试如下: 我们有一个pandas加载的dataframe如下,features是0和1特征的组合,可惜都是str形式(字符串形式),我们要将其 ...
- 文件重命名工具(ReNamer)7.2中文绿色便携专业版
ReNamer 是一个非常强大和灵活的文件重命名工具,它提供所有标准的重命名过程,包括前缀.后缀.替换.大小写更改以及删除括号内容.添加编号规则.更改文件扩展名等.对于高级用户,支持正则表达式和 Pa ...
- 哪些地方会出现css阻塞,哪些地方会出现js阻塞?
js的阻塞特性: 所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等. 直到JS下载.解析.执行完毕后才开始继续并行下载其他资源并呈现内容. 为了提高用户体验,新一代浏 ...
- 协程gevent学习
import gevent def f1(): print(11) gevent.sleep(2) print(33) def f2(): print(22) gevent.sleep(1) prin ...
- pytorch和tensorflow的爱恨情仇之一元线性回归例子(keras插足啦)
直接看代码: 一.tensorflow #tensorflow import tensorflow as tf import random import numpy as np x_data = np ...
- 一文搞懂Java引用拷贝、浅拷贝、深拷贝
微信搜一搜 「bigsai」 专注于Java和数据结构与算法的铁铁 文章收录在github/bigsai-algorithm 在开发.刷题.面试中,我们可能会遇到将一个对象的属性赋值到另一个对象的情况 ...
- Zepto入门
Zepto 的介绍 #什么是 Zepto zepto是轻量级的JavaScript库,专门为移动端定制的框架. 与jquery有着类似的API,俗称:会jquery就会用zepto #zepto的特点 ...