Loading app-common/build.gradle.kts +4 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,10 @@ plugins { android { namespace = "net.thunderbird.app.common" buildFeatures { buildConfig = true } } dependencies { Loading app-common/src/main/kotlin/net/thunderbird/app/common/core/AppCommonCoreModule.kt +2 −1 Original line number Diff line number Diff line package net.thunderbird.app.common.core import net.thunderbird.app.common.BuildConfig import net.thunderbird.core.logging.DefaultLogger import net.thunderbird.core.logging.LogLevel import net.thunderbird.core.logging.LogSink Loading @@ -11,7 +12,7 @@ import org.koin.dsl.module val appCommonCoreModule: Module = module { single<LogLevel> { LogLevel.INFO if (BuildConfig.DEBUG) LogLevel.VERBOSE else LogLevel.INFO } single<List<LogSink>> { Loading core/logging/impl-console/build.gradle.kts +13 −0 Original line number Diff line number Diff line import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi plugins { id(ThunderbirdPlugins.Library.kmp) } Loading @@ -7,7 +9,18 @@ android { } kotlin { @OptIn(ExperimentalKotlinGradlePluginApi::class) applyDefaultHierarchyTemplate { common { group("commonJvm") { withAndroidTarget() withJvm() } } } sourceSets { val commonJvmMain by getting commonMain.dependencies { implementation(projects.core.logging.api) } Loading core/logging/impl-console/src/androidMain/kotlin/net/thunderbird/core/logging/console/ConsoleLogSink.android.kt +14 −1 Original line number Diff line number Diff line Loading @@ -11,7 +11,9 @@ private class AndroidConsoleLogSink( ) : ConsoleLogSink { override fun log(event: LogEvent) { val timber = event.tag?.let { Timber.tag(it) } ?: Timber val timber = event.tag ?.let { Timber.tag(it) } ?: Timber.tag(event.composeTag(ignoredClasses = IGNORE_CLASSES) ?: this::class.java.name) when (event.level) { LogLevel.VERBOSE -> timber.v(event.throwable, event.message) Loading @@ -21,4 +23,15 @@ private class AndroidConsoleLogSink( LogLevel.ERROR -> timber.e(event.throwable, event.message) } } companion object { private val IGNORE_CLASSES = setOf( Timber::class.java.name, Timber.Forest::class.java.name, Timber.Tree::class.java.name, Timber.DebugTree::class.java.name, AndroidConsoleLogSink::class.java.name, // Add other classes to ignore if needed ) } } core/logging/impl-console/src/commonJvmMain/kotlin/net/thunderbird/core/logging/console/ComposeLogTag.kt 0 → 100644 +67 −0 Original line number Diff line number Diff line package net.thunderbird.core.logging.console import net.thunderbird.core.logging.DefaultLogger import net.thunderbird.core.logging.LogEvent import net.thunderbird.core.logging.Logger /** * Composes a tag for the given [LogEvent]. * * If the event has a tag, it is used; otherwise, a tag is extracted from the stack trace. * The tag is processed using the [processTag] method before being returned. * * @receiver The [LogEvent] to compose a tag for. * @param ignoredClasses The set of Class full name to be ignored. * @param processTag Processes a tag before it is used for logging. * @return The composed tag, or null if no tag could be determined. */ internal fun LogEvent.composeTag( ignoredClasses: Set<String>, processTag: (String) -> String? = { it }, ): String? { // If a tag is provided, use it; otherwise, extract it from the stack trace val rawTag = tag ?: extractTagFromStackTrace(ignoredClasses) // Process the tag before returning it return rawTag?.let { processTag(it) } } /** * Extracts a tag from the stack trace. * * @return The extracted tag, or null if no suitable tag could be found. */ private fun extractTagFromStackTrace(ignoredClasses: Set<String>): String? { // Some classes are not available to this module, and we don't want // to add the dependency just for class filtering. val ignoredClasses = ignoredClasses + setOf( "net.thunderbird.core.logging.console.ComposeLogTagKt", "net.thunderbird.core.logging.composite.DefaultCompositeLogSink", "net.thunderbird.core.logging.legacy.Log", Logger::class.java.name, DefaultLogger::class.java.name, ) @Suppress("ThrowingExceptionsWithoutMessageOrCause") val stackTrace = Throwable().stackTrace return stackTrace .firstOrNull { element -> ignoredClasses.none { element.className.startsWith(it) } } ?.let(::createStackElementTag) } /** * Creates a tag from a stack trace element. * * @param element The stack trace element to create a tag from. * @return The created tag. */ private fun createStackElementTag(element: StackTraceElement): String { var tag = element.className.substringAfterLast('.') val regex = "(\\$\\d+)+$".toRegex() if (regex.containsMatchIn(input = tag)) { tag = regex.replace(input = tag, replacement = "") } return tag } Loading
app-common/build.gradle.kts +4 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,10 @@ plugins { android { namespace = "net.thunderbird.app.common" buildFeatures { buildConfig = true } } dependencies { Loading
app-common/src/main/kotlin/net/thunderbird/app/common/core/AppCommonCoreModule.kt +2 −1 Original line number Diff line number Diff line package net.thunderbird.app.common.core import net.thunderbird.app.common.BuildConfig import net.thunderbird.core.logging.DefaultLogger import net.thunderbird.core.logging.LogLevel import net.thunderbird.core.logging.LogSink Loading @@ -11,7 +12,7 @@ import org.koin.dsl.module val appCommonCoreModule: Module = module { single<LogLevel> { LogLevel.INFO if (BuildConfig.DEBUG) LogLevel.VERBOSE else LogLevel.INFO } single<List<LogSink>> { Loading
core/logging/impl-console/build.gradle.kts +13 −0 Original line number Diff line number Diff line import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi plugins { id(ThunderbirdPlugins.Library.kmp) } Loading @@ -7,7 +9,18 @@ android { } kotlin { @OptIn(ExperimentalKotlinGradlePluginApi::class) applyDefaultHierarchyTemplate { common { group("commonJvm") { withAndroidTarget() withJvm() } } } sourceSets { val commonJvmMain by getting commonMain.dependencies { implementation(projects.core.logging.api) } Loading
core/logging/impl-console/src/androidMain/kotlin/net/thunderbird/core/logging/console/ConsoleLogSink.android.kt +14 −1 Original line number Diff line number Diff line Loading @@ -11,7 +11,9 @@ private class AndroidConsoleLogSink( ) : ConsoleLogSink { override fun log(event: LogEvent) { val timber = event.tag?.let { Timber.tag(it) } ?: Timber val timber = event.tag ?.let { Timber.tag(it) } ?: Timber.tag(event.composeTag(ignoredClasses = IGNORE_CLASSES) ?: this::class.java.name) when (event.level) { LogLevel.VERBOSE -> timber.v(event.throwable, event.message) Loading @@ -21,4 +23,15 @@ private class AndroidConsoleLogSink( LogLevel.ERROR -> timber.e(event.throwable, event.message) } } companion object { private val IGNORE_CLASSES = setOf( Timber::class.java.name, Timber.Forest::class.java.name, Timber.Tree::class.java.name, Timber.DebugTree::class.java.name, AndroidConsoleLogSink::class.java.name, // Add other classes to ignore if needed ) } }
core/logging/impl-console/src/commonJvmMain/kotlin/net/thunderbird/core/logging/console/ComposeLogTag.kt 0 → 100644 +67 −0 Original line number Diff line number Diff line package net.thunderbird.core.logging.console import net.thunderbird.core.logging.DefaultLogger import net.thunderbird.core.logging.LogEvent import net.thunderbird.core.logging.Logger /** * Composes a tag for the given [LogEvent]. * * If the event has a tag, it is used; otherwise, a tag is extracted from the stack trace. * The tag is processed using the [processTag] method before being returned. * * @receiver The [LogEvent] to compose a tag for. * @param ignoredClasses The set of Class full name to be ignored. * @param processTag Processes a tag before it is used for logging. * @return The composed tag, or null if no tag could be determined. */ internal fun LogEvent.composeTag( ignoredClasses: Set<String>, processTag: (String) -> String? = { it }, ): String? { // If a tag is provided, use it; otherwise, extract it from the stack trace val rawTag = tag ?: extractTagFromStackTrace(ignoredClasses) // Process the tag before returning it return rawTag?.let { processTag(it) } } /** * Extracts a tag from the stack trace. * * @return The extracted tag, or null if no suitable tag could be found. */ private fun extractTagFromStackTrace(ignoredClasses: Set<String>): String? { // Some classes are not available to this module, and we don't want // to add the dependency just for class filtering. val ignoredClasses = ignoredClasses + setOf( "net.thunderbird.core.logging.console.ComposeLogTagKt", "net.thunderbird.core.logging.composite.DefaultCompositeLogSink", "net.thunderbird.core.logging.legacy.Log", Logger::class.java.name, DefaultLogger::class.java.name, ) @Suppress("ThrowingExceptionsWithoutMessageOrCause") val stackTrace = Throwable().stackTrace return stackTrace .firstOrNull { element -> ignoredClasses.none { element.className.startsWith(it) } } ?.let(::createStackElementTag) } /** * Creates a tag from a stack trace element. * * @param element The stack trace element to create a tag from. * @return The created tag. */ private fun createStackElementTag(element: StackTraceElement): String { var tag = element.className.substringAfterLast('.') val regex = "(\\$\\d+)+$".toRegex() if (regex.containsMatchIn(input = tag)) { tag = regex.replace(input = tag, replacement = "") } return tag }