Last active
March 28, 2020 10:36
-
-
Save daniellAlgar/03c6424f99cb1b360bc5ca0ce47bd2eb to your computer and use it in GitHub Desktop.
This is a safe way to do logging in your Android apps without running the risk of having Log() statements in your production code. It reduces garbage collection and eliminates the need for a log tag.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.? | |
import android.os.Build | |
import android.util.Log | |
import com.varvet.shipgaz.BuildConfig | |
import java.util.regex.Pattern | |
/** | |
* A logger to avoid logging in production. It will check if [BuildConfig.DEBUG] is true or not. | |
* If true then allow logging, otherwise don't. | |
* | |
* All log strings are initialized lazily with a closure to keep the garbage to one object only. | |
*/ | |
object Logger { | |
fun v(tag: String = callerTag(), message: () -> String) = inDebug { | |
Log.v(tag, message()) | |
} | |
fun v(tag: String = callerTag(), message: () -> String, exception: Exception) = inDebug { | |
Log.v(tag, message(), exception) | |
} | |
fun d(tag: String = callerTag(), message: () -> String) = inDebug { | |
Log.d(tag, message()) | |
} | |
fun d(tag: String = callerTag(), message: () -> String, exception: Exception) = inDebug { | |
Log.d(tag, message(), exception) | |
} | |
fun i(tag: String = callerTag(), message: () -> String) = inDebug { | |
Log.i(tag, message()) | |
} | |
fun i(tag: String = callerTag(), message: () -> String, exception: Exception) = inDebug { | |
Log.i(tag, message(), exception) | |
} | |
fun w(tag: String = callerTag(), message: () -> String) = inDebug { | |
Log.w(tag, message()) | |
} | |
fun w(tag: String = callerTag(), message: () -> String, exception: Exception) = inDebug { | |
Log.w(tag, message(), exception) | |
} | |
fun e(tag: String = callerTag(), message: () -> String) = inDebug { | |
Log.e(tag, message()) | |
} | |
fun e(tag: String = callerTag(), message: () -> String, exception: Exception) = inDebug { | |
Log.e(tag, message(), exception) | |
} | |
fun wtf(tag: String = callerTag(), message: () -> String) = inDebug { | |
Log.wtf(tag, message()) | |
} | |
fun wtf(tag: String = callerTag(), message: () -> String, exception: Exception) = inDebug { | |
Log.wtf(tag, message(), exception) | |
} | |
private inline fun inDebug(action: () -> Unit) { | |
if (BuildConfig.DEBUG) { | |
action() | |
} | |
} | |
/** | |
* @return The class name for the calling class as a String. | |
*/ | |
private fun callerTag(): String { | |
val callStackIndex = 2 | |
val maxTagLength = 23 | |
val anonymousClassPattern = Pattern.compile("(\\$\\d+)+$") | |
val stackTrace = Throwable().stackTrace | |
val callerElement = stackTrace[callStackIndex] | |
var tag = callerElement.className | |
val matcher = anonymousClassPattern.matcher(tag) | |
if (matcher.find()) { | |
tag = matcher.replaceAll("") | |
} | |
tag = tag.substring(tag.lastIndexOf('.') + 1) | |
// Tag length limit was removed in API 24. | |
return if (tag.length <= maxTagLength || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
tag | |
} else tag.substring(0, maxTagLength) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment