大家平时使用Log4j一般都是在classpath下放置一个log4j的配置文件,比如log4j.xml,里面配置好Appenders和Loggers,但是前一阵想做某需求的时候,想要的效果是每一个任务都要有一个单独的日志文件记录下来,比如job.001.log,job.002.log这种,这种完全不能使用配置文件来设置。

整体架构:

Log4j的组成:

Log4j由三个重要的组成构成:日志记录器(Loggers),输出端(Appenders)和日志格式化器(Layout)。

1.日志记录器(Loggers):控制要输出哪些日志记录语句,对日志信息进行级别限制。
2.输出端(Appenders):指定了日志将打印到控制台还是文件中。

3.日志格式化器(Layout):控制日志信息的显示格式。

  于是点开Log4j的源码,研究了一番,发现使用Log4j的底层代码完全可以动态生成新的Logger,比较关键的类有

org.apache.logging.log4j.core.Layout负责格式
org.apache.logging.log4j.core.Appender就是配置文件里的Appender,我们使用FileAppender,也可以使用RollingFileAppender,
org.apache.logging.log4j.core.config.Configuration和org.apache.logging.log4j.core.LoggerContext是负责Log4j的配置的。

LoggerContext

  在日志系统中,LoggerContext扮演者重要的角色。然而,根据实际情况,一个应用中可能存在多个有效的LoggerContext。

Configuration  

  每一个LoggerContext都有一个有效的Configuaration,它包含了所有的Appenders、context-wide Filters、LoggerConfigs以及对StrSubstitutor的引用。在重新配置期间,两个Configuaration会同时存在;一旦日志器被重新赋予新的Configuaration,旧的Configuaration就会停止工作并丢弃。

LoggerConfig

  LoggerConfig将会在Loggers在logging configuration中被声明的时候创建。在LoggerConfig 拥有一列类的过滤器(Filter),这些过滤器将会过来所有的记录日志的事件,只有符合要求的日志才会被传递到Appenders。因为LoggerConfig需要将事件传递给Appenders,所以它拥有一系列Appenders的引用。

Appender

   根据logger请求选择去接受或者拒绝该只是他们的一个能力。Log4j允许日志打印服务打印到多个目的地上。在Log4j的说法是一个输出的目的地对应着一个Appdender。现在的Appender允许是console, files, remote socket servers, Apache Flume, JMS, remote UNIX Syslog daemons, and various database APIs。

  是在Log4j2.3下测试通过的。注意在不使用Logger的时候一定要调用stop方法将Logger移除,不然我自己测试生成7000多个Logger后便会报错open too many file。

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class JobLogFactory {
private JobLogFactory() {
}
public static void start(int jobId) {
   //为false时,返回多个LoggerContext对象, true:返回唯一的单例LoggerContext
   final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
   //创建一个展示的样式:PatternLayout, 还有其他的日志打印样式。
Layout layout = PatternLayout.createLayout(PatternLayout.DEFAULT_CONVERSION_PATTERN,
config, null, null, true, false, null, null);
//TriggeringPolicy tp = SizeBasedTriggeringPolicy.createPolicy("10MB");
//Appender appender = RollingFileAppender.createAppender(String.format("
// logs/test/syncshows-job-%s.log", jobID),
// "/logs/test/" + jobID + "/syncshows-job-" + jobID + ".log.gz",
// "true", jobID, null, null, null, tp, null, layout, null,
// null, null, null, config);
   // 日志打印方式——输出为文件
   Appender appender = FileAppender.createAppender(
String.format("logs/test/syncshows-job-%s.log", jobId), "true", "false",
"" + jobId, null, "true", "true", null, layout, null, null, null, config);
appender.start();
config.addAppender(appender);
AppenderRef ref = AppenderRef.createAppenderRef("" + jobId, null, null);
AppenderRef[] refs = new AppenderRef[]{ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.ALL, "" + jobId,
"true", refs, null, config, null);
loggerConfig.addAppender(appender, null, null);
config.addLogger("" + jobId, loggerConfig);
ctx.updateLoggers();
}
public static void stop(int jobId) {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
config.getAppender("" + jobId).stop();
config.getLoggerConfig("" + jobId).removeAppender("" + jobId);
config.removeLogger("" + jobId);
ctx.updateLoggers();
}
/**
* 获取Logger
*
* 如果不想使用slf4j,那这里改成直接返回Log4j的Logger即可
* @param jobId
* @return
*/
public static Logger createLogger(int jobId) {
start(jobId);
return LoggerFactory.getLogger("" + jobId);
}
}

测试类:

