Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KTOR-1219 Make Android logger log to Logcat on Android if the SLF4J b… #4009

Merged
merged 4 commits into from
Apr 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package io.ktor.client.plugins.logging

import io.ktor.client.*
import org.slf4j.*
import org.slf4j.helpers.NOPLoggerFactory

public actual val Logger.Companion.DEFAULT: Logger
get() = object : Logger {
Expand All @@ -16,11 +17,50 @@ public actual val Logger.Companion.DEFAULT: Logger
}

/**
* Android [Logger]: breaks up long log messages that would be truncated by Android's max log
* length of 4068 characters
* Android [Logger]: Logs to the Logcat on Android if the SLF4J provider isn't found.
* Otherwise, uses the [Logger.Companion.DEFAULT].
* Breaks up long log messages that would be truncated by Android's max log
* length of 4068 characters.
*/
public val Logger.Companion.ANDROID: Logger
get() = MessageLengthLimitingLogger()
public val Logger.Companion.ANDROID: Logger by lazy { getAndroidLogger() }

private fun getAndroidLogger(): Logger {
val logger = Logger.DEFAULT

val logClass = try {
Class.forName("android.util.Log")
} catch (_: ClassNotFoundException) {
return MessageLengthLimitingLogger(delegate = logger)
}

if (LoggerFactory.getILoggerFactory() !is NOPLoggerFactory) {
return MessageLengthLimitingLogger(delegate = logger)
}

return MessageLengthLimitingLogger(delegate = LogcatLogger(logClass, logger))
}

private class LogcatLogger(logClass: Class<*>, private val fallback: Logger) : Logger {
private val tag = "Ktor Client"

private val method = try {
logClass.getDeclaredMethod("i", String::class.java, String::class.java)
} catch (_: Throwable) {
null
}
override fun log(message: String) {
if (method == null) {
fallback.log(message)
return
}

try {
method.invoke(null, tag, message)
} catch (_: Throwable) {
fallback.log(message)
}
}
}

/**
* A [Logger] that breaks up log messages into multiple logs no longer than [maxLength]
Expand Down