blob: be60e748e6c9e44f38701726856407c724e465cf [file] [log] [blame]
package org.wordpress.android.util;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* simple wrapper for Android log calls, enables recording and displaying log
*/
public class AppLog {
// T for Tag
public enum T {READER, EDITOR, MEDIA, NUX, API, STATS, UTILS, NOTIFS, DB, POSTS, COMMENTS, THEMES, TESTS, PROFILING,
SIMPERIUM, SUGGESTION, MAIN, SETTINGS, PLANS, PEOPLE}
public static final String TAG = "WordPress";
public static final int HEADER_LINE_COUNT = 2;
private static boolean mEnableRecording = false;
private AppLog() {
throw new AssertionError();
}
/**
* Capture log so it can be displayed by AppLogViewerActivity
* @param enable A boolean flag to capture log. Default is false, pass true to enable recording
*/
public static void enableRecording(boolean enable) {
mEnableRecording = enable;
}
/**
* Sends a VERBOSE log message
* @param tag Used to identify the source of a log message.
* It usually identifies the class or activity where the log call occurs.
* @param message The message you would like logged.
*/
public static void v(T tag, String message) {
message = StringUtils.notNullStr(message);
Log.v(TAG + "-" + tag.toString(), message);
addEntry(tag, LogLevel.v, message);
}
/**
* Sends a DEBUG log message
* @param tag Used to identify the source of a log message.
* It usually identifies the class or activity where the log call occurs.
* @param message The message you would like logged.
*/
public static void d(T tag, String message) {
message = StringUtils.notNullStr(message);
Log.d(TAG + "-" + tag.toString(), message);
addEntry(tag, LogLevel.d, message);
}
/**
* Sends a INFO log message
* @param tag Used to identify the source of a log message.
* It usually identifies the class or activity where the log call occurs.
* @param message The message you would like logged.
*/
public static void i(T tag, String message) {
message = StringUtils.notNullStr(message);
Log.i(TAG + "-" + tag.toString(), message);
addEntry(tag, LogLevel.i, message);
}
/**
* Sends a WARN log message
* @param tag Used to identify the source of a log message.
* It usually identifies the class or activity where the log call occurs.
* @param message The message you would like logged.
*/
public static void w(T tag, String message) {
message = StringUtils.notNullStr(message);
Log.w(TAG + "-" + tag.toString(), message);
addEntry(tag, LogLevel.w, message);
}
/**
* Sends a ERROR log message
* @param tag Used to identify the source of a log message.
* It usually identifies the class or activity where the log call occurs.
* @param message The message you would like logged.
*/
public static void e(T tag, String message) {
message = StringUtils.notNullStr(message);
Log.e(TAG + "-" + tag.toString(), message);
addEntry(tag, LogLevel.e, message);
}
/**
* Send a ERROR log message and log the exception.
* @param tag Used to identify the source of a log message.
* It usually identifies the class or activity where the log call occurs.
* @param message The message you would like logged.
* @param tr An exception to log
*/
public static void e(T tag, String message, Throwable tr) {
message = StringUtils.notNullStr(message);
Log.e(TAG + "-" + tag.toString(), message, tr);
addEntry(tag, LogLevel.e, message + " - exception: " + tr.getMessage());
addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr));
}
/**
* Sends a ERROR log message and the exception with StackTrace
* @param tag Used to identify the source of a log message. It usually identifies the class or activity where the log call occurs.
* @param tr An exception to log to get StackTrace
*/
public static void e(T tag, Throwable tr) {
Log.e(TAG + "-" + tag.toString(), tr.getMessage(), tr);
addEntry(tag, LogLevel.e, tr.getMessage());
addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr));
}
/**
* Sends a ERROR log message
* @param tag Used to identify the source of a log message. It usually identifies the class or activity where the log call occurs.
* @param volleyErrorMsg
* @param statusCode
*/
public static void e(T tag, String volleyErrorMsg, int statusCode) {
if (TextUtils.isEmpty(volleyErrorMsg)) {
return;
}
String logText;
if (statusCode == -1) {
logText = volleyErrorMsg;
} else {
logText = volleyErrorMsg + ", status " + statusCode;
}
Log.e(TAG + "-" + tag.toString(), logText);
addEntry(tag, LogLevel.w, logText);
}
// --------------------------------------------------------------------------------------------------------
private static final int MAX_ENTRIES = 99;
private enum LogLevel {
v, d, i, w, e;
private String toHtmlColor() {
switch(this) {
case v:
return "grey";
case i:
return "black";
case w:
return "purple";
case e:
return "red";
case d:
default:
return "teal";
}
}
}
private static class LogEntry {
LogLevel mLogLevel;
String mLogText;
T mLogTag;
public LogEntry(LogLevel logLevel, String logText, T logTag) {
mLogLevel = logLevel;
mLogText = logText;
if (mLogText == null) {
mLogText = "null";
}
mLogTag = logTag;
}
private String toHtml() {
StringBuilder sb = new StringBuilder();
sb.append("<font color=\"");
sb.append(mLogLevel.toHtmlColor());
sb.append("\">");
sb.append("[");
sb.append(mLogTag.name());
sb.append("] ");
sb.append(mLogLevel.name());
sb.append(": ");
sb.append(TextUtils.htmlEncode(mLogText).replace("\n", "<br />"));
sb.append("</font>");
return sb.toString();
}
}
private static class LogEntryList extends ArrayList<LogEntry> {
private synchronized boolean addEntry(LogEntry entry) {
if (size() >= MAX_ENTRIES)
removeFirstEntry();
return add(entry);
}
private void removeFirstEntry() {
Iterator<LogEntry> it = iterator();
if (!it.hasNext())
return;
try {
remove(it.next());
} catch (NoSuchElementException e) {
// ignore
}
}
}
private static LogEntryList mLogEntries = new LogEntryList();
private static void addEntry(T tag, LogLevel level, String text) {
// skip if recording is disabled (default)
if (!mEnableRecording) {
return;
}
LogEntry entry = new LogEntry(level, text, tag);
mLogEntries.addEntry(entry);
}
private static String getStringStackTrace(Throwable throwable) {
StringWriter errors = new StringWriter();
throwable.printStackTrace(new PrintWriter(errors));
return errors.toString();
}
/**
* Returns entire log as html for display (see AppLogViewerActivity)
* @param context
* @return Arraylist of Strings containing log messages
*/
public static ArrayList<String> toHtmlList(Context context) {
ArrayList<String> items = new ArrayList<String>();
// add version & device info - be sure to change HEADER_LINE_COUNT if additional lines are added
items.add("<strong>WordPress Android version: " + PackageUtils.getVersionName(context) + "</strong>");
items.add("<strong>Android device name: " + DeviceUtils.getInstance().getDeviceName(context) + "</strong>");
Iterator<LogEntry> it = mLogEntries.iterator();
while (it.hasNext()) {
items.add(it.next().toHtml());
}
return items;
}
/**
* Converts the entire log to plain text
* @param context
* @return The log as plain text
*/
public static String toPlainText(Context context) {
StringBuilder sb = new StringBuilder();
// add version & device info
sb.append("WordPress Android version: " + PackageUtils.getVersionName(context)).append("\n")
.append("Android device name: " + DeviceUtils.getInstance().getDeviceName(context)).append("\n\n");
Iterator<LogEntry> it = mLogEntries.iterator();
int lineNum = 1;
while (it.hasNext()) {
sb.append(String.format("%02d - ", lineNum))
.append(it.next().mLogText)
.append("\n");
lineNum++;
}
return sb.toString();
}
}