package com.apigee.sdk.apm.android; import android.util.Log; import com.apigee.sdk.Logger; import com.apigee.sdk.apm.android.model.ApigeeMobileAPMConstants; import com.apigee.sdk.apm.android.model.ClientLog; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * * This class basically wraps the Android Logger and is used to intercept * logging methods. * * @author vadmin * */ public class AndroidLog implements Logger { /** * Maximum length for log messages. Longer messages are truncated. */ public static final int LOG_RECORD_MAX_LENGTH = 200; Queue<ClientLog> log; int logMaxSize; boolean useLogTriggerLevel; int logTriggerLevel; boolean useTagFilter; String tagFilter; ApigeeActiveSettings activeSettings; public AndroidLog(ApigeeActiveSettings activeSettings) { log = new ConcurrentLinkedQueue<ClientLog>(); this.activeSettings = activeSettings; logMaxSize = 100; useLogTriggerLevel = false; tagFilter = ""; useLogTriggerLevel = false; logTriggerLevel = Log.VERBOSE; } public int d(String tag, String msg) { writeToLog(Log.DEBUG, tag, msg); return Log.d(tag, msg); } public int d(String tag, String msg, Throwable tr) { writeToLog(Log.DEBUG, tag, msg); return Log.d(tag, msg, tr); } public int e(String tag, String msg) { writeToLog(Log.ERROR, tag, msg); return Log.e(tag, msg); } public int e(String tag, String msg, Throwable tr) { writeToLog(Log.ERROR, tag, msg); return Log.e(tag, msg, tr); } public int i(String tag, String msg) { writeToLog(Log.INFO, tag, msg); return Log.i(tag, msg); } public int i(String tag, String msg, Throwable tr) { writeToLog(Log.INFO, tag, msg); return Log.i(tag, msg, tr); } public int v(String tag, String msg) { writeToLog(Log.VERBOSE, tag, msg); return Log.v(tag, msg); } public int v(String tag, String msg, Throwable tr) { writeToLog(Log.VERBOSE, tag, msg); return Log.v(tag, msg, tr); } public int w(String tag, String msg) { writeToLog(Log.WARN, tag, msg); return Log.w(tag, msg); } public int w(String tag, String msg, Throwable tr) { writeToLog(Log.WARN, tag, msg); return Log.w(tag, msg, tr); } public int wtf(String tag, String msg) { writeToLog(Log.ASSERT, tag, msg); return Log.wtf(tag, msg); } public int wtf(String tag, String msg, Throwable tr) { writeToLog(Log.ASSERT, tag, msg); return Log.wtf(tag, msg, tr); } protected boolean isLogLevelBeingCaptured(int level) { return level >= this.activeSettings.getLogLevelToMonitor(); } private void writeToLog(int level, String tag, String msg) { if (!isLogLevelBeingCaptured(level)) { return; } if (useTagFilter && !tagFilter.equals(tag)) { return; } // is monitoring paused? ApigeeMonitoringClient client = ApigeeMonitoringClient.getInstance(); if (client != null) { if (client.isPaused()) { return; } } ClientLog logRecord = new ClientLog(); logRecord.setTag(tag); if (msg.length() > LOG_RECORD_MAX_LENGTH) { logRecord.setLogMessage(msg.substring(0, LOG_RECORD_MAX_LENGTH-3) + "..."); } else { logRecord.setLogMessage(msg); } logRecord.setTimeStamp(new Date()); String logLevelCode = ApigeeMobileAPMConstants.logLevelCodeForValue(level); logRecord.setLogLevel(logLevelCode); synchronized(this) { if( log != null ) { if (log.size() == logMaxSize) { log.poll(); } if (!log.offer(logRecord)) { Log.w("AndroidLog", "Logger cannot add new log message"); } } } } static final SimpleDateFormat LOG_DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd-HH-mm-ssZ"); String formatLogMessage(int level, String tag, String msg) { String tagText; switch (level) { case Log.ASSERT: tagText = "ASSERT "; break; case Log.ERROR: tagText = "ERROR "; break; case Log.WARN: tagText = "WARN "; break; case Log.INFO: tagText = "INFO "; break; case Log.VERBOSE: tagText = "VERBOSE"; break; default: tagText = "DEBUG "; break; } return LOG_DATE_FORMAT.format(new Date()) + " " + tagText + " [" + tag + "] " + msg; } /** * Discard all existing log records */ public synchronized void clear() { if (log != null) { log.clear(); } } public synchronized List<ClientLog> flush() { int numLogs = 0; if( log != null ) { numLogs = log.size(); } if( numLogs > 0 ) { List<ClientLog> newLog = new ArrayList<ClientLog>(numLogs); // drains the queue for (int i = 0; i < numLogs; i++) { ClientLog logRecord = log.remove(); int logLevelValue = ApigeeMobileAPMConstants.logLevelValueForCode(logRecord.getLogLevel()); if (isLogLevelBeingCaptured(logLevelValue)) { newLog.add(logRecord); } } return newLog; } else { return null; } } public boolean haveLogRecords() { boolean haveLogRecords = false; if( log != null ) { synchronized(this) { haveLogRecords = !log.isEmpty(); } } return haveLogRecords; } }