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 } core/logging/impl-console/src/jvmMain/kotlin/net/thunderbird/core/logging/console/ConsoleLogSink.jvm.kt +10 −2 Original line number Diff line number Diff line Loading @@ -15,10 +15,18 @@ private class JvmConsoleLogSink( } private fun composeMessage(event: LogEvent): String { return if (event.tag != null) { "[${event.tag}] ${event.message}" val tag = event.tag ?: event.composeTag(ignoredClasses = IGNORE_CLASSES) return if (tag != null) { "[$tag] ${event.message}" } else { event.message } } companion object { private val IGNORE_CLASSES = setOf( JvmConsoleLogSink::class.java.name, // Add other classes to ignore if needed ) } } 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 }
core/logging/impl-console/src/jvmMain/kotlin/net/thunderbird/core/logging/console/ConsoleLogSink.jvm.kt +10 −2 Original line number Diff line number Diff line Loading @@ -15,10 +15,18 @@ private class JvmConsoleLogSink( } private fun composeMessage(event: LogEvent): String { return if (event.tag != null) { "[${event.tag}] ${event.message}" val tag = event.tag ?: event.composeTag(ignoredClasses = IGNORE_CLASSES) return if (tag != null) { "[$tag] ${event.message}" } else { event.message } } companion object { private val IGNORE_CLASSES = setOf( JvmConsoleLogSink::class.java.name, // Add other classes to ignore if needed ) } }