//region initializing the logger using the application object or any other way class CoreApplication : Application() { private val initializer by inject() override fun onCreate() { super.onCreate() initializer.initialize() } } interface LogInitializer { fun initialize() } //endregion //region logger initializer implementation exposed in the DI (hence the internal visibility) internal class LogInitializerImpl( private val handler: Handler ) : LogInitializer { override fun initialize() { Logger.getLogger("").apply { level = Level.ALL handlers.forEach { removeHandler(it) } addHandler(handler) } } } internal class AndroidLogHandler : Handler() { private val Level.androidLevel: Int get() = when (intValue()) { Level.SEVERE.intValue() -> Log.ERROR Level.WARNING.intValue() -> Log.WARN Level.INFO.intValue() -> Log.INFO Level.FINE.intValue() -> Log.DEBUG else -> Log.DEBUG } override fun publish(record: LogRecord) { val tag = record.loggerName val message = record.thrown?.let { thrown -> "${record.message}: ${Log.getStackTraceString(thrown)}" } ?: record.message Log.println(record.level.androidLevel, tag, message) } override fun flush() { // no-op } override fun close() { // no-op } } //endregion //region no-op logger initializer exposed in the DI (hence the internal visibility) internal class NoOpLogInitializer : LogInitializer { override fun initialize() { // no-op } } //endregion // region CoreLogger.kt val Any.coreLogger: CoreLogger get() = InternalLogger(logger = Logger.getLogger(this@coreLogger::class.java.simpleName)) private class InternalLogger( private val logger: Logger, ) : CoreLogger { override fun d(message: String) { logger.log(Level.FINE, message) } override fun i(message: String) { logger.log(Level.INFO, message) } override fun w(message: String) { logger.log(Level.WARNING, message) } override fun e(message: String) { logger.log(Level.SEVERE, message) } override fun e(throwable: Throwable, message: String) { logger.log(Level.SEVERE, message, throwable) } } interface CoreLogger { fun d(message: String) fun i(message: String) fun w(message: String) fun e(message: String) fun e(throwable: Throwable, message: String) } //endregion