From 7f92a3e614f803a74a2ddc2cb6634cfeb33a3cb6 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 12 Nov 2025 13:45:57 +0600 Subject: [PATCH] generate kdocs --- .../KSLoggerDefaultPlatformLoggerLambda.kt | 15 ++ src/commonMain/kotlin/Extensions.kt | 12 ++ src/commonMain/kotlin/KSLog.kt | 167 +++++++++++++++--- src/commonMain/kotlin/KSLogTypealiases.kt | 36 ++++ ...LoggerDefaultPlatformLoggerLambdaExpect.kt | 18 +- src/commonMain/kotlin/filter/FilterKSLog.kt | 17 +- .../kotlin/filter/FilteredExtension.kt | 16 +- src/commonMain/kotlin/typed/TypedKSLog.kt | 22 ++- .../kotlin/typed/TypedKSLogBuilder.kt | 71 +++++++- src/commonMain/kotlin/utils/Combination.kt | 21 ++- src/jsMain/kotlin/ExtendedConsole.kt | 45 ++++- .../KSLoggerDefaultPlatformLoggerLambda.kt | 18 ++ src/jvmMain/kotlin/ActualLogger.kt | 67 ++++++- .../KSLoggerDefaultPlatformLoggerLambda.kt | 10 +- .../KSLoggerDefaultPlatformLoggerLambda.kt | 8 + .../KSLoggerDefaultPlatformLoggerLambda.kt | 7 + 16 files changed, 510 insertions(+), 40 deletions(-) diff --git a/src/androidMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt b/src/androidMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt index c55f39f..e2392bb 100644 --- a/src/androidMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt +++ b/src/androidMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt @@ -2,6 +2,21 @@ package dev.inmo.kslog.common import android.util.Log +/** + * Android platform implementation of the default logger + * + * Uses Android's `[android.util.Log]` as the logging backend, mapping KSLog levels + * to Android log levels: + * - [LogLevel.TRACE] → [Log.d] (debug) + * - [LogLevel.DEBUG] → [Log.d] (debug) + * - [LogLevel.VERBOSE] → [Log.v] (verbose) + * - [LogLevel.INFO] → [Log.i] (info) + * - [LogLevel.WARNING] → [Log.w] (warning) + * - [LogLevel.ERROR] → [Log.e] (error) + * - [LogLevel.ASSERT] → [Log.wtf] (what a terrible failure) + * + * Logs can be viewed using `adb logcat` or Android Studio's Logcat window. + */ actual var KSLoggerDefaultPlatformLoggerLambda: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit = { l, t, m, e -> val messageString = m.toString() when(l) { diff --git a/src/commonMain/kotlin/Extensions.kt b/src/commonMain/kotlin/Extensions.kt index 4110a9c..c454b25 100644 --- a/src/commonMain/kotlin/Extensions.kt +++ b/src/commonMain/kotlin/Extensions.kt @@ -2,6 +2,18 @@ package dev.inmo.kslog.common +/** + * Extension functions for convenient logging with [KSLog] + * + * This file provides: + * - Generic log functions for all log levels + * - Specific functions for each log level (trace, debug, verbose, info, warning, error, assert) + * - Short aliases (t, d, v, i, w, e, wtf) for quick logging + * - Suspendable variants (with 'S' suffix) for async contexts + * - Support for lazy message evaluation via lambda builders + * - Both tagged and untagged variants + */ + inline fun KSLog.log(level: LogLevel, tag: String?, e: Throwable? = null, noinline messageBuilder: () -> Any) = performLog(level, tag, e, messageBuilder) inline fun KSLog.log(level: LogLevel, tag: String, noinline messageBuilder: () -> Any) = performLog(level, tag, null, messageBuilder) suspend inline fun KSLog.logS(level: LogLevel, tag: String?, e: Throwable? = null, noinline messageBuilder: suspend () -> Any) = performLogS(level, tag, e, messageBuilder) diff --git a/src/commonMain/kotlin/KSLog.kt b/src/commonMain/kotlin/KSLog.kt index c964734..800e189 100644 --- a/src/commonMain/kotlin/KSLog.kt +++ b/src/commonMain/kotlin/KSLog.kt @@ -4,36 +4,83 @@ import dev.inmo.kslog.common.filter.filtered import dev.inmo.kslog.common.utils.plus +/** + * Enumeration of all available log levels ordered from least to most severe + * + * Used to categorize and filter log messages by importance + */ enum class LogLevel { + /** Trace level - most detailed logging, typically for tracing code execution */ TRACE, + /** Debug level - detailed information useful for debugging */ DEBUG, + /** Verbose level - detailed informational messages */ VERBOSE, + /** Info level - general informational messages about application state */ INFO, + /** Warning level - potentially harmful situations */ WARNING, + /** Error level - error events that might still allow the application to continue */ ERROR, + /** Assert level - severe errors that should never happen */ ASSERT, } /** - * Base interface for any logger - * - * @see default + * Base interface for any logger in KSLog framework * + * This is the core logging interface that all logger implementations must implement. + * It provides multiple overloads for logging messages with various combinations of parameters. + * + * The interface supports: + * - Synchronous and suspendable logging + * - Lazy message evaluation via lambda builders + * - Optional tags for categorizing logs + * - Exception/throwable logging + * - All standard log levels (TRACE, DEBUG, VERBOSE, INFO, WARNING, ERROR, ASSERT) + * + * @see default Default logger instance + * @see DefaultKSLog Default implementation + * @see FilterKSLog Logger with filtering capabilities + * @see TypedKSLog Logger with type-based routing */ interface KSLog { /** - * The only one function required to realization in any inheritor. All other [performLog] functions - * will call this one by default + * The core logging method that must be implemented by all logger implementations + * + * All other [performLog] overloads will eventually call this method by default. + * + * @param level The severity level of the log message + * @param tag Optional tag to categorize or identify the source of the log + * @param message The message to be logged (can be any object, will be converted to string) + * @param throwable Optional exception or throwable to be logged alongside the message */ fun performLog(level: LogLevel, tag: String?, message: Any, throwable: Throwable?) /** - * Calls default [performLog] with `tag` == `null` + * Logs a message without a tag + * + * Convenience method that calls the main [performLog] with `tag` set to `null` + * + * @param level The severity level of the log message + * @param message The message to be logged + * @param throwable Optional exception or throwable to be logged */ fun performLog(level: LogLevel, message: Any, throwable: Throwable?) = performLog(level, null, message, throwable) /** - * Calls default [performLog] with `message` built using [messageBuilder]. This method supposed to be overriden in - * case when logger supports lazy-loaded messages (like [dev.inmo.kslog.common.filter.FilterKSLog]) + * Logs a message with lazy evaluation of the message content + * + * The [messageBuilder] lambda will only be executed if the message is actually logged. + * This is useful for expensive message construction that should be avoided when the + * message would be filtered out. + * + * This method should be overridden in logger implementations that support lazy evaluation + * (like [dev.inmo.kslog.common.filter.FilterKSLog]). + * + * @param level The severity level of the log message + * @param tag Optional tag to categorize the log + * @param throwable Optional exception or throwable to be logged + * @param messageBuilder Lambda that builds the message only when needed */ fun performLog( level: LogLevel, @@ -43,8 +90,18 @@ interface KSLog { ) = performLog(level, tag, messageBuilder(), throwable) /** - * Suspendable variant of [performLog] with [messageBuilder]. Uses default [performLog] with `message` built using - * [messageBuilder] by default + * Suspendable variant of [performLog] with lazy message evaluation + * + * Similar to the non-suspending [performLog] with [messageBuilder], but allows the + * message builder to be a suspending function. This enables logging with messages + * that require async operations to construct. + * + * By default, executes the suspending [messageBuilder] and calls the regular [performLog]. + * + * @param level The severity level of the log message + * @param tag Optional tag to categorize the log + * @param throwable Optional exception or throwable to be logged + * @param messageBuilder Suspending lambda that builds the message only when needed */ suspend fun performLogS( level: LogLevel, @@ -58,7 +115,13 @@ interface KSLog { private var defaultLogger: KSLog? = null /** - * Default logger used in case you are trying to use [KSLog] as a receiver for extensions like [info] + * Default logger instance used when calling logging extensions without an explicit receiver + * + * If not explicitly set, a default logger with tag "app" will be created automatically. + * You can customize this by setting your own logger implementation. + * + * @see setDefaultKSLog + * @see addDefaultKSLog */ var default: KSLog get() { @@ -87,21 +150,49 @@ interface KSLog { } +/** + * Creates a [CallbackKSLog] by invoking a [KSLog] instance with a callback function + * + * This operator allows convenient logger creation syntax: + * ```kotlin + * val logger = KSLog { level, tag, message, throwable -> + * // Custom logging logic + * } + * ``` + * + * @param performLogCallback The callback function to handle log messages + * @return A new [CallbackKSLog] instance + */ operator fun KSLog.invoke(performLogCallback: (level: LogLevel, tag: String?, message: Any, throwable: Throwable?) -> Unit) = CallbackKSLog(performLogCallback) +/** + * Simple logging implementation that uses `println` to output formatted log messages + * + * Uses [defaultMessageFormatter] to format messages before outputting to standard output. + * This is used as the default logging backend for Native and WASM platforms. + * + * @see defaultMessageFormatter + */ internal val printlnLogging: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit = { l, t, m, e -> println(defaultMessageFormatter(l, t, m, e)) } /** - * Simple builder for [DefaultKSLog] logger based on [defaultTag] + * Creates a [DefaultKSLog] logger with the specified default tag + * + * @param defaultTag The default tag to use for all log messages from this logger + * @return A new [DefaultKSLog] instance */ fun KSLog( defaultTag: String, ): KSLog = DefaultKSLog(defaultTag) /** - * Simple builder for [DefaultKSLog] logger based on [defaultTag] and [messageFormatter] + * Creates a [DefaultKSLog] logger with a custom message formatter + * + * @param defaultTag The default tag to use for all log messages + * @param messageFormatter Custom formatter for converting log parameters to strings + * @return A new [DefaultKSLog] instance */ fun KSLog( defaultTag: String, @@ -122,8 +213,15 @@ fun KSLog( ).filtered(filter) /** - * Building logger using [KSLog] builder based on [defaultTag] and [messageFormatter]. This logger will also filter - * incoming levels: only levels passed in [levels] param will be logged + * Creates a filtered [KSLog] that only logs messages at specific levels + * + * Builds a logger that will only process log messages whose level is included in the [levels] collection. + * All other log levels will be filtered out. + * + * @param defaultTag The default tag to use for all log messages + * @param levels Collection of log levels that should be logged + * @param messageFormatter Custom formatter for converting log parameters to strings (defaults to [defaultMessageFormatter]) + * @return A new filtered [KSLog] instance */ fun KSLog( defaultTag: String, @@ -137,8 +235,16 @@ fun KSLog( } /** - * Building logger using [KSLog] builder based on [defaultTag] and [messageFormatter]. This logger will also filter - * incoming levels: only levels passed in [firstLevel], [secondLevel] and [otherLevels] param will be logged + * Creates a filtered [KSLog] that only logs messages at the specified levels + * + * Convenience overload that accepts individual log levels as parameters. + * + * @param defaultTag The default tag to use for all log messages + * @param firstLevel First log level to include + * @param secondLevel Second log level to include + * @param otherLevels Additional log levels to include + * @param messageFormatter Custom formatter for converting log parameters to strings (defaults to [defaultMessageFormatter]) + * @return A new filtered [KSLog] instance */ fun KSLog( defaultTag: String, @@ -149,8 +255,16 @@ fun KSLog( ): KSLog = KSLog(defaultTag, setOf(firstLevel, secondLevel, *otherLevels), messageFormatter) /** - * Building logger using [KSLog] builder based on [defaultTag] and [messageFormatter]. This logger will also filter - * incoming levels: only levels above [minLoggingLevel] will be logged + * Creates a filtered [KSLog] that only logs messages at or above a minimum severity level + * + * Uses the ordinal values of [LogLevel] enum to determine which messages to log. + * For example, if [minLoggingLevel] is INFO, then INFO, WARNING, ERROR, and ASSERT will be logged, + * while TRACE, DEBUG, and VERBOSE will be filtered out. + * + * @param defaultTag The default tag to use for all log messages + * @param minLoggingLevel Minimum log level to include (inclusive) + * @param messageFormatter Custom formatter for converting log parameters to strings (defaults to [defaultMessageFormatter]) + * @return A new filtered [KSLog] instance */ fun KSLog( defaultTag: String, @@ -164,11 +278,22 @@ fun KSLog( } /** - * Setting [KSLog.default] logger to [newDefault] + * Sets the [KSLog.default] logger to a new instance + * + * This replaces the current default logger completely. + * + * @param newDefault The new default logger to use */ fun setDefaultKSLog(newDefault: KSLog) { KSLog.default = newDefault } + /** - * Setting [KSLog.default] logger to new [CallbackKSLog] using [plus] operation + * Adds an additional logger to the [KSLog.default] logger chain + * + * Uses the [plus] operator to combine the current default logger with [newDefault], + * so that log messages will be sent to both loggers. + * + * @param newDefault Additional logger to add to the default logger chain + * @see dev.inmo.kslog.common.utils.plus */ fun addDefaultKSLog(newDefault: KSLog) { KSLog.default += newDefault diff --git a/src/commonMain/kotlin/KSLogTypealiases.kt b/src/commonMain/kotlin/KSLogTypealiases.kt index 1d55ad4..66e24c2 100644 --- a/src/commonMain/kotlin/KSLogTypealiases.kt +++ b/src/commonMain/kotlin/KSLogTypealiases.kt @@ -1,7 +1,43 @@ package dev.inmo.kslog.common +/** + * Function type for formatting log messages + * + * @param l The log level + * @param t Optional tag for the log message + * @param m The message object to be logged + * @param Throwable Optional exception/throwable to be logged + * @return Formatted string representation of the log message + */ typealias MessageFormatter = (l: LogLevel, t: String?, m: Any, Throwable?) -> String + +/** + * Helper function to create a [MessageFormatter] from a lambda + */ inline fun MessageFormatter(noinline formatter: MessageFormatter) = formatter + +/** + * Function type for filtering log messages + * + * @param l The log level + * @param t Optional tag for the log message + * @param Throwable Optional exception/throwable associated with the log + * @return `true` if the message should be logged, `false` to filter it out + */ typealias MessageFilter = (l: LogLevel, t: String?, Throwable?) -> Boolean + +/** + * Default message formatter that formats logs as: `[LEVEL] tag - message` + * + * Example output: `[LogLevel.INFO] MyTag - Hello world` + */ val defaultMessageFormatter: MessageFormatter = { l, t, m, _ -> "[$l] ${t ?.let { "$it " } ?: ""}- $m" } + +/** + * Message formatter that includes stack trace of exceptions in the output + * + * Formats logs as: `[LEVEL] tag - message: stacktrace` + * + * Example output: `[LogLevel.ERROR] MyTag - Error occurred: java.lang.Exception: ...` + */ val defaultMessageFormatterWithErrorPrint: MessageFormatter = { l, t, m, e -> "[$l] ${t ?.let { "$it " } ?: ""}- $m${e ?.let { ": ${it.stackTraceToString()}" } ?: ""}" } diff --git a/src/commonMain/kotlin/KSLoggerDefaultPlatformLoggerLambdaExpect.kt b/src/commonMain/kotlin/KSLoggerDefaultPlatformLoggerLambdaExpect.kt index 1b88c9d..2ee0148 100644 --- a/src/commonMain/kotlin/KSLoggerDefaultPlatformLoggerLambdaExpect.kt +++ b/src/commonMain/kotlin/KSLoggerDefaultPlatformLoggerLambdaExpect.kt @@ -1,7 +1,21 @@ package dev.inmo.kslog.common /** - * Default logger for current platform. You may change it, but you should remember that it is global logger - * used in [KSLog.default] by default + * Platform-specific default logging implementation + * + * This is an `expect` declaration that provides platform-specific logging behavior: + * - **Android**: Uses `android.util.Log` (Log.d, Log.i, Log.w, Log.e, etc.) + * - **JVM**: Uses `java.util.logging.Logger` + * - **JS**: Uses browser `console` (console.debug, console.info, console.warn, console.error) + * - **Native/WASM**: Uses `println` for output + * + * This lambda is used by [DefaultKSLog] as the default logging backend when no custom + * logging function is provided. + * + * **Warning**: This is a global mutable variable. Changing it will affect all loggers + * that use the default platform logger. It's primarily used by [KSLog.default]. + * + * @see DefaultKSLog + * @see KSLog.default */ expect var KSLoggerDefaultPlatformLoggerLambda: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit \ No newline at end of file diff --git a/src/commonMain/kotlin/filter/FilterKSLog.kt b/src/commonMain/kotlin/filter/FilterKSLog.kt index 470dbf3..196ec06 100644 --- a/src/commonMain/kotlin/filter/FilterKSLog.kt +++ b/src/commonMain/kotlin/filter/FilterKSLog.kt @@ -3,8 +3,21 @@ package dev.inmo.kslog.common.filter import dev.inmo.kslog.common.* /** - * In its [performLog]/[performLogS] methods do logging only in cases when [messageFilter] returns true for incoming - * parameters + * A logger that filters messages before passing them to a fallback logger + * + * This logger implementation applies a [messageFilter] predicate to all incoming log requests. + * Only when the filter returns `true` will the message be passed to the [fallbackLogger]. + * + * This enables: + * - Log level filtering (e.g., only log ERROR and above) + * - Tag-based filtering (e.g., only log from specific components) + * - Conditional logging based on exception presence + * - Lazy message evaluation - messages are only constructed if they pass the filter + * + * @param fallbackLogger The underlying logger that will receive filtered messages + * @param messageFilter Predicate function that determines which messages to log + * + * @see filtered Extension function for convenient filter creation */ class FilterKSLog( private val fallbackLogger: KSLog, diff --git a/src/commonMain/kotlin/filter/FilteredExtension.kt b/src/commonMain/kotlin/filter/FilteredExtension.kt index 94b085d..cc20cf0 100644 --- a/src/commonMain/kotlin/filter/FilteredExtension.kt +++ b/src/commonMain/kotlin/filter/FilteredExtension.kt @@ -4,7 +4,21 @@ import dev.inmo.kslog.common.KSLog import dev.inmo.kslog.common.MessageFilter /** - * Creates [FilterKSLog] with applying of [filter] to it + * Creates a [FilterKSLog] that wraps this logger with a message filter + * + * This extension function provides a convenient way to add filtering to any existing logger. + * The resulting logger will only pass messages to this logger when the [filter] returns `true`. + * + * Example: + * ```kotlin + * val logger = KSLog("app").filtered { level, tag, throwable -> + * level.ordinal >= LogLevel.INFO.ordinal // Only log INFO and above + * } + * ``` + * + * @param filter Predicate function that receives (level, tag, throwable) and returns whether to log + * @return A new [FilterKSLog] instance wrapping this logger + * @see FilterKSLog */ fun KSLog.filtered( filter: MessageFilter diff --git a/src/commonMain/kotlin/typed/TypedKSLog.kt b/src/commonMain/kotlin/typed/TypedKSLog.kt index bd15239..3182aba 100644 --- a/src/commonMain/kotlin/typed/TypedKSLog.kt +++ b/src/commonMain/kotlin/typed/TypedKSLog.kt @@ -4,9 +4,25 @@ import dev.inmo.kslog.common.* import kotlin.reflect.KClass /** - * Uses [typedLoggers] [Map] to determine, where incoming __message__s should be sent. If there is no [KClass] key for - * incoming message in [typedLoggers], logger will use logger by `null` key if exists. If there is no default logger - * (by `null` key), logging will be skipped + * A logger that routes messages to different loggers based on the message type + * + * This logger uses the Kotlin class ([KClass]) of the log message to determine which logger to use. + * This enables type-based routing of log messages, allowing different message types to be + * handled by different loggers. + * + * The routing works as follows: + * 1. Extract the [KClass] from the incoming message object + * 2. Look up the class in [typedLoggers] map + * 3. If found, use that logger + * 4. If not found, fall back to the logger with `null` key (if it exists) + * 5. If no default logger exists, skip logging + * + * Example use case: Route structured log events to different destinations based on their type. + * + * @param typedLoggers Map from message class to logger. Use `null` key for the default/fallback logger + * + * @see TypedKSLogBuilder Builder for creating typed loggers + * @see buildTypedLogger DSL function for convenient creation */ class TypedKSLog( private val typedLoggers: Map?, KSLog> diff --git a/src/commonMain/kotlin/typed/TypedKSLogBuilder.kt b/src/commonMain/kotlin/typed/TypedKSLogBuilder.kt index 075cfe5..741e40d 100644 --- a/src/commonMain/kotlin/typed/TypedKSLogBuilder.kt +++ b/src/commonMain/kotlin/typed/TypedKSLogBuilder.kt @@ -4,7 +4,14 @@ import dev.inmo.kslog.common.* import kotlin.reflect.KClass /** - * Special builder for [TypedKSLog] + * Builder for creating [TypedKSLog] instances with a fluent API + * + * Provides convenient methods for configuring type-based routing of log messages. + * Supports both explicit [KClass] specifications and reified type parameters. + * + * @param preset Optional initial map of type-to-logger associations to start with + * + * @see buildTypedLogger DSL function for convenient usage */ class TypedKSLogBuilder( private val preset: Map?, KSLog> = emptyMap() @@ -13,20 +20,80 @@ class TypedKSLogBuilder( putAll(preset) } + /** + * Associates a specific class with a logger + * + * @param kClass The class to route, or `null` for the default/fallback logger + * @param with The logger to use for this class + */ fun on(kClass: KClass<*>?, with: KSLog) = loggers.put(kClass, with) + + /** + * Associates a specific class with a callback-based logger + * + * @param kClass The class to route, or `null` for the default/fallback logger + * @param with The callback function to handle logs for this class + */ fun on(kClass: KClass<*>?, with: SimpleKSLogCallback) = loggers.put(kClass, CallbackKSLog(with)) + /** + * Sets the default/fallback logger for messages of unregistered types + * + * @param with The logger to use as default + */ fun default(with: KSLog) = on(null, with) + + /** + * Sets the default/fallback logger using a callback function + * + * @param with The callback function to handle logs from unregistered types + */ fun default(with: SimpleKSLogCallback) = on(null, with) + /** + * Associates a specific type with a logger using reified type parameter + * + * Example: `on(customLogger)` + * + * @param T The type to route + * @param with The logger to use for this type + */ inline fun on(with: KSLog) = on(T::class, with) + + /** + * Associates a specific type with a callback-based logger using reified type parameter + * + * Example: `on { level, tag, message, error -> ... }` + * + * @param T The type to route + * @param with The callback function to handle logs for this type + */ inline fun on(noinline with: SimpleKSLogCallback) = on(T::class, with) + /** + * Builds the [TypedKSLog] instance with the configured type-to-logger associations + */ fun build() = TypedKSLog(loggers.toMap()) } /** - * DSL for [TypedKSLogBuilder] + * DSL function for building a [TypedKSLog] with a fluent configuration block + * + * Provides a convenient way to create typed loggers with type-to-logger associations. + * + * Example: + * ```kotlin + * val logger = buildTypedLogger { + * on(errorLogger) + * on(warningLogger) + * default(defaultLogger) + * } + * ``` + * + * @param preset Optional initial map of type-to-logger associations + * @param block Configuration block for specifying type-to-logger associations + * @return A new [TypedKSLog] instance + * @see TypedKSLogBuilder */ inline fun buildTypedLogger( preset: Map?, KSLog> = emptyMap(), diff --git a/src/commonMain/kotlin/utils/Combination.kt b/src/commonMain/kotlin/utils/Combination.kt index 543d121..f3133e8 100644 --- a/src/commonMain/kotlin/utils/Combination.kt +++ b/src/commonMain/kotlin/utils/Combination.kt @@ -4,8 +4,25 @@ import dev.inmo.kslog.common.CallbackKSLog import dev.inmo.kslog.common.KSLog /** - * Will send [KSLog.performLog] of both [this] and [other] [KSLog] instances. In case when [this] will throw exception - * result logger will rethrow it. After it, if [other] will throw exception - will also rethrow it + * Combines two loggers into one that sends messages to both + * + * Creates a new logger that will invoke [performLog] on both this logger and the [other] logger + * for every log message. Both loggers will be called even if one fails. + * + * Error handling: + * - If this logger throws an exception, it will be rethrown after attempting to log to [other] + * - If [other] throws an exception, it will also be rethrown + * - If both throw exceptions, both will be rethrown (first this logger's, then other's) + * + * Example: + * ```kotlin + * val combinedLogger = consoleLogger + fileLogger + * combinedLogger.info("Message") // Logs to both console and file + * ``` + * + * @param other The second logger to combine with this one + * @return A new [CallbackKSLog] that logs to both loggers + * @see addDefaultKSLog Uses this operator to add loggers to the default logger */ infix operator fun KSLog.plus(other: KSLog) = CallbackKSLog { l, t, m, e -> val resultOfFirst = runCatching { diff --git a/src/jsMain/kotlin/ExtendedConsole.kt b/src/jsMain/kotlin/ExtendedConsole.kt index 25864c7..3be5237 100644 --- a/src/jsMain/kotlin/ExtendedConsole.kt +++ b/src/jsMain/kotlin/ExtendedConsole.kt @@ -2,23 +2,62 @@ package dev.inmo.kslog.common import kotlin.js.Console +/** + * Extended Console interface that includes additional console methods + * not present in Kotlin's standard Console interface + * + * Provides access to browser/Node.js console methods like `debug`, `trace`, and `assert`. + */ external interface ExtendedConsole : Console { + /** + * Outputs a stack trace to the console + */ fun trace() + + /** + * Outputs a debug message to the console + * + * @param o Objects to output + */ fun debug(vararg o: Any?) + + /** + * Writes an error message to the console if the assertion is false + * + * @param assertion Boolean condition to test + * @param o Objects to output if assertion is false + */ fun assert(assertion: Boolean, vararg o: Any?) } /** - * [https://developer.mozilla.org/en-US/docs/Web/API/console/debug_static](https://developer.mozilla.org/en-US/docs/Web/API/console/debug_static) + * Extension function to output debug messages to the console + * + * Maps to the browser's `console.debug()` method. + * + * [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/console/debug_static) + * + * @param args Objects to output */ fun Console.debug(vararg args: Any?) = unsafeCast().debug(*args) /** - * [https://developer.mozilla.org/en-US/docs/Web/APtraceI/console/assert_static](https://developer.mozilla.org/en-US/docs/Web/API/console/assert_static) + * Extension function to write an error message if assertion fails + * + * Maps to the browser's `console.assert()` method. + * + * [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/console/assert_static) + * + * @param assertion Boolean condition to test + * @param args Objects to output if assertion is false */ fun Console.assert(assertion: Boolean, vararg args: Any?) = unsafeCast().assert(assertion, *args) /** - * [https://developer.mozilla.org/en-US/docs/Web/API/console/trace_static](https://developer.mozilla.org/en-US/docs/Web/API/console/trace_static) + * Extension function to output a stack trace to the console + * + * Maps to the browser's `console.trace()` method. + * + * [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/console/trace_static) */ fun Console.trace() = unsafeCast().trace() diff --git a/src/jsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt b/src/jsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt index e6fac74..e0e52c1 100644 --- a/src/jsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt +++ b/src/jsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt @@ -1,5 +1,23 @@ package dev.inmo.kslog.common +/** + * JavaScript platform implementation of the default logger + * + * Uses browser/Node.js `console` API as the logging backend, mapping KSLog levels + * to console methods: + * - [LogLevel.TRACE] → console.trace() + console.debug() + * - [LogLevel.DEBUG] → console.debug() + * - [LogLevel.VERBOSE] → console.info() + * - [LogLevel.INFO] → console.info() + * - [LogLevel.WARNING] → console.warn() + * - [LogLevel.ERROR] → console.error() + * - [LogLevel.ASSERT] → console.error() + * + * Logs can be viewed in the browser's Developer Tools console or Node.js console output. + * + * **Note**: The tag parameter is ignored in JS implementation as console methods + * don't support tagging natively. + */ actual var KSLoggerDefaultPlatformLoggerLambda: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit = { l, _, m, e -> val args = e ?.let { arrayOf(m, e) diff --git a/src/jvmMain/kotlin/ActualLogger.kt b/src/jvmMain/kotlin/ActualLogger.kt index 71099f6..117a979 100644 --- a/src/jvmMain/kotlin/ActualLogger.kt +++ b/src/jvmMain/kotlin/ActualLogger.kt @@ -4,11 +4,33 @@ import dev.inmo.kslog.common.filter.filtered import java.util.logging.Level import java.util.logging.Logger +/** + * Default Java Logger instance used by KSLog on JVM platform + * + * Initialized lazily with the name "KSLog" + */ internal val defaultKSLogLogger by lazy { Logger.getLogger("KSLog") } + +/** + * Extension function to log with KSLog levels using Java Logger + * + * Maps KSLog [LogLevel] to Java [Level]: + * - [LogLevel.TRACE] → [Level.FINEST] + * - [LogLevel.DEBUG] → [Level.FINER] + * - [LogLevel.VERBOSE] → [Level.FINE] + * - [LogLevel.INFO] → [Level.INFO] + * - [LogLevel.WARNING] → [Level.WARNING] + * - [LogLevel.ERROR] → [Level.SEVERE] + * - [LogLevel.ASSERT] → [Level.SEVERE] + * + * @param l KSLog log level + * @param m Message string + * @param e Optional throwable + */ internal fun Logger.doLog( - l: LogLevel, t: String, m: String, e: Throwable? + l: LogLevel, m: String, e: Throwable? ) = log( when(l) { LogLevel.TRACE -> Level.FINEST @@ -32,18 +54,35 @@ fun KSLog( ) = KSLog { l, t, m, e -> if (!filter(l, t, e)) return@KSLog val text = messageFormatter(l,t ?: defaultTag,m.toString(),e) - logger.doLog(l, t ?: defaultTag, text, e) + logger.doLog(l, text, e) } +/** + * Creates a KSLog that uses a specific Java [Logger] instance + * + * @param defaultTag Default tag to use when tag is not specified + * @param logger The Java Logger instance to use for logging + * @param messageFormatter Formatter for log messages (defaults to [defaultMessageFormatter]) + * @return A new [CallbackKSLog] instance wrapping the Java logger + */ fun KSLog( defaultTag: String, logger: Logger, messageFormatter: MessageFormatter = defaultMessageFormatter ) = KSLog { l, t, m, e -> val text = messageFormatter(l,t ?: defaultTag,m.toString(),e) - logger.doLog(l, t ?: defaultTag, text, e) + logger.doLog(l, text, e) } +/** + * Creates a filtered KSLog using a Java [Logger] that only logs specific levels + * + * @param defaultTag Default tag to use when tag is not specified + * @param logger The Java Logger instance to use for logging + * @param levels Collection of log levels to include + * @param messageFormatter Formatter for log messages (defaults to [defaultMessageFormatter]) + * @return A new filtered [KSLog] instance + */ fun KSLog( defaultTag: String, logger: Logger, @@ -54,6 +93,17 @@ fun KSLog( return KSLog (defaultTag, logger, messageFormatter).filtered { l, _, _ -> l in levelsSet } } +/** + * Creates a filtered KSLog using a Java [Logger] with specific log levels + * + * @param defaultTag Default tag to use when tag is not specified + * @param logger The Java Logger instance to use for logging + * @param firstLevel First log level to include + * @param secondLevel Second log level to include + * @param otherLevels Additional log levels to include + * @param messageFormatter Formatter for log messages (defaults to [defaultMessageFormatter]) + * @return A new filtered [KSLog] instance + */ fun KSLog( defaultTag: String, logger: Logger, @@ -63,6 +113,17 @@ fun KSLog( messageFormatter: MessageFormatter = defaultMessageFormatter, ): KSLog = KSLog (defaultTag, logger, setOf(firstLevel, secondLevel, *otherLevels), messageFormatter) +/** + * Creates a filtered KSLog using a Java [Logger] with a minimum log level + * + * Only logs messages at or above the specified minimum level. + * + * @param defaultTag Default tag to use when tag is not specified + * @param logger The Java Logger instance to use for logging + * @param minLoggingLevel Minimum log level to include (defaults to TRACE - the first level) + * @param messageFormatter Formatter for log messages (defaults to [defaultMessageFormatter]) + * @return A new filtered [KSLog] instance + */ fun KSLog( defaultTag: String, logger: Logger, diff --git a/src/jvmMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt b/src/jvmMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt index 8317513..52870cb 100644 --- a/src/jvmMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt +++ b/src/jvmMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt @@ -1,5 +1,13 @@ package dev.inmo.kslog.common +/** + * JVM platform implementation of the default logger + * + * Uses `[java.util.logging.Logger]` as the logging backend, mapping KSLog levels + * to Java logging levels. + * + * @see defaultKSLogLogger + */ actual var KSLoggerDefaultPlatformLoggerLambda: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit = { l, t, m, e -> - defaultKSLogLogger.doLog(l, t, m.toString(), e) + defaultKSLogLogger.doLog(l, m.toString(), e) } \ No newline at end of file diff --git a/src/nativeMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt b/src/nativeMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt index 305d580..17de881 100644 --- a/src/nativeMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt +++ b/src/nativeMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt @@ -1,4 +1,12 @@ package dev.inmo.kslog.common +/** + * Native platform implementation of the default logger + * + * Uses [printlnLogging] which formats and outputs logs using `[println]`. + * Logs are written to standard output. + * + * @see printlnLogging + */ actual var KSLoggerDefaultPlatformLoggerLambda: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit = printlnLogging \ No newline at end of file diff --git a/src/wasmJsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt b/src/wasmJsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt index 305d580..92abcbd 100644 --- a/src/wasmJsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt +++ b/src/wasmJsMain/kotlin/KSLoggerDefaultPlatformLoggerLambda.kt @@ -1,4 +1,11 @@ package dev.inmo.kslog.common +/** + * WebAssembly JavaScript platform implementation of the default logger + * + * Uses [printlnLogging] which formats and outputs logs using `[println]`. + * + * @see printlnLogging + */ actual var KSLoggerDefaultPlatformLoggerLambda: (level: LogLevel, tag: String, message: Any, throwable: Throwable?) -> Unit = printlnLogging \ No newline at end of file