• logback--How do I configure an AsyncAppender with code? 转载


    原文地址:https://github.com/tony19/logback-android/issues/54

    Please provide an example of how to configure the AsyncAppender with a FileAppender to write to the file in an async way. I am getting many StrictMode policy violations (StrictModeDiskWriteViolation) on every log write to my log file.
    
    Thanks.

    I verified the following config works in Android 4.2.2 without any exceptions.

    <configuration debug="true">
      <property name="LOG_DIR" value="/data/data/com.example/files" />
    
      <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${LOG_DIR}/log.txt</file>
        <encoder>
          <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
      </appender>
    
      <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
      </appender>
    
      <root level="DEBUG">
        <appender-ref ref="ASYNC" />
      </root>
    </configuration>

    Example: Configure by in-memory XML string

    package com.example;
    
    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    
    import org.slf4j.LoggerFactory;
    
    import ch.qos.logback.classic.LoggerContext;
    import ch.qos.logback.classic.joran.JoranConfigurator;
    import ch.qos.logback.core.joran.spi.JoranException;
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    
    public class MainActivity extends Activity {
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        configureLogbackByString();
    
        org.slf4j.Logger log = LoggerFactory.getLogger(MainActivity.class);
        log.info("hello world!!");
      }
    
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
      }
    
      @Override
      protected void onDestroy() {
        super.onDestroy();
    
        // Assume SLF4J is bound to logback-classic in the current environment.
        // This must be called to properly shutdown AsyncAppender and flush logs
        // upon application exit.
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        loggerContext.stop();
      }
    
      String LOGBACK_XML =
          "<configuration debug='true'>" +
              "  <property name='LOG_DIR' value='/data/data/com.example/files' />" +
              "  <appender name='FILE' class='ch.qos.logback.core.FileAppender'>" +
              "    <file>${LOG_DIR}/log.txt</file>" +
              "    <encoder>" +
              "      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern>" +
              "    </encoder>" +
              "  </appender>" +
              "  <appender name='ASYNC' class='ch.qos.logback.classic.AsyncAppender'>" +
              "    <appender-ref ref='FILE' />" +
              "  </appender>" +
              "  <root level='DEBUG'>" +
              "    <appender-ref ref='ASYNC' />" +
              "  </root>" +
              "</configuration>";
    
      private void configureLogbackByString() {
        // reset the default context (which may already have been initialized)
        // since we want to reconfigure it
        LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
        lc.reset();
    
        JoranConfigurator config = new JoranConfigurator();
        config.setContext(lc);
    
        InputStream stream = new ByteArrayInputStream(LOGBACK_XML.getBytes());
        try {
          config.doConfigure(stream);
        } catch (JoranException e) {
          e.printStackTrace();
        }
      }
    }

    Example: Configure with direct calls into logback

    package com.example;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import ch.qos.logback.classic.AsyncAppender;
    import ch.qos.logback.classic.LoggerContext;
    import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
    import ch.qos.logback.classic.spi.ILoggingEvent;
    import ch.qos.logback.core.FileAppender;
    import ch.qos.logback.core.util.StatusPrinter;
    
    public class MainActivity extends Activity {
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        configureLogbackDirectly();
    
        org.slf4j.Logger log = LoggerFactory.getLogger(MainActivity.class);
        log.info("hello world!!");
    
      }
    
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
      }
    
      @Override
      protected void onDestroy() {
        super.onDestroy();
    
        // assume SLF4J is bound to logback-classic in the current environment
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        loggerContext.stop();
      }
    
      private void configureLogbackDirectly() {
        // reset the default context (which may already have been initialized)
        // since we want to reconfigure it
        LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
        lc.reset();
    
        // setup FileAppender
        PatternLayoutEncoder encoder1 = new PatternLayoutEncoder();
        encoder1.setContext(lc);
        encoder1.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n");
        encoder1.start();
    
        FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>();
        fileAppender.setContext(lc);
        fileAppender.setName("FILE");
        fileAppender.setFile(this.getFileStreamPath("log.txt").getAbsolutePath());
        fileAppender.setEncoder(encoder1);
        fileAppender.start();
    
        AsyncAppender asyncAppender = new AsyncAppender();
        asyncAppender.setContext(lc);
        asyncAppender.setName("ASYNC");
    
        // UNCOMMENT TO TWEAK OPTIONAL SETTINGS
    //    // excluding caller data (used for stack traces) improves appender's performance
    //    asyncAppender.setIncludeCallerData(false);
    //    // set threshold to 0 to disable discarding and keep all events
    //    asyncAppender.setDiscardingThreshold(0);
    //    asyncAppender.setQueueSize(256);
    
        asyncAppender.addAppender(fileAppender);
        asyncAppender.start();
    
        // add the newly created appenders to the root logger;
        // qualify Logger to disambiguate from org.slf4j.Logger
        ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
        root.addAppender(asyncAppender);
    
        StatusPrinter.print(lc);
      }
    }
  • 相关阅读:
    巧用nginx屏蔽对用户不可见的文件
    关于之前我的主页页面加载很慢的问题
    学习Entity Framework 中的Code First
    理解POCO
    浅谈依赖注入
    从Microsoft.AspNet.Identity看微软推荐的一种MVC的分层架构
    ASP.NET Identity V2
    泛型约束
    C# Serializable
    C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
  • 原文地址:https://www.cnblogs.com/davidwang456/p/4913618.html
Copyright © 2020-2023  润新知