log4j2的使用教程

因为log4j版本存在bug,公司要求将log4j升级到log4j2,在处理过程中,有一些心得体会,这里分享一下;

升级场景:我们的代码不是web程序,也没有用到spring或者springboot,这里所有的东西都是自己写的,使用的main函数,从main函数直接进入,然后自己填写log4j2.xml,自己读取log4j2.xml,之后将日志打印到指定的目录下;

log4j和log4j2的比较:
(1)log4j中的日志配置信息是保存在.properties的配置文件中,而log4j2的配置文件中保存在.xml配置文件中;
(2)log4j是由logger和appender这两个部分组成,将logger和appender进行绑定,当在logger中输入logger.info则会将对应的日志输入appender设定的文件当中;而对于log4j2来说,一个logger可以绑定多个的appender,即当你在代码中输出日志信息时,可以将这些日志信息输出到多个日志文件中(多个appender),当然在log4j中可能也会存在这种情况,但是在log4j2中这种配置更加的明显;

log4j2的基本知识:
在将log4j2的组成部分时,我们可以从log4j2.xml文件来看,以下是一个log4j2的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="info" monitorInterval="1800">
 <Appenders>
    <RollingFile name="A1" fileName="D:/java/log/TestLog4j2.log" append="true" filePattern="D:/java/log/TestLog4j2-%d{yyyy-MM-dd}.log">
        <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        <Policies>
            <TimeBasedTriggeringPolicy/>
            <SizeBasedTriggeringPolicy size="100 MB"/>
        </Policies>
    </RollingFile>


    <RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log"
                 filePattern="D:/java/log/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
        <!--ThresholdFilter :日志输出过滤-->
        <!--level="info" :日志级别,onMatch="ACCEPT" :级别在info之上则接受,onMismatch="DENY" :级别在info之下则拒绝-->
        <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
        <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        <!-- Policies :日志滚动策略-->
        <Policies>
            <!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点-->
            <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
            <!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
            <SizeBasedTriggeringPolicy size="100 MB"/>
        </Policies>
        <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
        <DefaultRolloverStrategy max="20"/>
    </RollingFile>

</Appenders>
<loggers>
    <root level="INFO">
        <appender-ref ref="RollingFile"/>
    </root>

    <logger name="Test.TestLog4j2" includeLocation="false" additivity="false">
        <AppenderRef ref="A1"/>
    </logger>
</loggers>

可以看到log4j2的具体的配置信息是在configuration下面,其主要有2部分组成,分别是appenders和loggers:
(1)appenders由多个appender组成,每个appender代表一个写入的文件;目前常用的appender有以下几种,分别是:
ConsoleAppnder:将日志输出到命令行
FileAppender:普通地输入到本地文件
RollingFileAppender:对日志文件进行封存
这里参考了这个博客,https://blog.csdn.net/henry115/article/details/78483457, 具体可以去查看

(2)loggers,logger也是由多个logger组成,每个logger都对应的原始类的日志输出方向;

策略:我们的logger和appender是一一对应的,即每个main函数所对应的类都会写入一个新的日志空间当中,但是有一点,就是写入的日志文件是根据传递给main函数的参数而变化的,基于这一点,我们配置了每个类对应的logger,然后将其对接的appender设置为空,与此同时,我们会在配置文件中设置一个模板appender;之后在代码中,我们加载配置信息,然后获取对应类的logger和appender模板,根据appender模板,我们创建一个我们需要的appender(主要是设置appender的名称和appender存储的文件路径),最后将创建的appender和logger进行关联,提供对应的logger给用户;
注:在log4j中可以直接获取logger和appender,并且可以直接修改appender存储的文件路径,而这一特性在log4j2中没有找到,因此我们采用新创建appender,然后将appender和logger进行绑定的方式;

代码:
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>









<loggers>
    <root level="INFO">
    </root>

    <logger name="merchant.analysis.entry.BatchPreOptBySys" includeLocation="false" additivity="false">
    </logger>
    <logger name="merchant.analysis.entry.ExtractTableCtl" includeLocation="false" additivity="false">
    </logger>
    <logger name="merchant.analysis.utils.FileUtils" includeLocation="false" additivity="false">
    </logger>
    <logger name="merchant.analysis.entry.InitExtractTableCtl" includeLocation="false" additivity="false">
    </logger>
    <logger name="merchant.analysis.entry.PtfExtractCtl" includeLocation="false" additivity="false">
    </logger>
    <logger name="merchant.analysis.entry.HiveExport" includeLocation="false" additivity="false">
    </logger>
    <logger name="merchant.analysis.entry.MonSrcTblColumn" includeLocation="false" additivity="false">
    </logger>

</loggers>

代码:

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.OutputStreamManager;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.Property;
@SuppressWarnings("all")
public class LogUtils {

    /**
     * 逻辑:
     * (1)先获取模板的appender
     * (2)然后按照模板创建新的appender
     * (3)最后在logger里添加appender的关联关系
     * @param config
     * @param loggerName
     * @param moduleAppenderName
     * @param appenderName
     * @param logFilePath
     * @return
     */
    public static Logger getLogger(Configuration config, String loggerName, String moduleAppenderName, String appenderName, String logFilePath){
        //通过config获取相应的Appender
        RollingFileAppender appender = config.getAppender(moduleAppenderName);

        //提取Appender的对应信息
        TriggeringPolicy policy = appender.getTriggeringPolicy();
        String filePattern = appender.getFilePattern();
        Filter filter = appender.getFilter();
        ErrorHandler handler = appender.getHandler();
        String immediateFlush = String.valueOf(appender.getImmediateFlush());
        Layout layout = appender.getLayout();
        OutputStreamManager manager = appender.getManager();
        Property[] properties = appender.getPropertyArray();
        LifeCycle.State state = appender.getState();
        String name = appenderName;
        String fileName = logFilePath;

        //通过Appender的模板创建新的Appender,主要是修改Appender的路径信息
        Appender appender2 = RollingFileAppender.createAppender(fileName,filePattern,"true",name,"true",
                "8192",immediateFlush,policy,null,layout,filter,"true","true","",config);
        config.addAppender(appender2);

        //将Appender添加到Logger中,并返回该Logger
        LoggerConfig loggerConfig = config.getLoggerConfig(loggerName);
        loggerConfig.removeAppender(moduleAppenderName);
        loggerConfig.addAppender(appender2, Level.INFO, null);
        LoggerContext loggerContext = config.getLoggerContext();
        Logger logger = loggerContext.getLogger(loggerName);
        return logger;
    }
}

采用这种方式,我们可以将返回一个logger

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值