Giter Club home page Giter Club logo

logback-android's Introduction

logback-android

v1.1.1-2

Overview

logback-android brings the power of logback to Android. This library provides a highly configurable logging framework for Android apps, supporting multiple log destinations simultaneously:

  • files
  • SQLite databases
  • logcat
  • sockets
  • syslog
  • email

Runs on Android 2.1 or higher.

Quick Start

  1. Add logback-android and slf4j-api to your project class path.
  2. Configure logback-android using either ${project-root}/assets/logback.xml or in-code statements. Otherwise, logging is silently disabled.
  3. Use slf4j-api in your application to write logging statements as shown in the example below.

Example:

package com.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // SLF4J
    Logger log = LoggerFactory.getLogger(MainActivity.class);
    log.info("hello world");
  }
}

Download

OR Maven users can simply add these dependencies to pom.xml:

<dependency>
  <groupId>com.github.tony19</groupId>
  <artifactId>logback-android-core</artifactId>
  <version>1.1.1-2</version>
</dependency>
<dependency>
  <groupId>com.github.tony19</groupId>
  <artifactId>logback-android-classic</artifactId>
  <version>1.1.1-2</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.6</version>
</dependency>

Contents

Configuration via XML

logback-android can be configured simply by creating assets/logback.xml, containing configuration XML. This file is read automatically upon loading the first logger from your code. Additional code configuration is not necessary.

Example 1: Basic configuration (single destination)

<configuration>
  <!-- Create a file appender for a log in the application's data directory -->
  <appender name="file" class="ch.qos.logback.core.FileAppender">
    <file>/data/data/com.example/files/log/foo.log</file>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Write INFO (and higher-level) messages to the log file -->
  <root level="INFO">
    <appender-ref ref="file" />
  </root>
</configuration>

Example 2: Advanced configuration (multiple destinations)

<configuration>
  <property name="LOG_DIR" value="/data/data/com.example/files" />

  <!-- Create a logcat appender -->
  <appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
    <encoder>
      <pattern>%msg</pattern>
    </encoder>
  </appender>

  <!-- Create a file appender for TRACE-level messages -->
  <appender name="TraceLog" class="ch.qos.logback.core.FileAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>TRACE</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>

    <file>${LOG_DIR}/trace.log</file>

    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Create a file appender for DEBUG-level messages -->
  <appender name="DebugLog" class="ch.qos.logback.core.FileAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>DEBUG</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>

    <file>${LOG_DIR}/debug.log</file>

    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <!-- Write TRACE messages from class A to its own log -->
  <logger name="com.example.A" level="TRACE">
    <appender-ref ref="TraceLog" />
  </logger>

  <!-- Write DEBUG messages from class B to its own log -->
  <logger name="com.example.B" level="DEBUG">
    <appender-ref ref="DebugLog" />
  </logger>

  <!-- Write INFO (and higher-level) messages to logcat -->
  <root level="INFO">
    <appender-ref ref="logcat" />
  </root>
</configuration>

AndroidManifest.xml

logback-android also supports configuration XML within your application's AndroidManifest.xml (requires setting up your initialization search path). Simply put the configuration XML inside the <manifest>/<logback> element as shown in the example below.

Example:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <logback>
        <configuration>
          <appender
              name="LOGCAT"
              class="ch.qos.logback.classic.android.LogcatAppender" >
              <tagEncoder>
                  <pattern>%logger{0}</pattern>
              </tagEncoder>
              <encoder>
                  <pattern>[ %thread ] %msg%n</pattern>
              </encoder>
          </appender>

          <root level="WARN" >
              <appender-ref ref="LOGCAT" />
          </root>
        </configuration>
    </logback>

</manifest>
Android Lint Preferences

If you enter configuration XML in AndroidManifest.xml, the Android SDK r21+ emits an error message by default due to the android namespace prefix missing from the logback-android configuration elements. To resolve this, change the Severity level for MissingPrefix in your project's Android Lint preferences from Eclipse.

Initialization search path

