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运行时动态创建日志文件的更多相关文章

  1. C# 在运行时动态创建类型

    C# 在运行时动态的创建类型,这里是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型 public static Assembly NewAssembly() { //创建编译 ...

  2. [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤

    作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...

  3. [转] Java运行时动态生成class的方法

    [From] http://www.liaoxuefeng.com/article/0014617596492474eea2227bf04477e83e6d094683e0536000 廖雪峰 / 编 ...

  4. Java 运行时动态生成class

    转载 http://www.liaoxuefeng.com/article/0014617596492474eea2227bf04477e83e6d094683e0536000 Java是一门静态语言 ...

  5. 利用log4net创建日志文件时过滤日志,这是坑还是?

    前言 网上貌似没有太多关于log4net过滤日志的资料,在研究过程中发现一点小问题,这里做下记录,希望对后续有用到的童鞋起到一丢丢帮助作用. log4net日志过滤 由于是在.NET Core中使用, ...

  6. LINQ to SQL 运行时动态构建查询条件

    在进行数据查询时,经常碰到需要动态构建查询条件.使用LINQ实现这个需求可能会比以前拼接SQL语句更麻烦一些.本文介绍了3种运行时动态构建查询条件的方法.本文中的例子最终实现的都是同一个功能,从Nor ...

  7. 使用javassist运行时动态重新加载java类及其他替换选择

    在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...

  8. 解决 Retrofit 多 BaseUrl 及运行时动态改变 BaseUrl ?

    原文地址: juejin.im/post/597856- 解决Retrofit多BaseUrl及运行时动态改变BaseUrl(一) 解决Retrofit多BaseUrl及运行时动态改变BaseUrl( ...

  9. .NET6运行时动态更新限流阈值

    昨天博客园撑不住流量又崩溃了,很巧正在编写这篇文章,于是产生一个假想:如果博客园用上我这个限流组件会怎么样呢? 用户会收到几个429错误,并且多刷新几次就看到了内容,不会出现完全不可用. 还可以降低查 ...

随机推荐

  1. 喜欢 Dapper 的朋友看过来,送一份厚礼

    写在开头 众所周知 Dapper 是 .NET 下最轻最快的 ORM,它是喜欢写 SQL 码农的福音,相对于 SqlHelper 它更加方便,据统计 10个 .NETer 有 9个 用过 Dapper ...

  2. PyQt(Python+Qt)学习随笔:树型部件QTreeWidget中的topLevelItem、indexOfTopLevelItem和takeTopLevelItem方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 获取指定位置顶层项 树型部件QTreeWidget中,通过topLevelItem方法根据位置索引取 ...

  3. PyQt(Python+Qt)学习随笔:Qt Designer中主窗口对象的animated属性

    animated属性用于设置在操作可浮动部件和工具栏时是否设置动画. 当一个可浮动部件或工具栏被拖到主窗口上时,主窗口将调整其内容,以显示浮动部件或工具栏应该放置的位置.设置此属性后主窗口将使用平滑动 ...

  4. 推荐系统实践 0x0c FM系列

    逻辑回归(LR) 在介绍FM系列之前,我想首先简单介绍一下逻辑回归.通常来说,逻辑回归模型能够综合利用更多的信息,如用户.物品.上下文等多种不同的特征,生成更为全面的结果.另外,逻辑回归将推荐问题看成 ...

  5. CSS绘制正五角星原理(数学模型)

    尽管网上有很多CSS绘制五角星的代码案例,但是对于初学者来说可以拿来移植使用,但是在不明白其原理的情况下,进行修改移植就比较困难了.譬如想要将五角星尺寸进行缩小或者放大等设计,就需要对原代码相关数据进 ...

  6. 【Codeforces 1037H】Security(SAM & 线段树合并)

    Description 给出一个字符串 \(S\). 给出 \(Q\) 个操作,给出 \(L, R, T\),求字典序最小的 \(S_1\),使得 \(S^\prime\) 为\(S[L..R]\) ...

  7. 【Jmeter Linux环境下运行方法】

    Jmeter 运行 1.cd  jmeter/apache-jmeter-4.0/bin 2.执行 ./jmeter -n -t jmx脚本文件 -l 测结果.jtl文件 -e -o html文件路径 ...

  8. Eclipse设置自动提示

    Eclipse设置自动提示可通过以下方式实现, 1.运行Eclipse开发工具,在开发工具最顶端菜单栏,点击"windows"->"preferences" ...

  9. SpringBoot + SpringSecurity + Quartz + Layui实现系统权限控制和定时任务

    1. 简介   Spring Security是一个功能强大且易于扩展的安全框架,主要用于为Java程序提供用户认证(Authentication)和用户授权(Authorization)功能.    ...

  10. Python定时任务利器—Apscheduler

    导语 在工作场景遇到了这么一个场景,就是需要定期去执行一个缓存接口,用于同步设备配置.首先想到的就是Linux上的crontab,可以定期,或者间隔一段时间去执行任务.但是如果你想要把这个定时任务作为 ...