Skip to content

Commit 2bd38d1

Browse files
typotternicklasl
andauthored
feat: Add structured logging to Logger interface (#233)
Signed-off-by: Tyler Potter <tyler.john.potter@gmail.com> Co-authored-by: Nicklas Lundin <nicklasl@spotify.com>
1 parent e7e29a5 commit 2bd38d1

13 files changed

Lines changed: 569 additions & 356 deletions

File tree

kotlin-sdk/api/android/kotlin-sdk.api

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -830,21 +830,21 @@ public final class dev/openfeature/kotlin/sdk/logging/LogLevel : java/lang/Enum
830830
}
831831

832832
public abstract interface class dev/openfeature/kotlin/sdk/logging/Logger {
833-
public abstract fun debug (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
834-
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
835-
public abstract fun error (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
836-
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
837-
public abstract fun info (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
838-
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
839-
public abstract fun warn (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
840-
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
833+
public abstract fun debug (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
834+
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
835+
public abstract fun error (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
836+
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
837+
public abstract fun info (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
838+
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
839+
public abstract fun warn (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
840+
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
841841
}
842842

843843
public final class dev/openfeature/kotlin/sdk/logging/Logger$DefaultImpls {
844-
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
845-
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
846-
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
847-
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
844+
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
845+
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
846+
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
847+
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
848848
}
849849

850850
public final class dev/openfeature/kotlin/sdk/logging/LoggerFactory {
@@ -855,10 +855,10 @@ public final class dev/openfeature/kotlin/sdk/logging/LoggerFactory {
855855

856856
public final class dev/openfeature/kotlin/sdk/logging/NoOpLogger : dev/openfeature/kotlin/sdk/logging/Logger {
857857
public fun <init> ()V
858-
public fun debug (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
859-
public fun error (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
860-
public fun info (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
861-
public fun warn (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
858+
public fun debug (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
859+
public fun error (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
860+
public fun info (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
861+
public fun warn (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
862862
}
863863

864864
public final class dev/openfeature/kotlin/sdk/multiprovider/FirstMatchStrategy : dev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Strategy {

kotlin-sdk/api/jvm/kotlin-sdk.api

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -830,21 +830,21 @@ public final class dev/openfeature/kotlin/sdk/logging/LogLevel : java/lang/Enum
830830
}
831831

832832
public abstract interface class dev/openfeature/kotlin/sdk/logging/Logger {
833-
public abstract fun debug (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
834-
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
835-
public abstract fun error (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
836-
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
837-
public abstract fun info (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
838-
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
839-
public abstract fun warn (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
840-
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
833+
public abstract fun debug (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
834+
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
835+
public abstract fun error (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
836+
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
837+
public abstract fun info (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
838+
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
839+
public abstract fun warn (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
840+
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
841841
}
842842

843843
public final class dev/openfeature/kotlin/sdk/logging/Logger$DefaultImpls {
844-
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
845-
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
846-
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
847-
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
844+
public static synthetic fun debug$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
845+
public static synthetic fun error$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
846+
public static synthetic fun info$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
847+
public static synthetic fun warn$default (Ldev/openfeature/kotlin/sdk/logging/Logger;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;ILjava/lang/Object;)V
848848
}
849849

850850
public final class dev/openfeature/kotlin/sdk/logging/LoggerFactory {
@@ -855,10 +855,10 @@ public final class dev/openfeature/kotlin/sdk/logging/LoggerFactory {
855855

856856
public final class dev/openfeature/kotlin/sdk/logging/NoOpLogger : dev/openfeature/kotlin/sdk/logging/Logger {
857857
public fun <init> ()V
858-
public fun debug (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
859-
public fun error (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
860-
public fun info (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
861-
public fun warn (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function0;)V
858+
public fun debug (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
859+
public fun error (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
860+
public fun info (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
861+
public fun warn (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Ljava/lang/Throwable;)V
862862
}
863863

864864
public final class dev/openfeature/kotlin/sdk/multiprovider/FirstMatchStrategy : dev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Strategy {

kotlin-sdk/src/androidMain/kotlin/dev/openfeature/kotlin/sdk/logging/LoggerFactory.kt

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,32 @@ actual object LoggerFactory {
1313
/**
1414
* Android-specific logger implementation using android.util.Log.
1515
* Logs are visible in Logcat.
16+
* Attributes are appended to the message as key=value pairs.
1617
*/
1718
internal class AndroidLogger(private val tag: String) : Logger {
18-
override fun debug(throwable: Throwable?, message: () -> String) {
19-
Log.d(tag, message(), throwable)
19+
// throwable is passed directly to Log.*() which formats the stack trace natively.
20+
// Do NOT pass throwable to formatLogLine here — it would duplicate the stack trace in Logcat.
21+
override fun debug(message: () -> String, attributes: () -> Map<String, Any?>, throwable: Throwable?) {
22+
if (!Log.isLoggable(tag, Log.DEBUG)) return
23+
val msg = formatLogLine(message(), attributes())
24+
if (throwable != null) Log.d(tag, msg, throwable) else Log.d(tag, msg)
2025
}
2126

22-
override fun info(throwable: Throwable?, message: () -> String) {
23-
Log.i(tag, message(), throwable)
27+
override fun info(message: () -> String, attributes: () -> Map<String, Any?>, throwable: Throwable?) {
28+
if (!Log.isLoggable(tag, Log.INFO)) return
29+
val msg = formatLogLine(message(), attributes())
30+
if (throwable != null) Log.i(tag, msg, throwable) else Log.i(tag, msg)
2431
}
2532

26-
override fun warn(throwable: Throwable?, message: () -> String) {
27-
Log.w(tag, message(), throwable)
33+
override fun warn(message: () -> String, attributes: () -> Map<String, Any?>, throwable: Throwable?) {
34+
if (!Log.isLoggable(tag, Log.WARN)) return
35+
val msg = formatLogLine(message(), attributes())
36+
if (throwable != null) Log.w(tag, msg, throwable) else Log.w(tag, msg)
2837
}
2938

30-
override fun error(throwable: Throwable?, message: () -> String) {
31-
Log.e(tag, message(), throwable)
39+
override fun error(message: () -> String, attributes: () -> Map<String, Any?>, throwable: Throwable?) {
40+
if (!Log.isLoggable(tag, Log.ERROR)) return
41+
val msg = formatLogLine(message(), attributes())
42+
if (throwable != null) Log.e(tag, msg, throwable) else Log.e(tag, msg)
3243
}
3344
}

0 commit comments

Comments
 (0)