原文地址: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);
  }
}

 

posted on 2015-10-27 11:12  一天不进步,就是退步  阅读(1342)  评论(0编辑  收藏  举报