Log4j 2 使用总结

Log4j 2 包含了基于LMAX 分离库的下一代的异步日志系统,在多线程环境下,异步日志系统比 Log4j 1.x 和Logback 提高了10倍性能提升(吞吐量和延迟率 )。原文如下:
Log4j 2 contains next-generation Asynchronous Loggers based on the LMAX Disruptor library. In multi-threaded scenarios Asynchronous Loggers have 10 times higher throughput and orders of magnitude lower latency than Log4j 1.x and Logback.
Log4j2目前已经出到了beta8版本,估计beta9在最近一周将放出,试用了下,感觉还不错,做如下总结!
我是从logback迁移到log4j2,
删除掉原有的包 log4j-over-slf4j-1.6.4.jar logback-classic-1.0.7.jar logback-core-1.0.7.jar slf4j-api-1.6.4.jar
增添以下的包 log4j-over-slf4j-1.7.5.jar log4j-api-2.0-beta8.jar log4j-core-2.0-beta8.jar log4j-slf4j-impl-2.0-beta8.jar

由于作者推荐,为了性能考虑,尽量不要使用slf4j,但我依赖的第三方框架比如spring有对slf4j使用,所以对JAR包做了以上的取舍,所以原有代码中要做如下的改动
改动前:import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(OOXX.class);

改动后:iimport org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
private static final Logger logger = LogManager.getLogger(OOXX.class);
配置文件log4j2.xml如下:
[html] view plain copy print?在CODE上查看代码片派生到我的代码片

<?xml version="1.0" encoding="UTF-8"?>  
<!-- status=debug 可以查看log4j的装配过程 -->  
<configuration status="off" monitorInterval="1800">  
    <properties>  
        <property name="LOG_HOME">/log/fish</property>  
        <!-- 日志备份目录 -->  
        <property name="BACKUP_HOME">{LOG_HOME}/backup</property>  
        <property name="STAT_NAME">stat</property>  
        <property name="SERVER_NAME">global</property>  
    </properties>  
    <appenders>  
        <!-- 定义控制台输出 -->  
        <Console name="Console" target="SYSTEM_OUT" follow="true">  
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />  
        </Console>  
        <!-- 程序员调试日志 -->  
        <RollingRandomAccessFile name="DevLog" fileName="${LOG_HOME}/${SERVER_NAME}"  
            filePattern="${LOG_HOME}/${SERVER_NAME}.%d{yyyy-MM-dd-HH}.log">  
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />  
            <Policies>  
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />  
            </Policies>  
        </RollingRandomAccessFile>  
        <!-- 游戏产品数据分析日志 -->  
        <RollingRandomAccessFile name="ProductLog"  
            fileName="${LOG_HOME}/${SERVER_NAME}_${STAT_NAME}"  
            filePattern="${LOG_HOME}/${SERVER_NAME}_${STAT_NAME}.%d{yyyy-MM-dd-HH}.log">  
            <PatternLayout  
                pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />  
            <Policies>  
                <TimeBasedTriggeringPolicy interval="1"  
                    modulate="true" />  
            </Policies>  
        </RollingRandomAccessFile>  
    </appenders>  
    <loggers>  
        <!-- 3rdparty Loggers -->  
        <logger name="org.springframework.core" level="info">  
        </logger>  
        <logger name="org.springframework.beans" level="info">  
        </logger>  
        <logger name="org.springframework.context" level="info">  
        </logger>  
        <logger name="org.springframework.web" level="info">  
        </logger>  
        <logger name="org.jboss.netty" level="warn">  
        </logger>  
        <logger name="org.apache.http" level="warn">  
        </logger>  
        <logger name="com.mchange.v2" level="warn">  
        </logger>  
        <!-- Game Stat  logger -->  
        <logger name="com.u9.global.service.log" level="info"  
            additivity="false">  
            <appender-ref ref="ProductLog" />  
        </logger>  
        <!-- Root Logger -->  
        <root level="DEBUG" includeLocation="true">  
            <appender-ref ref="DevLog" />  
            <appender-ref ref="Console" />  
        </root>  
    </loggers>  