Even though assets/logback.xml is the first configuration loaded, this file could include other configuration files from within your JAR or from the host filesystem. This is achieved with the <includes> tag, containing a list of optional <include> tags (i.e., no error is thrown for nonexistent resources/files). The first <include> tag that points to an existent resource/file causes the remainder of the list to be ignored.

Example:

<configuration>
  <includes>
    <include file="/sdcard/foo.xml"/>
    <include resource="assets/config/test.xml"/>
    <include resource="AndroidManifest.xml"/>
  </includes>
</configuration>

Prior to v1.0.8-1, the initialization search path was hard-coded, and that can be recreated with this configuration:

<configuration>
  <includes>
    <include file="/sdcard/logback/logback-test.xml"/>
    <include file="/sdcard/logback/logback.xml"/>
    <include resource="AndroidManifest.xml"/>
    <include resource="assets/logback-test.xml"/>
    <include resource="assets/logback.xml"/>
  </includes>
</configuration>

Configuration in Code

If you prefer code-based configuration instead of the XML method above, you can use the logback classes directly to initialize logback-android as shown in the following examples. Note the direct usage of logback classes removes the advantage of the facade provided by SLF4J.

Example: Uses BasicLogcatConfigurator to redirect to logcat

package com.example;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.android.BasicLogcatConfigurator;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    BasicLogcatConfigurator.configureDefaultContext();

    org.slf4j.Logger log = LoggerFactory.getLogger(MainActivity.class);
    for (int i = 0; i < 10; i++) {
      log.info("hello world");
    }
  }

}

Example: Configures appenders directly

package com.example;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.android.LogcatAppender;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;

import android.os.Bundle;
import android.app.Activity;

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);
    for (int i = 0; i < 10; i++) {
      log.info("hello world");
    }
  }

  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{36} - %msg%n");
    encoder1.start();

    FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>();
    fileAppender.setContext(lc);
    fileAppender.setFile(this.getFileStreamPath("app.log").getAbsolutePath());
    fileAppender.setEncoder(encoder1);
    fileAppender.start();

    // setup LogcatAppender
    PatternLayoutEncoder encoder2 = new PatternLayoutEncoder();
    encoder2.setContext(lc);
    encoder2.setPattern("[%thread] %msg%n");
    encoder2.start();

    LogcatAppender logcatAppender = new LogcatAppender();
    logcatAppender.setContext(lc);
    logcatAppender.setEncoder(encoder2);
    logcatAppender.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(fileAppender);
    root.addAppender(logcatAppender);
  }
}

Example: Configures by XML file

// snip…

private void configureLogbackByFilePath() {
  // 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);

  try {
    config.doConfigure("/path/to/config.xml");
  } catch (JoranException e) {
    e.printStackTrace();
  }
}

Example: Configures by in-memory XML string

// snip…

static final String LOGBACK_XML =
    "<configuration>" +
      "<appender name='FILE' class='ch.qos.logback.core.FileAppender'>" +
         "<file>foo.log</file>" +
         "<append>false</append>" +
         "<encoder>" +
           "<pattern>%-4r [%t] %-5p %c{35} - %m%n</pattern>" +
         "</encoder>" +
       "</appender>" +
       "<root level='DEBUG'>" +
         "<appender-ref ref='FILE' />" +
       "</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();
  }
}

ProGuard

When optimizing your application with ProGuard, include the following rules to prevent logback-android and SLF4J calls from being removed (unless that's desired):

-keep class ch.qos.** { *; }
-keep class org.slf4j.** { *; }
-keepattributes *Annotation*

If you don't use the mailing features of logback (i.e., the SMTPAppender), you might encounter an error while exporting your app with ProGuard. To resolve this, add the following rule:

-dontwarn ch.qos.logback.core.net.*

Other Documentation

For help with using logback-android, ask the Logback User mailing list.

Build

logback-android is built with Apache Maven 2+. Use these commands to create the uber JAR (with debug symbols).

git clone git://github.com/tony19/logback-android.git
cd logback-android
./makejar.sh

The jar would be in: ./target/logback-android-<version>.jar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.