Skip to content

Refactor: Unified Logger Provider Architecture #584

Merged
oshai merged 20 commits intomasterfrom
fix515
Jan 5, 2026
Merged

Refactor: Unified Logger Provider Architecture #584
oshai merged 20 commits intomasterfrom
fix515

Conversation

@oshai
Copy link
Owner

@oshai oshai commented Jan 3, 2026

Universal Provider Architecture Refactoring

Fixes #494
Fixes #515

Summary

This PR implements a Universal Provider Architecture, unified under a common configuration strategy. It enables swappable logging implementations (Providers) across all platforms (JVM, Android, Native, Darwin, JS, Wasm) and promotes the "Direct" logging implementation (Appenders) to be a first-class citizen available on every platform.

Key Changes

Unified Configuration (commonMain)

  • KotlinLoggingConfiguration is now accessible from commonMain and serves as the single entry point.
  • loggerFactory (KLoggerFactory): Controls the active logging provider (e.g., SLF4J, OSLog, Direct).
    • Users can runtime-swap the provider by setting this property.
  • direct Configuration Object: Dedicated namespace for Direct Logging settings.
    • KotlinLoggingConfiguration.direct.logLevel
    • KotlinLoggingConfiguration.direct.appender
    • KotlinLoggingConfiguration.direct.formatter
  • Validation & Diagnostics:
    • Prints the active Logger Factory on initialization (stderr) to aid debugging.
    • Prints specific warnings if a user tries to configure direct properties (like appender) while the active factory is not DirectLoggerFactory, preventing "silent ignore" confusion.

Platform-Specific Factories & Detection

The monolithic DefaultLoggerFactory has been removed. Logger selection is cleaner:

  • JVM: Detects the best available logger (JUL, Logback, or Direct) via system properties, defaulting to SLF4J.
  • Android: Detects AndroidNativeLoggerFactory or defaults to SLF4J.
  • Darwin: Defaults to DarwinLoggerFactory (OSLog).
  • Native/JS/Wasm: Defaults to DirectLoggerFactory.

Public API Moves

  • DirectLoggerFactory and DarwinLoggerFactory have been moved from internal packages to io.github.oshai.kotlinlogging.
    • This allows users to explicitly reference them when configuring KotlinLoggingConfiguration.loggerFactory.

Cross-Platform Appenders

  • Moved Appender, Formatter, Level, and KLoggingEvent to commonMain.
  • DirectLoggerFactory is available on ALL platforms.
    • You can write a custom Appender once in commonMain and use it everywhere.
    • On JVM/Android/Darwin, this requires opt-in: KotlinLoggingConfiguration.loggerFactory = DirectLoggerFactory.

Breaking Changes

  • Major Version Bump to 8.x:
  • Configuration Structure: logLevel, appender, and formatter are now nested under KotlinLoggingConfiguration.direct.
    • Old: KotlinLoggingConfiguration.logLevel = Level.INFO
    • New: KotlinLoggingConfiguration.direct.logLevel = Level.INFO
  • Property Rename: logFactory is now loggerFactory.
  • Removed Classes: DefaultLoggerFactory, KotlinLoggingLevel.kt (shadowed extension functions).

Verification

  • assembleCommonMain
  • jvmTest (SLF4J, JUL, Logback, and Direct tests passing)
  • compileReleaseKotlinAndroid
  • compileDarwinMainKotlinMetadata
  • compileKotlinJs / compileTestKotlinJs
  • compileKotlinWasmJs / compileTestKotlinWasmJs
  • compileKotlinWasmWasi / compileTestKotlinWasmWasi
  • spotlessApply