</configuration>  

TimeBased Triggering Policy

基于时间的触发策略。该策略主要是完成周期性的log文件封存工作。有两个参数:

interval,integer型,指定两次封存动作之间的时间间隔。单位:以日志的命名精度来确定单位,比如yyyy-MM-dd-HH 单位为小时,yyyy-MM-dd-HH-mm 单位为分钟

modulate,boolean型,说明是否对封存时间进行调制。若modulate=true,则封存时间将以0点为边界进行偏移计算。比如,modulate=true,interval=4hours,那么假设上次封存日志的时间为03:00,则下次封存日志的时间为04:00,之后的封存时间依次为08:00,12:00,16:00,。。。

存在问题:在Eclipse下一切运行正常,如果把应用打包成jar包发布后,cmd命令行模式下,即使Console开着的情况下,也没法输出,文件输出也没有任何日志。
问题已经解决,需要在MANIFEST.MF文件里Class-Path 最前加个’.’,目的是让与jar包平级的配置文件log4j2.xml加载进来。
比如
Class-Path: . lib/antlr-2.7.6.jar lib/other.jar
这样,就把包含了log4j2.xml的路径放到了classpath,因此,log4j2能读取这个文件。感谢老外Jacob Kjome的回复!
log4j2 在Web的应用,把log4j2.xml放在src根目录下,不需要任何在代码级别的设置,直接类似Java应用一样使用,但把servlet改成了servlet3.0,因为官网上描述如下:
[html] view plain copy print?在CODE上查看代码片派生到我的代码片
The Short Story
Log4j 2 “just works” in Servlet 3.0 and newer web applications. It is capable of automatically starting when the application deploys and shutting down when the application undeploys.Important Note! For performance reasons, containers often ignore certain JARs known not to contain TLDs or ServletContainerInitializers and do not scan them for web-fragments and initializers. Importantly, Tomcat 7 <7.0.43 ignores all JAR files named log4j*.jar, which prevents this feature from working. This has been fixed in Tomcat 7.0.43, Tomcat 8, and later. In Tomcat 7 <7.0.43 you will need to change catalina.properties and remove “log4j*.jar” from the jarsToSkip property. You may need to do something similar on other containers if they skip scanning Log4j JAR files.

但发现在eclipse下servlet2.0 也可以用的,并且不用修改catalina.properties文件。我用的是apache-tomcat-7.0.42,很奇怪!

有时候,为了同一份log4j文件要支持写到不同的log中(否则会导致打印的内容被覆盖,其中一个进程写不进log等问题),需要在载入的时候对内容进行动态修改,比如根据server id分别生成game1.log,game2.log
可以代码进行加载log4文件
[java] view plain copy print?在CODE上查看代码片派生到我的代码片

File file = new File("log4j2.xml");  
        BufferedInputStream in = null;  
        try {  
            in = new BufferedInputStream(new FileInputStream(file));  
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
<span style="white-space:pre">            </span><strong><span style="color:#33cc00;">//TODO 先进行文本修改</span></strong>  
            final ConfigurationSource source = new ConfigurationSource();  
            source.setInputStream(in);  
            Configurator.initialize(null, source);  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        }  

要使用异步写日志的功能,必须引入Disruptor
or
官方建议一般程序员查看的日志改成异步方式,一些运营日志改成同步

Asynchronous Appenders 和 Asynchronous Loggers 区别:
在 节点里添加

  <Async name="Async">
      <AppenderRef ref="MyFile"/>
    </Async>
为Asynchronous Appenders 性能比同步快,比Asynchronous Loggers慢
在loggers节点添加
    <AsyncLogger name="com.foo.Bar" level="trace" includeLocation="true">
      <AppenderRef ref="RandomAccessFile"/>
    </AsyncLogger>
或者添加
<!-- Root Logger -->
<asyncRoot level="DEBUG">
<appender-ref ref="DevLog" />
<appender-ref ref="Console" />
</asyncRoot>

