// file: app/src/commonMain/kotlin/eu/torvian/chatbot/app/utils/misc/KmpLogger.kt
package eu.torvian.chatbot.app.utils.misc
/**
* Common logging interface for Kotlin Multiplatform.
* This interface defines the logging API available in common code.
* Each platform will provide its actual implementation.
*/
interface KmpLogger {
fun trace(message: String, throwable: Throwable? = null)
fun debug(message: String, throwable: Throwable? = null)
fun info(message: String, throwable: Throwable? = null)
fun warn(message: String, throwable: Throwable? = null)
fun error(message: String, throwable: Throwable? = null)
fun fatal(message: String, throwable: Throwable? = null)
}
/**
* Expected top-level function that acts as a factory for [KmpLogger] instances.
* Each platform will provide an 'actual' implementation of this function.
*
* This is the most stable and recommended approach for platform-specific utilities
* when avoiding DI framework boilerplate in every consuming class and ensuring
* compatibility with parallel test execution.
*/
expect fun createKmpLogger(tag: String): KmpLogger
/**
* Helper function to easily get a [KmpLogger] instance for a class.
* This function uses the platform-specific `createKmpLogger` factory function.
*
* Usage: `private val logger = kmpLogger()`
*/
inline fun kmpLogger(): KmpLogger {
return createKmpLogger(T::class.simpleName ?: "Unknown")
}
// file: app/src/androidMain/kotlin/eu/torvian/chatbot/app/utils/misc/KmpLogger.android.kt
package eu.torvian.chatbot.app.utils.misc
import android.util.Log
/**
* Actual implementation of [KmpLogger] for the Android target, using Android's Log API.
*/
class AndroidKmpLogger(private val tag: String) : KmpLogger {
override fun trace(message: String, throwable: Throwable?) {
Log.v(tag, message, throwable)
}
override fun debug(message: String, throwable: Throwable?) {
Log.d(tag, message, throwable)
}
override fun info(message: String, throwable: Throwable?) {
Log.i(tag, message, throwable)
}
override fun warn(message: String, throwable: Throwable?) {
Log.w(tag, message, throwable)
}
override fun error(message: String, throwable: Throwable?) {
Log.e(tag, message, throwable)
}
override fun fatal(message: String, throwable: Throwable?) {
Log.wtf(tag, message, throwable)
}
}
/**
* Actual implementation of the [createKmpLogger] factory function for the Android target.
* This function provides [AndroidKmpLogger] instances.
*/
actual fun createKmpLogger(tag: String): KmpLogger {
return AndroidKmpLogger(tag)
}
// file: app/src/desktopMain/kotlin/eu/torvian/chatbot/app/utils/misc/createKmpLogger.desktop.kt
package eu.torvian.chatbot.app.utils.misc
import org.apache.logging.log4j.LogManager
/**
* Actual implementation of [KmpLogger] for the JVM (Desktop) target, using Log4j2.
*/
class DesktopKmpLogger(private val tag: String) : KmpLogger {
private val logger = LogManager.getLogger(tag)
override fun trace(message: String, throwable: Throwable?) {
logger.trace(message, throwable)
}
override fun debug(message: String, throwable: Throwable?) {
logger.debug(message, throwable)
}
override fun info(message: String, throwable: Throwable?) {
logger.info(message, throwable)
}
override fun warn(message: String, throwable: Throwable?) {
logger.warn(message, throwable)
}
override fun error(message: String, throwable: Throwable?) {
logger.error(message, throwable)
}
override fun fatal(message: String, throwable: Throwable?) {
logger.fatal(message, throwable)
}
}
/**
* Actual implementation of the [createKmpLogger] factory function for the JVM (Desktop) target.
* This function provides [DesktopKmpLogger] instances.
*/
actual fun createKmpLogger(tag: String): KmpLogger {
return DesktopKmpLogger(tag)
}
// file: app/src/wasmJsMain/kotlin/eu/torvian/chatbot/app/utils/misc/createKmpLogger.wasmJs.kt
package eu.torvian.chatbot.app.utils.misc
/**
* A simplified external interface for the browser's Console API, compatible with Kotlin/Wasm.
* It explicitly uses String for arguments, as per Wasm JS interop rules.
*
* Console methods typically take a primary message and then optional additional arguments.
* We model this by having a `message: String` and `vararg optionalParams: String`.
*/
external interface Console {
// Note: The actual JS console functions take Any, but for Wasm interop,
// we limit it to String as that's what we primarily pass.
fun debug(message: String, vararg optionalParams: String)
fun info(message: String, vararg optionalParams: String)
fun warn(message: String, vararg optionalParams: String)
fun error(message: String, vararg optionalParams: String)
}
/**
* The global browser `console` object.
* Declared 'external val' to indicate it's a JavaScript global variable.
*/
external val console: Console
/**
* Actual implementation of [KmpLogger] for the Kotlin/Wasm (JavaScript) target,
* using the browser's `console` API.
*/
class WasmKmpLogger(private val tag: String) : KmpLogger {
override fun trace(message: String, throwable: Throwable?) {
if (throwable != null) {
console.debug("[$tag] $message ${throwable.stackTraceToString()}")
} else {
console.debug("[$tag] $message")
}
}
override fun debug(message: String, throwable: Throwable?) {
if (throwable != null) {
console.debug("[$tag] $message ${throwable.stackTraceToString()}")
} else {
console.debug("[$tag] $message")
}
}
override fun info(message: String, throwable: Throwable?) {
if (throwable != null) {
console.info("[$tag] $message ${throwable.stackTraceToString()}")
} else {
console.info("[$tag] $message")
}
}
override fun warn(message: String, throwable: Throwable?) {
if (throwable != null) {
console.warn("[$tag] $message ${throwable.stackTraceToString()}")
} else {
console.warn("[$tag] $message")
}
}
override fun error(message: String, throwable: Throwable?) {
if (throwable != null) {
console.error("[$tag] $message ${throwable.stackTraceToString()}")
} else {
console.error("[$tag] $message")
}
}
override fun fatal(message: String, throwable: Throwable?) {
if (throwable != null) {
console.error("[$tag] $message ${throwable.stackTraceToString()}")
} else {
console.error("[$tag] $message")
}
}
}
/**
* Actual implementation of the [createKmpLogger] factory function for the Kotlin/Wasm (JavaScript) target.
* This function provides [WasmKmpLogger] instances.
*/
actual fun createKmpLogger(tag: String): KmpLogger {
return WasmKmpLogger(tag)
}