![JAR search and dependency download from the Maven repository](/logo.png)
ch.qos.logback.classic.android.LogcatAppender Maven / Gradle / Ivy
Show all versions of logback-android-classic Show documentation
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.classic.android;
import android.util.Log;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
/**
* An appender that wraps the native Android logging mechanism (logcat);
* redirects all logging requests to logcat
*
* Note:
* By default, this appender pushes all messages to logcat regardless
* of logcat's own filter settings (i.e., everything is printed). To disable this
* behavior and enable filter-checking, use {@link #setCheckLoggable(boolean)}.
* See the Android Developer Guide for details on adjusting the logcat filter.
*
* See http://developer.android.com/guide/developing/tools/adb.html#filteringoutput
*
* @author Fred Eisele
* @author Anthony Trinh
*/
public class LogcatAppender extends UnsynchronizedAppenderBase {
/**
* Max tag length enforced by Android
* http://developer.android.com/reference/android/util/Log.html#isLoggable(java.lang.String, int)
*/
private static final int MAX_TAG_LENGTH = 23;
private PatternLayoutEncoder encoder = null;
private PatternLayoutEncoder tagEncoder = null;
private boolean checkLoggable = false;
/**
* As in most cases, the default constructor does nothing.
*/
public LogcatAppender() {
}
/**
* Checks that required parameters are set, and if everything is in order,
* activates this appender.
*/
@Override
public void start() {
if ((this.encoder == null) || (this.encoder.getLayout() == null)) {
addError("No layout set for the appender named [" + name + "].");
return;
}
// tag encoder is optional but needs a layout
if (this.tagEncoder != null) {
final Layout> layout = this.tagEncoder.getLayout();
if (layout == null) {
addError("No tag layout set for the appender named [" + name + "].");
return;
}
// prevent stack traces from showing up in the tag
// (which could lead to very confusing error messages)
if (layout instanceof PatternLayout) {
String pattern = this.tagEncoder.getPattern();
if (!pattern.contains("%nopex")) {
this.tagEncoder.stop();
this.tagEncoder.setPattern(pattern + "%nopex");
this.tagEncoder.start();
}
PatternLayout tagLayout = (PatternLayout) layout;
tagLayout.setPostCompileProcessor(null);
}
}
super.start();
}
/**
* Writes an event to Android's logging mechanism (logcat)
*
* @param event
* the event to be logged
*/
public void append(ILoggingEvent event) {
if (!isStarted()) {
return;
}
String tag = getTag(event);
switch (event.getLevel().levelInt) {
case Level.ALL_INT:
case Level.TRACE_INT:
if (!checkLoggable || Log.isLoggable(tag, Log.VERBOSE)) {
Log.v(tag, this.encoder.getLayout().doLayout(event));
}
break;
case Level.DEBUG_INT:
if (!checkLoggable || Log.isLoggable(tag, Log.DEBUG)) {
Log.d(tag, this.encoder.getLayout().doLayout(event));
}
break;
case Level.INFO_INT:
if (!checkLoggable || Log.isLoggable(tag, Log.INFO)) {
Log.i(tag, this.encoder.getLayout().doLayout(event));
}
break;
case Level.WARN_INT:
if (!checkLoggable || Log.isLoggable(tag, Log.WARN)) {
Log.w(tag, this.encoder.getLayout().doLayout(event));
}
break;
case Level.ERROR_INT:
if (!checkLoggable || Log.isLoggable(tag, Log.ERROR)) {
Log.e(tag, this.encoder.getLayout().doLayout(event));
}
break;
case Level.OFF_INT:
default:
break;
}
}
/**
* Gets the pattern-layout encoder for this appender's logcat message
*
* @return the pattern-layout encoder
*/
public PatternLayoutEncoder getEncoder() {
return this.encoder;
}
/**
* Sets the pattern-layout encoder for this appender's logcat message
*
* @param encoder the pattern-layout encoder
*/
public void setEncoder(PatternLayoutEncoder encoder) {
this.encoder = encoder;
}
/**
* Gets the pattern-layout encoder for this appender's logcat tag
*
* @return the pattern encoder
*/
public PatternLayoutEncoder getTagEncoder() {
return this.tagEncoder;
}
/**
* Sets the pattern-layout encoder for this appender's logcat tag
*
* The expanded text of the pattern must be less than 23 characters as
* limited by Android. Layouts that exceed this limit are truncated,
* and a star is appended to the tag to indicate this.
*
* The tagEncoder
result is limited to 22 characters plus a star to
* indicate truncation (%logger{0}
has no length limit in logback,
* but LogcatAppender
limits the length internally). For example,
* if the tagEncoder
evaluated to foo.foo.foo.foo.foo.bar.Test
,
* the tag seen in Logcat would be: foo.foo.foo.foo.foo.ba*
.
* Note that %logger{23}
yields more useful results
* (in this case: f.f.foo.foo.bar.Test
).
*
* @param encoder
* the pattern-layout encoder; specify {@code null} to
* automatically use the logger's name as the tag
*/
public void setTagEncoder(PatternLayoutEncoder encoder) {
this.tagEncoder = encoder;
}
/**
* Sets whether to ask Android before logging a message with a specific
* tag and priority (i.e., calls {@code android.util.Log.html#isLoggable}).
*
* See http://developer.android.com/reference/android/util/Log.html#isLoggable(java.lang.String, int)
*
* @param enable
* {@code true} to enable; {@code false} to disable
*/
public void setCheckLoggable(boolean enable) {
this.checkLoggable = enable;
}
/**
* Gets the enable status of the isLoggable()
-check
* that is called before logging
*
* See http://developer.android.com/reference/android/util/Log.html#isLoggable(java.lang.String, int)
*
* @return {@code true} if enabled; {@code false} otherwise
*/
public boolean getCheckLoggable() {
return this.checkLoggable;
}
/**
* Gets the logcat tag string of a logging event
* @param event logging event to evaluate
* @return the tag string, truncated if max length exceeded
*/
protected String getTag(ILoggingEvent event) {
// format tag based on encoder layout; truncate if max length
// exceeded (only necessary for isLoggable(), which throws
// IllegalArgumentException)
String tag = (this.tagEncoder != null) ? this.tagEncoder.getLayout().doLayout(event) : event.getLoggerName();
if (checkLoggable && (tag.length() > MAX_TAG_LENGTH)) {
tag = tag.substring(0, MAX_TAG_LENGTH - 1) + "*";
}
return tag;
}
}