Android中使用log4j2

Log4j2 的配置、使用

最近公司让调研log4j2在Android中的使用,在网上查了很多资料,在这做个总结,一起学习,参考了许多文章,文末都有链接,感谢大佬们的文章
Log4j2 简介

log4j2是log4j 1.x 的升级版,2015年5月,Apache宣布log4j1.x 停止更新。最新版:官网下载

log4j2参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:

  1. 异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。

  2. 性能提升:log4j2相较于log4j 1和logback都具有很明显的性能提升。

  3. 自动重载配置:参考了logback的设计,提供自动刷新参数配置,可以动态的修改日志的级别而不需要重启应用。

  4. 无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

Log4j2 配置

log4j2 既可以采用xml方式配置,也可采用代码的方式配置

在本文中是实现日志过滤,然后存入文件,按照一定大小分割文件。

  • 添加依赖包
    implementation 'org.apache.logging.log4j:log4j-api:2.14.0'
    implementation 'org.apache.logging.log4j:log4j-core:2.14.0'
    

直接这样添加会报错,网上给出的解决办法:

app gradle中添加一下代码:

packagingOptions {
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
}

不懂这是什么意思但是添加上就没问题了,知道的在下方评论一起学习吧。

  • xml方式配置:

    先上代码,xml文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration status="debug" >
        <appenders>
            <!--这个输出控制台的配置-->
            <console name="Stdout" target="SYSTEM_OUT">
                <!--输出日志的格式-->
                <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
                <PatternLayout pattern="%d  [%t] %-5level: %msg%n%throwable"/>
            </console>
            <RollingFile name="rolling" fileName="mnt/sdcard/rolling.log"
                filePattern="mnt/sdcard/rolling-%d{yyyy-MM-dd}-%i.txt" >
                <MarkerFilter marker="NAME" onMatch="ACCEPT" onMismatch="DENY"/>
                <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%c{1}-%p %l] %m%n"/>
                <Policies>
                    <!-- 基于指定文件大小的滚动策略,设置日志文件满1MB后打包,,size属性用来定义每个日志文件的大小 -->
                    <SizeBasedTriggeringPolicy size="1M"/>
                </Policies>
                <!-- DefaultRolloverStrategy属性如不设置,默认最多7个文件,这里设置20 -->
                <DefaultRolloverStrategy max="20"/>
            </RollingFile>
    
        </appenders>
    
    
        <loggers>
            <!--记录执行的HQL语句 -->
            <!-- additivity="false"是为了避免日志在root里再次输出 -->
            <Logger name="TestLogger" level="debugr" additivity="false">
                <AppenderRef ref="rolling" />
            </Logger>
            <root level="debug">
                <AppenderRef ref="rolling"/>
            </root>
        </loggers>
    </configuration>
    
    • 配置文件节点解析

      根节点Configuration

      1. 有两个属性:status和monitorinterval

        1. status用来指定log4j本身的打印日志的级别.
        2. monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s.
      2. 有两个子节点:Appenders和Loggers(表明可以定义多个Appender和Logger).

        1. Appenders节点,常见的有三种子节点:Console、RollingFile、File.

          1. Console节点用来定义输出到控制台的Appender.

            name:指定Appender的名字.

            target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT. PatternLayout:输出格式,不设置默认为:%m%n.

          2. File节点用来定义输出到指定位置的文件的Appender.

            name:指定Appender的名字.

            fileName:指定输出日志的目的文件带全路径的文件名.

            PatternLayout:输出格式,不设置默认为:%m%n.

            append:当为true时,会在之前的日志里面续加内容,而不清空

          3. RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender. name:指定Appender的名字.

            fileName:指定输出日志的目的文件带全路径的文件名.

            filePattern:指定新建日志文件的名称格式.

            PatternLayout:输出格式,不设置默认为:%m%n.

            Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志. TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。

            modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.

            SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.

            DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。

        2. Loggers节点,常见的有两种:Root和Logger.

          1. Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出

            level:日志输出级别,共有8个级别,见下面注

            AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.

          2. Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。 level:日志输出级别,共有8个级别,见下面注

            name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点. AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了, 那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity=“false” 只在自定义的Appender中进行输出。

      3. MarkerFilter: marker过滤tag的标志

      4. onMatchonMismatch都有三个属性值,分别为AcceptDENYNEUTRAL

        分别介绍这两个配置项的三个属性值:

        onMatch=“ACCEPT” 表示匹配该级别及以上
        onMatch=“DENY” 表示不匹配该级别及以上
        onMatch=“NEUTRAL” 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上
        onMismatch=“ACCEPT” 表示匹配该级别以下
        onMismatch=“NEUTRAL” 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的
        onMismatch=“DENY” 表示不匹配该级别以下的

      ps:关于日志level.共有8个级别

      ​ 按照从低到高为:All < **Trace **< Debug <Info < Warn < **Error **< **Fatal **< OFF.

      1.       **All**:最低等级的,用于打开所有日志记录.
      
      2.      **Trace**:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关
      3.      **Debug**:指出细粒度信息事件对调试应用程序是非常有帮助的.    
      4.      **Info**:消息在粗粒度级别上突出强调应用程序的运行过程.        
      5.      **Warn**:输出警告及warn以下级别的日志.    
      6.      **Error**:输出错误信息日志.
      7.      **Fatal**:输出每个严重的错误事件将会导致应用程序的退出的日志.        
      8.      **OFF**:最高等级的,用于关闭所有日志记录.        
      

      程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少,默认会打印ErrorFatal等级的日志信息

    使用配置文件:
    • 将xml文件放在asstes文件夹下:

      class:

      private static final Marker NAME = MarkerManager.getMarker("NAME");
      private static final Marker ERVIN = MarkerManager.getMarker("ERVIN");
      
      ExtendedLogger logger=null;
      InputStream open = null;
      try {
          open = getAssets().open("log4j2.xml");
          ConfigurationSource source = new ConfigurationSource(open);
          LoggerContext initialize = Configurator.initialize(null, source);
          logger =  initialize.getLogger(Main.class);
      } catch (IOException e) {
          e.printStackTrace();
          try {
              open.close();
          } catch (IOException ioException) {
              ioException.printStackTrace();
          }
      }
      while (true) {
          logger.error("error");
          logger.debug("debug");
          logger.fatal("fatal");
          logger.warn("warn");
          logger.info("info");
          logger.trace("trace");
      
          logger.log(Level.DEBUG, NAME, "marker debug");
          logger.log(Level.ERROR, ERVIN, "marker error");
          logger.log(Level.FATAL, NAME, "marker fatal");
          logger.log(Level.WARN, ERVIN, "marker warn");
          logger.log(Level.INFO, NAME, "marker info");
          logger.log(Level.TRACE, NAME, "marker trace");
      }
      
    • 将xml文件放在设备的内存中:

      class:

      LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
      File file = new File("/sdcard/log4j2.xml");
      Log.d(TAG, "onCreate: " + file.exists());
      if (file == null) {
          Log.d(TAG, "onCreate: ==========");
      }
      context.setConfigLocation(file.toURI());
      ExtendedLogger logger = context.getLogger(Main.class);
      

    这两种方式其实道理都一样,读出xml配置到LoggerContext中然后通过getLogger()方法得到ExtendedLogger然后就可以打印信息了。只要注意怎么读取xml文件就行了。

  • 使用代码的方式配置

    直接上代码:

    ConfigurationBuilder< BuiltConfiguration > builder = ConfigurationBuilderFactory.newConfigurationBuilder();
    builder.setStatusLevel( Level.DEBUG);
    builder.setConfigurationName("RollingBuilder");
    builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
            .addAttribute("level", Level.TRACE));//过滤日志级别的
    
    // create a console appender
    AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
            ConsoleAppender.Target.SYSTEM_OUT);
    appenderBuilder.add(builder.newLayout("PatternLayout")
            .addAttribute("pattern", "%d  [%t] %-5level: %msg%n%throwable"));
    builder.add( appenderBuilder );
    
    // create a rolling file appender
    LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
            .addAttribute("pattern", "%d  [%t] %-5level: %msg%n");
    ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
            //.addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))//每天凌晨清理文件
            .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "1M"));
    ComponentBuilder defaultRolloverStrategy = builder.newComponent("DefaultRolloverStrategy")
            .addAttribute("max",20);//设置文件夹下有几个日志文件
    appenderBuilder = builder.newAppender("rolling", "RollingFile")
            .addAttribute("fileName", "mnt/sdcard/rolling.log")
            .addAttribute("filePattern", "mnt/sdcard/rolling-%d{yyyy-MM-dd}-%i.txt")
            .add(builder.newFilter("MarkerFilter", Filter.Result.ACCEPT, Filter.Result.DENY)
            .addAttribute("marker", "NAME"))//过滤"NAME"的log
            .add(layoutBuilder)
            .addComponent(triggeringPolicy)
            .addComponent(defaultRolloverStrategy);
    
    builder.add(appenderBuilder);
    
    // create the new logger
    builder.add( builder.newLogger( "TestLogger", Level.DEBUG )
            .add( builder.newAppenderRef( "rolling" ) )
            .addAttribute( "additivity", false ) );
    builder.add( builder.newRootLogger( Level.DEBUG )
            .add( builder.newAppenderRef( "rolling" ) ) );
    LoggerContext ctx = Configurator.initialize(builder.build());
    ExtendedLogger logger = ctx.getLogger(MainActivity.class);
    

其实这代码配置也是和xml配置是一一对应的,ThresholdFiltertargetPatternLayout…对照一下这些关键词就能懂了。

日志信息格式中符号所代表的含义

(1)-X号: X信息输出时左对齐。
(2)%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
(3)%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921。
(4)%r: 输出自应用启动到输出该log信息耗费的毫秒数。
(5)
%c
: 输出日志信息所属的类目,通常就是所在类的全名。
(6)%t: 输出产生该日志事件的线程名。
(7)%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)。
(8)%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
(9)%%: 输出一个"%“字符。
(10)%F: 输出日志消息产生时所在的文件名称。
(11)%L: 输出代码中的行号。
(12)%m: 输出代码中指定的消息,产生的日志具体信息。
(13)%n: 输出一个回车换行符,Windows平台为”\r\n",Unix平台为"\n"输出日志信息换行。

参考文章地址:从assets中读取xml

Android中使用Log4j及配置说明

Log4j2进阶使用(按大小时间备份日志)

log4j2的配置以及代码实现

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值