为logger async 用的是无锁并发技术,必须引入Disruptor
测试了下,单线程异步比同步效率提高了1倍。线程越多性能提高越明显。
如果要加上位置信息比如哪个类,第几行,需要设置 includeLocation=”true”
但默认不设置好像也是true,
location 主要包含了如下:
If
one of the layouts is configured with a location-related attribute like HTML locationInfo,
or one of the patterns %C
or $class, %F
or %file, %l
or %location, %L
or %line, %M
or %method, Log4j will take a snapshot of the stack, and walk the stack trace to find the location information.

====================
log4j2最终输出点
AbstractOutputStreamAppender .append(final LogEvent event)

====================
以下要翻译
shutdownHook=”disable”

immediateFlush boolean
When set to true - the default, each write will be followed by a flush. This will guarantee the data is written to disk but could impact performance.

Flushing after every write is only useful when using this appender with synchronous loggers. Asynchronous loggers and appenders will automatically flush at the end of a batch of events, even if immediateFlush is set to false. This also guarantees the data is written to disk but is more efficient.

bufferSize int The buffer size, defaults to 262,144 bytes (256 * 1024).If an integer greater than 0, this causes the appender to buffer log events and flush whenever the buffer reaches this size.
AsyncLogger.RingBufferSize 256 * 1024 Size (number of slots) in the RingBuffer used by the asynchronous logging subsystem. Make this value large enough to deal with bursts of activity. The minimum size is 128. The RingBuffer will be pre-allocated at first use and will never grow or shrink during the life of the system.
Making All Loggers Asynchronous
Requires disruptor-3.0.0.jar or higher on the classpath.

This is simplest to configure and gives the best performance. To make all loggers asynchronous, add the disruptor jar to the classpath and set the system property Log4jContextSelector toorg.apache.logging.log4j.core.async.AsyncLoggerContextSelector.

By default, location is not passed to the I/O thread by asynchronous loggers. If one of your layouts or custom filters needs location information, you need to set “includeLocation=true” in the configuration of all relevant loggers, including the root logger.

A configuration that does not require location might look like:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 智慧社区背景与挑战 随着城市化的快速发展,社区面临健康、安全、邻里关系和服务质量等多方面的挑战。华为技术有限公司提出智慧社区解决方案,旨在通过先进的数字化技术应对这些问题,提升城市社区的生活质量。 2. 技术推动智慧社区发展 技术进步,特别是数字化、无线化、移动化和物联化,为城市社区的智慧化提供了可能。这些技术的应用不仅提高了社区的运行效率,也增强了居民的便利性和安全性。 3. 智慧社区的核心价值 智慧社区承载了智慧城市的核心价值,通过全面信息化处理,实现对城市各个方面的数字网络化管理、服务与决策功能,从而提升社会服务效率,整合社会服务资源。 4. 多层次、全方位的智慧社区服务 智慧社区通过构建和谐、温情、平安和健康四大社区模块,满足社区居民的多层次需求。这些服务模块包括社区医疗、安全监控、情感沟通和健康监测等。 5. 智慧社区技术框架 智慧社区技术框架强调统一平台的建设,设立数据中心,构建基础网络,并通过分层建设,实现平台能力及应用的可持续成长和扩展。 6. 感知统一平台与服务方案 感知统一平台是智慧社区的关键组成部分,通过统一的RFID身份识别和信息管理,实现社区服务的智能化和便捷化。同时,提供社区内外监控、紧急救助服务和便民服务等。 7. 健康社区的构建 健康社区模块专注于为居民提供健康管理服务,通过整合医疗资源和居民接入,实现远程医疗、慢性病管理和紧急救助等功能,推动医疗模式从治疗向预防转变。 8. 平安社区的安全保障 平安社区通过闭路电视监控、防盗报警和紧急求助等技术,保障社区居民的人身和财产安全,实现社区环境的实时监控和智能分析。 9. 温情社区的情感沟通 温情社区着重于建立社区居民间的情感联系,通过组织社区活动、一键呼叫服务和互帮互助平台,增强邻里间的交流和互助。 10. 和谐社区的资源整合 和谐社区作为社会资源的整合协调者,通过统一接入和身份识别,实现社区信息和服务的便捷获取,提升居民生活质量,促进社区和谐。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值