diff --git a/android-core/src/androidTest/kotlin/com.mparticle/MParticleOptionsTest.kt b/android-core/src/androidTest/kotlin/com.mparticle/MParticleOptionsTest.kt index dae8615ca..f607a5e46 100644 --- a/android-core/src/androidTest/kotlin/com.mparticle/MParticleOptionsTest.kt +++ b/android-core/src/androidTest/kotlin/com.mparticle/MParticleOptionsTest.kt @@ -571,14 +571,14 @@ class MParticleOptionsTest : BaseAbstractTest() { @Test fun testAndroidIdLogMessage() { val infoLogs = ArrayList() - Logger.setLogHandler(object : DefaultLogHandler() { + Logger.logHandler = object : DefaultLogHandler() { override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String) { super.log(priority, error, messages) if (priority == MParticle.LogLevel.INFO) { infoLogs.add(messages) } } - }) + } MParticleOptions.builder(mContext) .credentials("this", "that") .androidIdDisabled(true) diff --git a/android-core/src/main/java/com/mparticle/internal/Logger.java b/android-core/src/main/java/com/mparticle/internal/Logger.java deleted file mode 100644 index c0efcefc7..000000000 --- a/android-core/src/main/java/com/mparticle/internal/Logger.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.mparticle.internal; - -import android.util.Log; - -import com.mparticle.MParticle.LogLevel; - - -public class Logger { - public static final LogLevel DEFAULT_MIN_LOG_LEVEL = LogLevel.DEBUG; - private static LogLevel sMinLogLevel = DEFAULT_MIN_LOG_LEVEL; - private static boolean sExplicitlySet = false; - private static AbstractLogHandler logHandler = new DefaultLogHandler(); - - public static void setMinLogLevel(LogLevel minLogLevel) { - setMinLogLevel(minLogLevel, null); - } - - public static void setMinLogLevel(LogLevel minLogLevel, Boolean explicit) { - if (explicit != null) { - sExplicitlySet = explicit; - } - if (sExplicitlySet && explicit == null) { - return; - } - Logger.sMinLogLevel = minLogLevel; - } - - public static LogLevel getMinLogLevel() { - return sMinLogLevel; - } - - public static void verbose(String... messages) { - verbose(null, messages); - } - - public static void verbose(Throwable error, String... messages) { - getLogHandler().log(LogLevel.VERBOSE, error, getMessage(messages)); - } - - public static void info(String... messages) { - info(null, messages); - } - - public static void info(Throwable error, String... messages) { - getLogHandler().log(LogLevel.INFO, error, getMessage(messages)); - } - - public static void debug(String... messages) { - debug(null, messages); - } - - public static void debug(Throwable error, String... messages) { - getLogHandler().log(LogLevel.DEBUG, error, getMessage(messages)); - } - - public static void warning(String... messages) { - warning(null, messages); - } - - public static void warning(Throwable error, String... messages) { - getLogHandler().log(LogLevel.WARNING, error, getMessage(messages)); - } - - public static void error(String... messages) { - error(null, messages); - } - - public static void error(Throwable error, String... messages) { - getLogHandler().log(LogLevel.ERROR, error, getMessage(messages)); - } - - private static String getMessage(String... messages) { - StringBuilder logMessage = new StringBuilder(); - for (String m : messages) { - logMessage.append(m); - } - return logMessage.toString(); - } - - - /** - * Testing method. Use this method to intercept Logs, or customize what happens when something is logged. - * For example, you can use this method to throw an exception every time an "error" log is called. - * - * @param logListener - */ - public static void setLogHandler(AbstractLogHandler logListener) { - Logger.logHandler = logListener; - } - - public static AbstractLogHandler getLogHandler() { - if (logHandler == null) { - logHandler = new DefaultLogHandler(); - } - return logHandler; - } - - public abstract static class AbstractLogHandler { - - public void log(LogLevel priority, Throwable error, String messages) { - if (messages != null && isLoggable(priority.logLevel)) { - switch (priority) { - case ERROR: - error(error, messages); - break; - case WARNING: - warning(error, messages); - break; - case DEBUG: - debug(error, messages); - break; - case VERBOSE: - verbose(error, messages); - break; - case INFO: - info(error, messages); - } - } - } - - private boolean isLoggable(int logLevel) { - boolean isAPILoggable = logLevel >= Logger.sMinLogLevel.logLevel; - boolean isADBLoggable; - - //This block will catch the exception that is thrown during testing. - try { - isADBLoggable = isADBLoggable(Constants.LOG_TAG, logLevel); - } catch (UnsatisfiedLinkError ex) { - return false; - } catch (RuntimeException ignored) { - return false; - } - return isADBLoggable || (isAPILoggable && MPUtility.isDevEnv()); - } - - //Override this method during testing, otherwise this will throw an error and logs will not be printed. - protected boolean isADBLoggable(String tag, int logLevel) { - return Log.isLoggable(tag, logLevel); - } - - public abstract void verbose(Throwable error, String message); - - public abstract void info(Throwable error, String message); - - public abstract void debug(Throwable error, String message); - - public abstract void warning(Throwable error, String message); - - public abstract void error(Throwable error, String message); - } - - public static class DefaultLogHandler extends AbstractLogHandler { - - @Override - public void verbose(Throwable error, String messages) { - if (error != null) { - Log.v(Constants.LOG_TAG, messages, error); - } else { - Log.v(Constants.LOG_TAG, messages); - } - } - - @Override - public void info(Throwable error, String messages) { - if (error != null) { - Log.i(Constants.LOG_TAG, messages, error); - } else { - Log.i(Constants.LOG_TAG, messages); - } - } - - @Override - public void debug(Throwable error, String messages) { - if (error != null) { - Log.d(Constants.LOG_TAG, messages, error); - } else { - Log.d(Constants.LOG_TAG, messages); - } - } - - @Override - public void warning(Throwable error, String messages) { - if (error != null) { - Log.w(Constants.LOG_TAG, messages, error); - } else { - Log.w(Constants.LOG_TAG, messages); - } - } - - @Override - public void error(Throwable error, String messages) { - if (error != null) { - Log.e(Constants.LOG_TAG, messages, error); - } else { - Log.e(Constants.LOG_TAG, messages); - } - } - } - -} diff --git a/android-core/src/main/kotlin/com/mparticle/internal/Logger.kt b/android-core/src/main/kotlin/com/mparticle/internal/Logger.kt new file mode 100644 index 000000000..9bac77d9a --- /dev/null +++ b/android-core/src/main/kotlin/com/mparticle/internal/Logger.kt @@ -0,0 +1,193 @@ +package com.mparticle.internal + +import android.util.Log +import com.mparticle.MParticle.LogLevel + +object Logger { + val DEFAULT_MIN_LOG_LEVEL: LogLevel = LogLevel.DEBUG + private var sMinLogLevel = DEFAULT_MIN_LOG_LEVEL + private var sExplicitlySet = false + private var internalLogHandler: AbstractLogHandler? = null + + /** + * Testing method. Use this method to intercept Logs, or customize what happens when something is logged. + * For example, you can use this method to throw an exception every time an "error" log is called. + * + * @param logListener + */ + @JvmStatic + var logHandler: AbstractLogHandler? = null + get() { + if (field == null) { + field = DefaultLogHandler() + } + return field + } + + @JvmStatic + fun setMinLogLevel(minLogLevel: LogLevel) { + setMinLogLevel(minLogLevel, null) + } + + @JvmStatic + fun setMinLogLevel(minLogLevel: LogLevel, explicit: Boolean?) { + explicit?.let { + sExplicitlySet = it + } + if (sExplicitlySet && explicit == null) { + return + } + sMinLogLevel = minLogLevel + } + + fun getMinLogLevel(): LogLevel { + return sMinLogLevel + } + + @JvmStatic + fun verbose(vararg messages: String) { + verbose(error = null, *messages) + } + + @JvmStatic + fun verbose(error: Throwable?, vararg messages: String) { + logHandler!!.log(LogLevel.VERBOSE, error, getMessage(*messages)) + } + + @JvmStatic + fun info(vararg messages: String) { + info(error = null, *messages) + } + + fun info(error: Throwable?, vararg messages: String) { + logHandler!!.log(LogLevel.INFO, error, getMessage(*messages)) + } + + @JvmStatic + fun debug(vararg messages: String) { + debug(error = null, *messages) + } + + @JvmStatic + fun debug(error: Throwable?, vararg messages: String) { + logHandler!!.log(LogLevel.DEBUG, error, getMessage(*messages)) + } + + @JvmStatic + fun warning(vararg messages: String) { + warning(error = null, *messages) + } + + @JvmStatic + fun warning(error: Throwable?, vararg messages: String) { + logHandler!!.log(LogLevel.WARNING, error, getMessage(*messages)) + } + + @JvmStatic + fun error(vararg messages: String) { + error(error = null, *messages) + } + + @JvmStatic + fun error(error: Throwable?, vararg messages: String) { + logHandler!!.log(LogLevel.ERROR, error, getMessage(*messages)) + } + + private fun getMessage(vararg messages: String): String { + val logMessage = StringBuilder() + for (m in messages) { + logMessage.append(m) + } + return logMessage.toString() + } + + + abstract class AbstractLogHandler { + open fun log(priority: LogLevel, error: Throwable?, messages: String) { + if (isLoggable(priority.logLevel)) { + when (priority) { + LogLevel.ERROR -> error(error, messages) + LogLevel.WARNING -> warning(error, messages) + LogLevel.DEBUG -> debug(error, messages) + LogLevel.VERBOSE -> verbose(error, messages) + LogLevel.INFO -> info(error, messages) + else -> { + debug(error, messages) + } + } + } + } + + private fun isLoggable(logLevel: Int): Boolean { + val isAPILoggable = logLevel >= sMinLogLevel.logLevel + val isADBLoggable: Boolean + + // This block will catch the exception that is thrown during testing. + try { + isADBLoggable = isADBLoggable(Constants.LOG_TAG, logLevel) + } catch (ex: UnsatisfiedLinkError) { + return false + } catch (ignored: RuntimeException) { + return false + } + return isADBLoggable || (isAPILoggable && MPUtility.isDevEnv()) + } + + // Override this method during testing, otherwise this will throw an error and logs will not be printed. + protected open fun isADBLoggable(tag: String, logLevel: Int): Boolean { + return Log.isLoggable(tag, logLevel) + } + + abstract fun verbose(error: Throwable?, message: String) + + abstract fun info(error: Throwable?, message: String) + + abstract fun debug(error: Throwable?, message: String) + + abstract fun warning(error: Throwable?, message: String) + + abstract fun error(error: Throwable?, message: String) + } + + open class DefaultLogHandler : AbstractLogHandler() { + override fun verbose(error: Throwable?, messages: String) { + if (error != null) { + Log.v(Constants.LOG_TAG, messages, error) + } else { + Log.v(Constants.LOG_TAG, messages) + } + } + + override fun info(error: Throwable?, messages: String) { + if (error != null) { + Log.i(Constants.LOG_TAG, messages, error) + } else { + Log.i(Constants.LOG_TAG, messages) + } + } + + override fun debug(error: Throwable?, messages: String) { + if (error != null) { + Log.d(Constants.LOG_TAG, messages, error) + } else { + Log.d(Constants.LOG_TAG, messages) + } + } + + override fun warning(error: Throwable?, messages: String) { + if (error != null) { + Log.w(Constants.LOG_TAG, messages, error) + } else { + Log.w(Constants.LOG_TAG, messages) + } + } + + override fun error(error: Throwable?, messages: String) { + if (error != null) { + Log.e(Constants.LOG_TAG, messages, error) + } else { + Log.e(Constants.LOG_TAG, messages) + } + } + } +} diff --git a/android-core/src/test/kotlin/com/mparticle/commerce/CommerceEventTest.kt b/android-core/src/test/kotlin/com/mparticle/commerce/CommerceEventTest.kt index 5c74cb92d..82bb2a87d 100644 --- a/android-core/src/test/kotlin/com/mparticle/commerce/CommerceEventTest.kt +++ b/android-core/src/test/kotlin/com/mparticle/commerce/CommerceEventTest.kt @@ -26,13 +26,13 @@ class CommerceEventTest { val event = CommerceEvent.Builder(Product.ADD_TO_CART, product).addProduct(product2).build() Assert.assertEquals("name 2", event.products?.get(1)?.name) val errorMessage = AndroidUtils.Mutable(null) - Logger.setLogHandler(object : DefaultLogHandler() { - override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String) { + Logger.logHandler = object : DefaultLogHandler() { + override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String?) { if (priority == MParticle.LogLevel.ERROR) { errorMessage.value = messages } } - }) + } CommerceEvent.Builder(Promotion.VIEW, Promotion().setId("whatever")).addProduct(product2) .build() Assert.assertNotNull("Should have logged Error", errorMessage.value) @@ -50,13 +50,13 @@ class CommerceEventTest { .transactionAttributes(TransactionAttributes().setId("the id")).build() Assert.assertEquals("the id", event.transactionAttributes?.id) val errorMessage = AndroidUtils.Mutable(null) - Logger.setLogHandler(object : DefaultLogHandler() { - override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String) { + Logger.logHandler = object : DefaultLogHandler() { + override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String?) { if (priority == MParticle.LogLevel.ERROR) { errorMessage.value = messages } } - }) + } CommerceEvent.Builder(Product.PURCHASE, product).build() Assert.assertNotNull("Should have logged Error", errorMessage.value) } @@ -102,13 +102,13 @@ class CommerceEventTest { .build() Assert.assertEquals("promo id", event.promotions?.get(0)?.id) val errorMessage = AndroidUtils.Mutable(null) - Logger.setLogHandler(object : DefaultLogHandler() { - override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String) { + Logger.logHandler = object : DefaultLogHandler() { + override fun log(priority: MParticle.LogLevel, error: Throwable?, messages: String?) { if (priority == MParticle.LogLevel.ERROR) { errorMessage.value = messages } } - }) + } CommerceEvent.Builder(Product.ADD_TO_CART, product).nonInteraction(true) .addPromotion(Promotion().setId("promo id")).build() Assert.assertNotNull("Should have logged Error", errorMessage.value) diff --git a/android-core/src/test/kotlin/com/mparticle/internal/LoggerTest.kt b/android-core/src/test/kotlin/com/mparticle/internal/LoggerTest.kt index 9c56d0063..c0eaa5926 100644 --- a/android-core/src/test/kotlin/com/mparticle/internal/LoggerTest.kt +++ b/android-core/src/test/kotlin/com/mparticle/internal/LoggerTest.kt @@ -52,11 +52,11 @@ class LoggerTest { null, null ) - Assert.assertNotNull(Logger.getLogHandler()) - Assert.assertTrue(Logger.getLogHandler() is DefaultLogHandler) + Assert.assertNotNull(Logger.logHandler) + Assert.assertTrue(Logger.logHandler is DefaultLogHandler) val called = BooleanArray(6) val logHandlerTest = LogHandlerTest(called) - Logger.setLogHandler(logHandlerTest) + Logger.logHandler=logHandlerTest assertTrueUpTo(0, called) Logger.verbose("testMessage") assertTrueUpTo(1, called) @@ -68,10 +68,10 @@ class LoggerTest { assertTrueUpTo(4, called) Logger.error("testMessage") assertTrueUpTo(5, called) - Assert.assertEquals(logHandlerTest, Logger.getLogHandler()) - Logger.setLogHandler(null) - Assert.assertNotNull(Logger.getLogHandler()) - Assert.assertTrue(Logger.getLogHandler() is DefaultLogHandler) + Assert.assertEquals(logHandlerTest, Logger.logHandler) + Logger.logHandler =null + Assert.assertNotNull(Logger.logHandler) + Assert.assertTrue(Logger.logHandler is DefaultLogHandler) } private fun assertTrueUpTo(limit: Int, called: BooleanArray) {