Original address: HTTPS://GITHUB.COM/TONY19/LOGBACK-ANDROID/ISSUES/54
Provide an example of what to configure the Asyncappender with a fileappender to write to the file in an async. 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.
<ConfigurationDebug= "true"> < Propertyname= "Log_dir"value= "/data/data/com.example/files" /> <Appendername= "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> <Appendername= "ASYNC"class= "Ch.qos.logback.classic.AsyncAppender"> <Appender-refref= "FILE" /> </Appender> <Root Level= "DEBUG"> <Appender-refref= "ASYNC" /> </Root></Configuration>Example:configure by In-memory XML string
Packagecom.example;ImportJava.io.ByteArrayInputStream;ImportJava.io.InputStream;Importorg.slf4j.LoggerFactory;ImportCh.qos.logback.classic.LoggerContext;ImportCh.qos.logback.classic.joran.JoranConfigurator;Importch.qos.logback.core.joran.spi.JoranException;Importandroid.app.Activity;ImportAndroid.os.Bundle;ImportAndroid.view.Menu; Public classMainactivityextendsActivity {@Overrideprotected voidonCreate (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 BooleanOncreateoptionsmenu (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; } @Overrideprotected voidOnDestroy () {Super. OnDestroy (); //assume slf4j is bound-logback-classic in the current environment. //This must is 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> "+" </appende R> "+" <appender name= ' ASYNC ' class= ' ch.qos.logback.classic.AsyncAppender ' > ' + ' <appen Der-ref ref= ' FILE '/> "+" </appender> "+" <root level= ' DEBUG ' > ' + ' <a Ppender-ref ref= ' ASYNC '/> "+" </root> "+" </configuration> "; Private voidconfigurelogbackbystring () {//Reset the default context (which may already has been initialized)//since we want to reconfigure itLoggercontext LC =(Loggercontext) loggerfactory.getiloggerfactory (); Lc.reset (); Joranconfigurator Config=NewJoranconfigurator (); Config.setcontext (LC); InputStream Stream=NewBytearrayinputstream (Logback_xml.getbytes ()); Try{config.doconfigure (stream); } Catch(joranexception e) {e.printstacktrace (); } }}Example:configure with direct calls to Logback
Packagecom.example;ImportOrg.slf4j.Logger;Importorg.slf4j.LoggerFactory;Importandroid.app.Activity;ImportAndroid.os.Bundle;ImportAndroid.view.Menu;ImportCh.qos.logback.classic.AsyncAppender;ImportCh.qos.logback.classic.LoggerContext;ImportCh.qos.logback.classic.encoder.PatternLayoutEncoder;Importch.qos.logback.classic.spi.ILoggingEvent;ImportCh.qos.logback.core.FileAppender;ImportCh.qos.logback.core.util.StatusPrinter; Public classMainactivityextendsActivity {@Overrideprotected voidonCreate (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 BooleanOncreateoptionsmenu (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; } @Overrideprotected voidOnDestroy () {Super. OnDestroy (); //assume slf4j is bound-logback-classic in the current environmentLoggercontext Loggercontext =(Loggercontext) loggerfactory.getiloggerfactory (); Loggercontext.stop (); } Private voidconfigurelogbackdirectly () {//Reset the default context (which may already has been initialized)//since we want to reconfigure itLoggercontext LC =(Loggercontext) loggerfactory.getiloggerfactory (); Lc.reset (); //Setup FileappenderPatternlayoutencoder Encoder1 =NewPatternlayoutencoder (); Encoder1.setcontext (LC); Encoder1.setpattern ("%d{hh:mm:ss. SSS} [%thread]%-5level%logger{35}-%msg%n "); Encoder1.start (); Fileappender<ILoggingEvent> Fileappender =NewFileappender<iloggingevent>(); Fileappender.setcontext (LC); Fileappender.setname ("FILE"); Fileappender.setfile ( This. Getfilestreampath ("Log.txt"). GetAbsolutePath ()); Fileappender.setencoder (Encoder1); Fileappender.start (); Asyncappender Asyncappender=NewAsyncappender (); 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 (n);Asyncappender.addappender (Fileappender); Asyncappender.start (); //Add the newly created appenders to the root logger; //qualify Logger to disambiguate from Org.slf4j.LoggerCh.qos.logback.classic.Logger root =(Ch.qos.logback.classic.Logger) Loggerfactory.getlogger (logger.root_logger_name); Root.addappender (Asyncappender); Statusprinter.print (LC); }}
Logback--how do I Configure a asyncappender with code? Reproduced