import org.slf4j.Logger;
/**
*
simple test
*/
public class LoggerTest {
public static void main(String[] args) {
for(int i=0;i<50000;i++) {
Logger logger = JobLogFactory.createLogger(i);
logger.info("Testing testing testing 111");
logger.debug("Testing testing testing 222");
logger.error("Testing testing testing 333");
JobLogFactory.stop(i);
}
}
}

  致谢,感谢您的阅读

log4j2 不使用配置文件,动态生成logger对象的更多相关文章

  1. 利用StringList对象来管理这些动态生成的对象

    如果程序需要动态创建大量的对象,那么我们可以利用StringList对象来管理这些动态生成的对象.1.创建StringList对象:OBJ := TStringList.Create; 2.保存动态生 ...

  2. JS 动态生成JSON对象

    JS 动态生成JSON对象,一般用到JSON传递参数的时候,会用到. function onGeneratedRow(columnsResult) { var jsonData = {}; colum ...

  3. Python PageFactory-使用配置文件动态生成页面PageObject

    需求 在Python Selenium 的 PageObject模式中,一般每个页面需要写一个类, 一种PageObject的写法如下: class BaiduPageObject(object): ...

  4. mybatis-generator 动态生成实体对象、dao 以及相关的xml映射文件

    .新建maven空项目 2.修改pom.xml文件 <?xml version="1.0" encoding="UTF-8"?> <proje ...

  5. Jquery给动态生成的对象绑定事件

    $(document).on("blur", ".Text1", function () { var index = this.id.replace('txtS ...

  6. Log4j2 - 动态生成Appender

    功能需求 项目里将User分成了各个区域(domain),这些domain有个标志domainId,现在要求在打印日志的时候,不仅将所有User的日志都打印到日志文件logs/CNTCore.log中 ...

  7. Emit动态生成代理类用于监控对象的字段修改

    利用Emit动态生成代理对象监控对象哪些字段被修改,被修改为什么值 被Register的对象要监控的值必须是Virtual虚类型 必须使用CreateInstance创建对象 必须使用DynamicP ...

  8. Vuforia图像追踪,动态创建的对象隐藏显示的坑

    刚做的一个项目,使用Unity3D的Vuforia插件进行图像识别,其中有动态生成的游戏对象模型,地形模型放在ImageTarget下,作为ImageTarget的子物体. 动态生成的敌人则有Pref ...

  9. log4cplus 直接创建logger 对象

    #include <log4cplus/loggingmacros.h> #include <log4cplus/fileappender.h> #include <lo ...

随机推荐

  1. 【开源框架】SqlSugarRepository 全库ORM 正式发布

    SqlSugarRepository.dll 全库开发框架支持 四种数据库:SqlServer. MySql .Oracle和Sqlite. SqlSugarRepository是为全库开发而生的OR ...

  2. webapi filter过滤器中获得请求的方法详情(方法名,Attributes)

    public class GlobalActionFilter : ActionFilterAttribute { private string _requestId; public override ...

  3. 背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout

    [源码下载] 背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout 作者:webabcd 介绍背水一战 Windows 10 之 ...

  4. eclipse报错:Failed to load the JNI shared library

    Eclipse运行时提示“Failed to load the JNI shared library /Java/jre6/bin/client/jvm.dll”的一个解决方案 因为 Eclipse ...

  5. mybatis入门

    1.什么是MyBatis ?      亲爱的度娘是这样说的: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation ...

  6. 网站banner无缝轮播

    网站banner无缝轮播 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  7. 谷歌浏览器下载地址 chrome最新版本 百度云地址

    每次下载更新谷歌浏览器是一件很蛋疼的事情.百度搜索"谷歌浏览器下载地址",居然有很多骗子网站,相信有很多不知所以的人中招了.收集了一些chrome的安装包,放在了百度云里面(打不开 ...

  8. 在vs2012中用C#开发Android应用Xamarin环境搭建

    Xamarin是Mono创始人Miguel de Icaza创建的公司,旨在让开发者可以用C#编写iOS, Android, Mac应用程序,也就是跨平台移动开发. 简介 Xamarin是基于Mono ...

  9. 如何在mac上安装docker[记录自己在mac上安装docker的经历]

    0.引子 最近入手了一台mac笔记本,想在本地安装docker. 1.找安装文档. 文档地址:http://www.widuu.com/chinese_docker/installation/mac. ...

  10. wampserver安装配置

    按步骤安装--选择指定浏览器-安装成功后显示绿色图标: 打开浏览器:将文件夹移入wampserver安装路径的www文件夹中:找到电脑IP 在手机端访问 IP/文件夹/demo.html即可