Last active
February 25, 2023 15:59
-
-
Save marcellogalhardo/256032be74cbe7ad692648a4e31ca067 to your computer and use it in GitHub Desktop.
Helper functions to make logging easier.
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
@file:OptIn(ExperimentalTypeInference::class) | |
package logcat | |
import android.util.Log | |
import java.io.PrintWriter | |
import java.io.StringWriter | |
import kotlin.experimental.ExperimentalTypeInference | |
@JvmName("logcatString") | |
@OverloadResolutionByLambdaReturnType | |
public inline fun Any.logcat( | |
priority: LogPriority, | |
tag: String?, | |
message: () -> String, | |
) { | |
internalRunIfLoggable(priority, tag) { innerTag -> internalLog(priority, innerTag, message()) } | |
} | |
@JvmName("logcatError") | |
@OverloadResolutionByLambdaReturnType | |
public inline fun Any.logcat( | |
priority: LogPriority, | |
tag: String?, | |
error: () -> Throwable, | |
) { | |
internalRunIfLoggable(priority, tag) { innerTag -> internalLog(priority, innerTag, error()) } | |
} | |
@JvmName("logcatResult") | |
@OverloadResolutionByLambdaReturnType | |
public inline fun <T> Any.logcat( | |
priority: LogPriority, | |
tag: String?, | |
result: () -> Result<T>, | |
) { | |
internalRunIfLoggable(priority, tag) { innerTag -> | |
internalLog(priority, innerTag, internalLogResult(result())) | |
} | |
} | |
@Suppress("NOTHING_TO_INLINE") | |
@JvmName("logcatResult") | |
public inline fun <T> Result<T>.logcat( | |
priority: LogPriority, | |
tag: String?, | |
): Result<T> = also { logcat(priority, tag, result = { this }) } | |
@JvmName("logcatString") | |
@PublishedApi | |
internal fun Any.internalRunIfLoggable( | |
priority: LogPriority, | |
tag: String?, | |
block: (tag: String) -> Unit, | |
) { | |
if (LogClient.isLoggable(priority)) block(tag ?: internalOuterClassSimpleName()) | |
} | |
@PublishedApi | |
internal fun internalLog( | |
priority: LogPriority, | |
tag: String, | |
message: String, | |
) { | |
when (priority) { | |
LogPriority.VERBOSE -> Log.v(tag, message) | |
LogPriority.DEBUG -> Log.d(tag, message) | |
LogPriority.INFO -> Log.i(tag, message) | |
LogPriority.WARN -> Log.w(tag, message) | |
LogPriority.ERROR -> Log.e(tag, message) | |
LogPriority.ASSERT -> Log.wtf(tag, message) | |
} | |
} | |
@PublishedApi | |
internal fun internalLog( | |
priority: LogPriority, | |
tag: String, | |
error: Throwable, | |
) { | |
internalLog(priority, tag, internalLogException(error)) | |
} | |
@PublishedApi | |
internal fun Any.internalOuterClassSimpleName(): String { | |
val javaClass = this::class.java | |
val fullClassName = javaClass.name | |
val outerClassName = fullClassName.substringBefore('$') | |
val simplerOuterClassName = outerClassName.substringAfterLast('.') | |
return if (simplerOuterClassName.isEmpty()) { | |
fullClassName | |
} else { | |
simplerOuterClassName.removeSuffix("Kt") | |
} | |
} | |
/** | |
* Utility to turn a [Throwable] into a loggable string. | |
* | |
* The implementation is based on Timber.getStackTraceString(). It's different | |
* from [android.util.Log.getStackTraceString] in the following ways: | |
* - No silent swallowing of UnknownHostException. | |
* - The buffer size is 256 bytes instead of the default 16 bytes. | |
*/ | |
@PublishedApi | |
internal fun internalLogException(error: Throwable): String { | |
val stringWriter = StringWriter(256) | |
val printWriter = PrintWriter(stringWriter, false) | |
error.printStackTrace(printWriter) | |
printWriter.flush() | |
return stringWriter.toString() | |
} | |
@PublishedApi | |
internal fun <T> internalLogResult(result: Result<T>): String { | |
val classToString = result.toString() | |
val exception = result.exceptionOrNull() | |
return if (exception != null) { | |
val exceptionToString = internalLogException(exception) | |
"$classToString/n$exceptionToString" | |
} else { | |
classToString | |
} | |
} |
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 logcat | |
public object LogClient { | |
private var isInitialized: Boolean = false | |
@PublishedApi | |
internal var isEnabled: Boolean = false | |
@PublishedApi | |
internal var minPriority: LogPriority = LogPriority.DEBUG | |
public fun initialize( | |
enabled: Boolean, | |
minPriority: LogPriority, | |
) { | |
require(!isInitialized) { "LogClient.initialize should be called only once." } | |
isInitialized = true | |
this.isEnabled = enabled | |
this.minPriority = minPriority | |
} | |
@PublishedApi | |
internal fun isLoggable(priority: LogPriority): Boolean { | |
return isEnabled && priority.level >= minPriority.level | |
} | |
} |
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 logcat | |
public enum class LogPriority(@PublishedApi internal val level: Int) { | |
VERBOSE(level = 2), | |
DEBUG(level = 3), | |
INFO(level = 4), | |
WARN(level = 5), | |
ERROR(level = 6), | |
ASSERT(level = 7); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment