Source

GWSLAE /

Filename Size Date modified Message
.settings
libs
res
src/org/bitbucket/fredgrott/gwslae
356 B
28 B
809 B
418 B
781 B
584 B
10.2 KB

GWSLAE

Android Project Library to support using LogbackAndroid logging instead of the default android logging system. With great power comes great respect, please respect your application users by setting proper controls such as ensuring that logs are only saved as files in the CacheDir to ensure only your application can access them.

License

Modications under Apache 2.0 License, original code from Logbackandroid examples is under GNU LPL or EPL.

Credits

Fred Grott(GrottWorkShop)

LogbackAndroid Tips

Short tutorial on logback in the android app dev context. Basically, in the Logback tutorial when they are using individual logback config files we can but that in the main one and not use joran to hav to read inanother config file.

logpath Workspace Setting and System.properties

We can use in the file element of the logback config file to set a logpath entry to our workspace: <code> <file>${logpath:-}logfile.log</file> </code> Than in our first activity called or the application class: <code> System.properties("logpath", mylogpath); </code> mylogpath would be setusing Environment calls to get the CacheDir path.

Ceki, project leadof Logback states not use the ContextInitializer but to use something like:

<code> LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

RollingFileAppender rfAppender = new RollingFileAppender();
rfAppender.setContext(loggerContext);
rfAppender.setFile("testFile.log");
FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy();
rollingPolicy.setContext(loggerContext);
// rolling policies need to know their parent
// it's one of the rare cases, where a sub-component knows about its parent
rollingPolicy.setParent(rfAppender);
rollingPolicy.setFileNamePattern("testFile.%i.log.zip");
rollingPolicy.start();

SizeBasedTriggeringPolicy triggeringPolicy = new ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy();
triggeringPolicy.setMaxFileSize("5MB");
triggeringPolicy.start();

PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext);
encoder.setPattern("%-4relative [%thread] %-5level %logger{35} - %msg%n");
encoder.start();

rfAppender.setEncoder(encoder);
rfAppender.setRollingPolicy(rollingPolicy);
rfAppender.setTriggeringPolicy(triggeringPolicy);

rfAppender.start();

// attach the rolling file appender to the logger of your choice
Logger logbackLogger = loggerContext.getLogger("Main");
logbackLogger.addAppender(rfAppender);

// OPTIONAL: print logback internal status messages
StatusPrinter.print(loggerContext);

// log something
logbackLogger.debug("hello");

</code>

SO post: setting-logback-appender-path-programmatically

CheckLoggable

You can set appenders as checkloggable: <code> <checkLoggable>false</checkLoggable> </code>

For example, LOGCAT appender would be set false while log to file would be set true.

file name as datetime stamped

File appenders have a FileNamePattern element thus we can set that as: <code> ${log_path:-}agent.%d{yyyy-MM-dd}.%i.zip. </code> The i variable is the counter.

Syslog with StrictMode

Settings to use Syslog with SrictMode are:

<code> StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads().detectDiskWrites().detectNetwork() .penaltyLog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects().detectLeakedClosableObjects() .penaltyLog().build());

super.onCreate(savedInstanceState);
logger = LoggerFactory.getLogger(SyslogLogbackActivity.class);
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
setContentView(R.layout.main);
logger.debug("Hello Test Strict Mode");

</code>

With the logback configuration file settigns being:

<code> < configuration debug="true" > < appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender" > < syslogHost>AAA.REMOVED.com < port>11111 < facility>AUTH < suffixPattern>[%thread] %logger %msg </ appender > < root level="DEBUG" > < appender-ref ref="SYSLOG" /> </ root > </ configuration > </code>

Log Separation

In Android we of course do not have JNDI and thus cannot use the JNDI context selector and appenders to sepearate log concerns.

In android we would separate logging concerns by using the logger name context, ie have logger named by package name of activity.

On the Instrumented testing side we can use MDC filter event classes to separate out our test loggign concenrs according to: -plain unit logic tests -basic robotium tests -robogherk story type tests

In the case of running something like the sdkcontroller apk or say the openintents GPS simulator we could also log that into a separate logging concern.

File output formatting

We will use HTMLLayout:

<code> <configuration debug="true"> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%relative%thread%mdc%level%logger%msg</pattern> <cssBuilder class="ch.qos.logback.classic.html.UrlCssBuilder"> <!-- url where the css file is located --> <url>http://...</url>; </cssBuilder> </layout> </encoder> <file>test.html</file> </appender>

<root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration> </code>

Notice no spaces in pattern element items and the CssBuilder entry. Not sure if css file url entry needs to point to css in assets folder, probably does as that is the most logical place to put the css file.

One could also set a Log4j XML output since that would probably be more integrateable with CI builder tools:

<code> <configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>test.xml</file> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="ch.qos.logback.classic.log4j.XMLLayout"> <locationInfo>true</locationInfo> </layout> </encoder> </appender>

<root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration> </code>

HtmlToConsole

<code> <configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <cssBuilder class="ch.qos.logback.classic.html.UrlCssBuilder"> <url>path_to_StyleFile.css</url> </cssBuilder>
<pattern>%-4relative [%thread] %-5level - %msg%n</pattern> </layout> </encoder> </appender>

<root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration> </code>

TimestampContextBirth

<code> <configuration>

<!-- Insert the logger context bith date formatted as "yyyyMMdd'T'HHmmss" under the key "bySecond" into the logger context. This value will be available to all subsequent configuration elements. --> <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" timeReference="contextBirth"/>

<appender name="FILE" class="ch.qos.logback.core.FileAppender"> <!-- use the previously created timestamp to create a uniquely named log file --> <file>log-${bySecond}.txt</file> <encoder> <pattern>%logger{35} - %msg%n</pattern> </encoder> </appender>

<root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration> </code>

RollingSizeAndTime

<code> <configuration>

<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>mylog.txt</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 100MB --> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%msg%n</pattern> </encoder> </appender>

<root level="debug"> <appender-ref ref="ROLLING" /> </root>

</configuration> </code>

ContextName

<code> <configuration>

<contextName>myAppName</contextName>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern> </encoder> </appender>

<root level="debug"> <appender-ref ref="STDOUT" /> </root>

</configuration> </code>

Multiple Appenders

<code> <configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>myApp.log</file> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern> </encoder> </appender>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
  <pattern>%msg%n</pattern>
</encoder>
</appender>

<root level="debug">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
</root>

</configuration> </code>

Highlighted

<code> <configuration debug="true"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- On Windows machines setting withJansi to true enables ANSI color code interpretation by the Jansi library. This requires org.fusesource.jansi:jansi:1.8 on the class path. Note that Unix-based operating systems such as Linux and Mac OS X support ANSI color codes by default. codes.--> <withJansi>false</withJansi> <encoder> <pattern>%date [%thread] %highlight(%-5level) %cyan(%-15logger{15}) %X - %msg %n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration> </code>