From b1d684c666496852c310913a10e2fb7b097563d0 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 30 Oct 2025 14:41:40 -0400 Subject: [PATCH 01/20] Adding initial extension --- extensions/kermit-ktor/README.md | 26 +++++++++ extensions/kermit-ktor/api/kermit-ktor.api | 0 extensions/kermit-ktor/build.gradle.kts | 57 +++++++++++++++++++ .../touchlab/kermit/ktor/KermitKtorLogger.kt | 30 ++++++++++ gradle/libs.versions.toml | 2 + settings.gradle.kts | 2 + 6 files changed, 117 insertions(+) create mode 100644 extensions/kermit-ktor/README.md create mode 100644 extensions/kermit-ktor/api/kermit-ktor.api create mode 100644 extensions/kermit-ktor/build.gradle.kts create mode 100644 extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt diff --git a/extensions/kermit-ktor/README.md b/extensions/kermit-ktor/README.md new file mode 100644 index 00000000..b97d6ca4 --- /dev/null +++ b/extensions/kermit-ktor/README.md @@ -0,0 +1,26 @@ +# Kermit-Ktor Integration + +The Kermit-Ktor module provides a way to add multiplatform logging to your Ktor client. + +Firstly, add the gradle dependency to your project. + +```kotlin +sourceSets { + commonMain { + dependencies { + implementation("co.touchlab:kermit-ktor:x.y.z") // Add the latest version + } + } +} +``` + +Then add the Kermit logger when you create your Ktor client - + +```kotlin +val koinApplication = startKoin { + modules( ... ) + + val kermit = Logger.withTag("koin") + logger(KermitKoinLogger(kermit)) +} +``` \ No newline at end of file diff --git a/extensions/kermit-ktor/api/kermit-ktor.api b/extensions/kermit-ktor/api/kermit-ktor.api new file mode 100644 index 00000000..e69de29b diff --git a/extensions/kermit-ktor/build.gradle.kts b/extensions/kermit-ktor/build.gradle.kts new file mode 100644 index 00000000..c085edeb --- /dev/null +++ b/extensions/kermit-ktor/build.gradle.kts @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Touchlab + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.multiplatform) + id("kermit-jvm-target") + id("kermit-publish") +} + +kotlin { + androidTarget { + publishAllLibraryVariants() + } + macosX64() + macosArm64() + iosX64() + iosArm64() + iosSimulatorArm64() + tvosArm64() + tvosSimulatorArm64() + tvosX64() + watchosArm32() + watchosArm64() + watchosSimulatorArm64() + watchosDeviceArm64() + watchosX64() + + sourceSets { + commonMain.dependencies { + implementation(libs.ktor.logging) + implementation(project(":kermit")) + } + } +} + +android { + namespace = "co.touchlab.kermit.ktor" + compileSdk = libs.versions.compileSdk.get().toInt() + defaultConfig { + minSdk = libs.versions.minSdk.get().toInt() + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} diff --git a/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt b/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt new file mode 100644 index 00000000..f02981c7 --- /dev/null +++ b/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Touchlab + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ + +package co.touchlab.kermit.ktor + +import co.touchlab.kermit.Logger as KermitLogger +import co.touchlab.kermit.LoggerConfig +import co.touchlab.kermit.Severity +import io.ktor.client.plugins.logging.Logger as KtorLogger + +class KermitKtorLogger(private val severity: Severity, config: LoggerConfig, tag: String = "") : KermitLogger(config, tag), KtorLogger { + // Overriding Ktor + override fun log(message: String) { + when (severity) { + Severity.Verbose -> this.v(messageString = message) + Severity.Debug -> this.d(messageString = message) + Severity.Info -> this.i(messageString = message) + Severity.Warn -> this.w(messageString = message) + Severity.Error -> this.e(messageString = message) + Severity.Assert -> this.a(messageString = message) + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2680c424..95c2f5ce 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,6 +36,7 @@ android-junitTest = "1.1.5" junit = "4.13.2" dokka = "2.0.0" touchlab-docusaurus-template = "0.1.11" +ktor = "3.3.1" ktlint-gradle = "12.3.0" @@ -52,6 +53,7 @@ androidx-runner = { module = "androidx.test:runner", version.ref = "android-test crashkios-crashlytics = { module = "co.touchlab.crashkios:crashlytics", version.ref = "crashkios" } crashkios-bugsnag = { module = "co.touchlab.crashkios:bugsnag", version.ref = "crashkios" } bugsnag-android = { module = "com.bugsnag:bugsnag-android", version.ref = "bugsnag" } +ktor-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" } stately-collections = { module = "co.touchlab:stately-collections", version.ref = "stately" } testhelp = { module = "co.touchlab:testhelp", version.ref = "testhelp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index b24bccc3..6b2ab394 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,10 +19,12 @@ include(":kermit-test") include(":kermit-crashlytics") include(":kermit-bugsnag") include(":kermit-koin") +include(":kermit-ktor") project(":kermit-crashlytics").projectDir = File("extensions/kermit-crashlytics") project(":kermit-bugsnag").projectDir = File("extensions/kermit-bugsnag") project(":kermit-koin").projectDir = File("extensions/kermit-koin") +project(":kermit-ktor").projectDir = File("extensions/kermit-ktor") // include(":kermit-gradle-plugin") // include(":kermit-ir-plugin") From fb1a9f5d5fa2c36061c9c36300a53d444406b91b Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 30 Oct 2025 14:57:35 -0400 Subject: [PATCH 02/20] updating call and readme --- extensions/kermit-ktor/README.md | 21 ++++++++++---- .../touchlab/kermit/ktor/KermitKtorLogger.kt | 28 +++++++++++++------ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/extensions/kermit-ktor/README.md b/extensions/kermit-ktor/README.md index b97d6ca4..6d7ed156 100644 --- a/extensions/kermit-ktor/README.md +++ b/extensions/kermit-ktor/README.md @@ -17,10 +17,21 @@ sourceSets { Then add the Kermit logger when you create your Ktor client - ```kotlin -val koinApplication = startKoin { - modules( ... ) - - val kermit = Logger.withTag("koin") - logger(KermitKoinLogger(kermit)) +val httpClient = HttpClient { + install(Logging) { + logger = KermitKtorLogger(severity = Severity.Info, logger = KermitLogger, tag = "") + level = LogLevel.INFO + } +} +``` + +or alternatively + +```kotlin +val httpClient = HttpClient { + install(Logging) { + logger = KermitKtorLogger(severity = Severity.Info, config = loggerConfigInit(CommonWriter()), tag = "") + level = LogLevel.INFO + } } ``` \ No newline at end of file diff --git a/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt b/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt index f02981c7..198dab01 100644 --- a/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt +++ b/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt @@ -15,16 +15,28 @@ import co.touchlab.kermit.LoggerConfig import co.touchlab.kermit.Severity import io.ktor.client.plugins.logging.Logger as KtorLogger -class KermitKtorLogger(private val severity: Severity, config: LoggerConfig, tag: String = "") : KermitLogger(config, tag), KtorLogger { - // Overriding Ktor +class KermitKtorLogger( + private val severity: Severity, + private val logger:KermitLogger, +) : KtorLogger { + + constructor( + severity: Severity, + config: LoggerConfig, + tag: String = "" + ) : this( + logger = KermitLogger(config = config, tag = tag), + severity = severity + ) + override fun log(message: String) { when (severity) { - Severity.Verbose -> this.v(messageString = message) - Severity.Debug -> this.d(messageString = message) - Severity.Info -> this.i(messageString = message) - Severity.Warn -> this.w(messageString = message) - Severity.Error -> this.e(messageString = message) - Severity.Assert -> this.a(messageString = message) + Severity.Verbose -> logger.v(messageString = message) + Severity.Debug -> logger.d(messageString = message) + Severity.Info -> logger.i(messageString = message) + Severity.Warn -> logger.w(messageString = message) + Severity.Error -> logger.e(messageString = message) + Severity.Assert -> logger.a(messageString = message) } } } From 522752188cecd330ce494d9ae53b3eb02066d1c4 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 30 Oct 2025 15:05:18 -0400 Subject: [PATCH 03/20] updating API --- extensions/kermit-ktor/api/kermit-ktor.api | 7 +++++++ .../kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt | 9 +++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/extensions/kermit-ktor/api/kermit-ktor.api b/extensions/kermit-ktor/api/kermit-ktor.api index e69de29b..35617cdf 100644 --- a/extensions/kermit-ktor/api/kermit-ktor.api +++ b/extensions/kermit-ktor/api/kermit-ktor.api @@ -0,0 +1,7 @@ +public final class co/touchlab/kermit/ktor/KermitKtorLogger : io/ktor/client/plugins/logging/Logger { + public fun (Lco/touchlab/kermit/Severity;Lco/touchlab/kermit/Logger;)V + public fun (Lco/touchlab/kermit/Severity;Lco/touchlab/kermit/LoggerConfig;Ljava/lang/String;)V + public synthetic fun (Lco/touchlab/kermit/Severity;Lco/touchlab/kermit/LoggerConfig;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun log (Ljava/lang/String;)V +} + diff --git a/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt b/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt index 198dab01..120c62b4 100644 --- a/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt +++ b/extensions/kermit-ktor/src/commonMain/kotlin/co/touchlab/kermit/ktor/KermitKtorLogger.kt @@ -15,18 +15,15 @@ import co.touchlab.kermit.LoggerConfig import co.touchlab.kermit.Severity import io.ktor.client.plugins.logging.Logger as KtorLogger -class KermitKtorLogger( - private val severity: Severity, - private val logger:KermitLogger, -) : KtorLogger { +class KermitKtorLogger(private val severity: Severity, private val logger: KermitLogger) : KtorLogger { constructor( severity: Severity, config: LoggerConfig, - tag: String = "" + tag: String = "", ) : this( logger = KermitLogger(config = config, tag = tag), - severity = severity + severity = severity, ) override fun log(message: String) { From 4cfb2a6fb088f8b7e0e3d6cc459ad2cc77239f68 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 30 Oct 2025 15:14:38 -0400 Subject: [PATCH 04/20] Updating readme and website --- extensions/kermit-ktor/README.md | 2 +- website/docs/extensions/KOIN.md | 2 +- website/docs/extensions/KTOR.md | 41 ++++++++++++++++++++++++++++++++ website/docs/extensions/index.md | 6 ++++- 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 website/docs/extensions/KTOR.md diff --git a/extensions/kermit-ktor/README.md b/extensions/kermit-ktor/README.md index 6d7ed156..f2564d80 100644 --- a/extensions/kermit-ktor/README.md +++ b/extensions/kermit-ktor/README.md @@ -19,7 +19,7 @@ Then add the Kermit logger when you create your Ktor client - ```kotlin val httpClient = HttpClient { install(Logging) { - logger = KermitKtorLogger(severity = Severity.Info, logger = KermitLogger, tag = "") + logger = KermitKtorLogger(severity = Severity.Info, logger = KermitLogger) level = LogLevel.INFO } } diff --git a/website/docs/extensions/KOIN.md b/website/docs/extensions/KOIN.md index 3ab17617..7f62d2f8 100644 --- a/website/docs/extensions/KOIN.md +++ b/website/docs/extensions/KOIN.md @@ -1,6 +1,6 @@ # Koin Integration -Kermit's Koin integation comes in two parts - a logger implementation that writes +Kermit's Koin integration comes in two parts - a logger implementation that writes Koin logger output to Kermit, and dependency injection helpers. ## Setup diff --git a/website/docs/extensions/KTOR.md b/website/docs/extensions/KTOR.md new file mode 100644 index 00000000..4a9cddfa --- /dev/null +++ b/website/docs/extensions/KTOR.md @@ -0,0 +1,41 @@ +# Koin Integration + +Kermit's Ktor integration allows you to pass in a Kermit logger instance to your Ktor client. + +## Setup + +### Add the dependency + +```kotlin +commonMain { + dependencies { + implementation("co.touchlab:kermit-ktor:{{LATEST_GITHUB_VERSION}}") + } +} +``` + +### Add the logger to your client + +```kotlin +val httpClient = HttpClient { + install(Logging) { + logger = KermitKtorLogger(severity = Severity.Info, logger = KermitLogger) + level = LogLevel.INFO + } +} +``` + +or alternatively + +```kotlin +val httpClient = HttpClient { + install(Logging) { + logger = KermitKtorLogger(severity = Severity.Info, config = loggerConfigInit(CommonWriter()), tag = "") + level = LogLevel.INFO + } +} +``` + +This takes in a Kermit logger instance, or alternatively a Kermit logger configuration to create a logger from. +This should allow some flexibility in how you want to set up your logging. You will also need to pass in a severity +level to log to, since the Ktor logger interface does not have levels itself. \ No newline at end of file diff --git a/website/docs/extensions/index.md b/website/docs/extensions/index.md index b3d73009..9ec78fee 100644 --- a/website/docs/extensions/index.md +++ b/website/docs/extensions/index.md @@ -14,4 +14,8 @@ Bugsnag breadcrumb writing. ## [Koin](KOIN) -Integration with Koin, for easy logger injection. \ No newline at end of file +Integration with Koin, for easy logger injection. + +## [Ktor](KTOR) + +Integration with Ktor, for easy client logging. \ No newline at end of file From 0887c9b01913e96b131bfcc3eacff4d561368950 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 30 Oct 2025 15:53:21 -0400 Subject: [PATCH 05/20] Adding Ktor Logger to sample --- .../sample/app/src/main/AndroidManifest.xml | 3 ++ .../co/touchlab/KermitSample/FirstFragment.kt | 8 +++++ .../src/main/res/layout/fragment_first.xml | 18 ++++++++--- samples/sample/shared/build.gradle.kts | 5 +++ .../co/touchlab/kermitsample/CommonClient.kt | 31 +++++++++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 samples/sample/shared/src/commonMain/kotlin/co/touchlab/kermitsample/CommonClient.kt diff --git a/samples/sample/app/src/main/AndroidManifest.xml b/samples/sample/app/src/main/AndroidManifest.xml index d0e97e26..6b458e7f 100644 --- a/samples/sample/app/src/main/AndroidManifest.xml +++ b/samples/sample/app/src/main/AndroidManifest.xml @@ -11,6 +11,9 @@ + + + + +