oshai added 5 commits January 3, 2026 22:16
- Promoted `KotlinLoggingConfiguration`, [Appender](cci:2://file:///Users/oshai/workspace/kotlin-logging/src/jvmMain/kotlin/io/github/oshai/kotlinlogging/ConsoleOutputAppender.kt:2:0-6:1), `Level`, and `KLoggingEvent` to `commonMain`.
- Introduced `public interface KLoggerFactory` in `commonMain` to allow runtime swapping of logger implementations.
- Added `DirectLoggerFactory` in `commonMain` to expose the direct/appender-based implementation to all platforms.
- Updated `KotlinLoggingConfiguration` to hold a mutable `LOG_FACTORY`, enabling users to opt-in to Direct logging (and custom Appenders) on JVM and Darwin.
- Refactored JVM and Darwin `DefaultLoggerFactory` to implement the new interface while preserving existing default behaviors (SLF4J/OSLog).
- Resolved `ErrorMessageProducer` cross-platform visibility by using platform aliases.
- Updated [CONTRIBUTING.md](cci:7://file:///Users/oshai/workspace/kotlin-logging/CONTRIBUTING.md:0:0-0:0) with build troubleshooting steps.
This change enables `FileAppender` and other custom appenders to be used on Darwin and JVM by configuring `KotlinLoggingConfiguration.LOG_FACTORY = DirectLoggerFactory`.
@oshai oshai changed the title Refactor: Unified Logger Provider Architecture (Fixes #494, #515) Refactor: Unified Logger Provider Architecture Jan 3, 2026
@oshai oshai requested a review from Copilot January 3, 2026 21:06
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the logger provider architecture to introduce a unified, configurable factory pattern across all platforms. The refactoring replaces the hardcoded internal KLoggerFactory object with a new public KLoggerFactory interface and moves platform-specific implementations to use this interface through KotlinLoggingConfiguration.logFactory.

Key changes:

  • Introduces a public KLoggerFactory interface and DirectLoggerFactory implementation for direct logging support
  • Adds a configurable logFactory property to KotlinLoggingConfiguration on all platforms, allowing runtime switching between logging implementations
  • Unifies the configuration model across JVM, Android, Darwin, Native, JS, and Wasm platforms using expect/actual patterns

Reviewed changes

Copilot reviewed 30 out of 36 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/commonMain/kotlin/io/github/oshai/kotlinlogging/KLoggerFactory.kt New public interface defining the logger factory contract
src/commonMain/kotlin/io/github/oshai/kotlinlogging/internal/DirectLoggerFactory.kt New direct logging factory implementation using KLoggerDirect
src/commonMain/kotlin/io/github/oshai/kotlinlogging/internal/KLoggerDirect.kt New direct logger implementation that uses configured appender
src/commonMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Adds expect declaration for logFactory property with documentation
src/commonMain/kotlin/io/github/oshai/kotlinlogging/KotlinLogging.kt Updates to use KotlinLoggingConfiguration.logFactory instead of internal factory
src/commonMain/kotlin/io/github/oshai/kotlinlogging/KLoggingEvent.kt New data class representing logging events
src/commonMain/kotlin/io/github/oshai/kotlinlogging/Appender.kt New interfaces for log appenders with formatting support
src/commonMain/kotlin/io/github/oshai/kotlinlogging/Formatter.kt New interfaces and default implementation for log message formatting
src/commonMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingLevel.kt New utility function for checking if logging is enabled for a level
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/internal/JvmLoggerFactory.kt Refactored to implement KLoggerFactory interface, adds support for direct logging via system property
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt New actual implementation with logFactory defaulting to JvmLoggerFactory
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/KLogging.kt Updates logger creation to use KotlinLoggingConfiguration.logFactory
src/androidMain/kotlin/io/github/oshai/kotlinlogging/internal/AndroidLoggerFactory.kt Refactored to implement KLoggerFactory interface
src/androidMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt New actual implementation with all common properties and AndroidLoggerFactory as default
src/darwinMain/kotlin/io/github/oshai/kotlinlogging/internal/DarwinLoggerFactory.kt Refactored to implement KLoggerFactory interface
src/darwinMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Updated to actual object with common properties, using DarwinLoggerFactory as default
src/darwinMain/kotlin/io/github/oshai/kotlinlogging/DefaultAppender.kt New file defining platform default appender
src/darwinMain/kotlin/io/github/oshai/kotlinlogging/ConsoleOutputAppender.kt New console appender using POSIX fprintf for stderr
src/nativeMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Updated with logFactory property using DirectLoggerFactory
src/nativeMain/kotlin/io/github/oshai/kotlinlogging/DefaultAppender.kt New file defining platform default appender
src/nativeMain/kotlin/io/github/oshai/kotlinlogging/internal/ErrorMessageProducer.kt New typealias to DefaultErrorMessageProducer
src/jsMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Updated with logFactory property using DirectLoggerFactory
src/jsMain/kotlin/io/github/oshai/kotlinlogging/internal/ErrorMessageProducer.kt New typealias to DefaultErrorMessageProducer
src/wasmJsMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Updated with logFactory property using DirectLoggerFactory
src/wasmJsMain/kotlin/io/github/oshai/kotlinlogging/internal/ErrorMessageProducer.kt New typealias to DefaultErrorMessageProducer
src/wasmWasiMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Updated with logFactory property using DirectLoggerFactory
src/wasmWasiMain/kotlin/io/github/oshai/kotlinlogging/internal/ErrorMessageProducer.kt New typealias to DefaultErrorMessageProducer
src/javaMain/kotlin/io/github/oshai/kotlinlogging/DefaultAppender.kt New file defining platform default appender
src/javaMain/kotlin/io/github/oshai/kotlinlogging/ConsoleOutputAppender.kt New console appender using println
src/directMain/kotlin/io/github/oshai/kotlinlogging/internal/KLoggerFactory.kt Removed - functionality moved to common DirectLoggerFactory
src/directMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Removed - expect declarations moved to commonMain
src/linuxMain/kotlin/io/github/oshai/kotlinlogging/KotlinLoggingConfiguration.kt Removed - functionality moved to nativeMain
fix_repo.gradle New Gradle init script to override repositories for build troubleshooting
CONTRIBUTING.md Added troubleshooting section for dependency resolution issues
settings.gradle.kts Minor formatting change (added blank line)
Comments suppressed due to low confidence (1)

src/jvmMain/kotlin/io/github/oshai/kotlinlogging/internal/JvmLoggerFactory.kt:21

  • Missing import for DirectLoggerFactory. The code uses DirectLoggerFactory.logger(name) on line 21, but DirectLoggerFactory is not imported. Add the import statement: import io.github.oshai.kotlinlogging.internal.DirectLoggerFactory

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 45 out of 48 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 20 to 26
/**
* Configuration for the **Direct Logging** implementation.
*
* These settings only apply when the [KotlinLoggingConfiguration.loggerFactory] is set to
* [io.github.oshai.kotlinlogging.internal.DirectLoggerFactory], which is the default on Native,
* JS, and Wasm, and can be opted-into on JVM, Android, and Darwin.
*/
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This documentation block appears to be duplicated. The DirectLoggingConfiguration interface is already documented on lines 11-17 above. This duplicate documentation should be removed to avoid confusion and maintain cleaner code.

Suggested change
/**
* Configuration for the **Direct Logging** implementation.
*
* These settings only apply when the [KotlinLoggingConfiguration.loggerFactory] is set to
* [io.github.oshai.kotlinlogging.internal.DirectLoggerFactory], which is the default on Native,
* JS, and Wasm, and can be opted-into on JVM, Android, and Darwin.
*/

Copilot uses AI. Check for mistakes.
public actual object KotlinLoggingConfiguration {
/**
* The global logger factory used by `KotlinLogging.logger`. Change this to swap the underlying
* logging implementation (e.g., to [io.github.oshai.kotlinlogging.internal.DirectLoggerFactory]
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KDoc reference points to io.github.oshai.kotlinlogging.internal.DirectLoggerFactory, but DirectLoggerFactory has been promoted to the public API and moved to io.github.oshai.kotlinlogging package (as indicated in the PR description). The reference should be updated to just DirectLoggerFactory since it's in the same package.

Copilot uses AI. Check for mistakes.
import io.github.oshai.kotlinlogging.internal.KLoggerDirect

/**
* A [KLoggerFactory] that creates [io.github.oshai.kotlinlogging.internal.KLoggerDirect] instances.
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KDoc references io.github.oshai.kotlinlogging.internal.KLoggerDirect which is an internal implementation class. Since this is public API documentation, it would be clearer to simply refer to it as "Direct logger instances" or remove the specific class reference. Internal implementation details should not be prominently featured in public API documentation.

Copilot uses AI. Check for mistakes.
*/
public object DirectLoggerFactory : KLoggerFactory {

/** Returns a [io.github.oshai.kotlinlogging.internal.KLoggerDirect] with the given [name]. */
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KDoc references io.github.oshai.kotlinlogging.internal.KLoggerDirect, exposing internal implementation details in public API documentation. Consider simplifying this to just describe the return value without referencing internal classes.

Copilot uses AI. Check for mistakes.
public expect object KotlinLoggingConfiguration {
/**
* The global logger factory used by `KotlinLogging.logger`. Change this to swap the underlying
* logging implementation (e.g., to [io.github.oshai.kotlinlogging.internal.DirectLoggerFactory]
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KDoc reference points to io.github.oshai.kotlinlogging.internal.DirectLoggerFactory, but based on the PR description and other files (e.g., DirectLoggerFactory.kt), the DirectLoggerFactory has been moved from the internal package to io.github.oshai.kotlinlogging package. The reference should be updated to io.github.oshai.kotlinlogging.DirectLoggerFactory or simply DirectLoggerFactory since it's in the same package.

Copilot uses AI. Check for mistakes.
@oshai oshai merged commit 6f21b1a into master Jan 5, 2026
9 checks passed
@oshai oshai deleted the fix515 branch January 5, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide an API to register multiple appenders KotlinLoggingConfiguration is not accessible on nativeMain

1 participant