tessl install tessl/kotlin-io-ktor--ktor-client-logging-macosx64@2.3.0HTTP client logging plugin for Ktor framework with configurable log levels and header sanitization support
Ktor Client Logging provides comprehensive HTTP client logging capabilities for the Ktor framework. It offers configurable logging levels, request/response filtering, header sanitization, and platform-specific logger implementations with full coroutine support.
build.gradle.kts dependenciesimport io.ktor.client.plugins.logging.*
import io.ktor.client.*import io.ktor.client.*
import io.ktor.client.plugins.logging.*
// Basic logging configuration
val client = HttpClient {
install(Logging) {
level = LogLevel.HEADERS
logger = Logger.DEFAULT
}
}
// Advanced configuration with filtering and sanitization
val client = HttpClient {
install(Logging) {
level = LogLevel.ALL
logger = Logger.SIMPLE
// Filter requests to only log specific URLs
filter { request ->
request.url.host.contains("api.example.com")
}
// Sanitize sensitive headers
sanitizeHeader("***") { header ->
header == "Authorization" || header == "API-Key"
}
}
}
// Make logged HTTP requests
client.get("https://api.example.com/users")Ktor Client Logging integrates with the Ktor HTTP client pipeline through several key components:
HttpClientPlugin for seamless integration with Ktor clientsMain plugin class providing HTTP client logging capabilities with extensive configuration options.
/**
* A client's plugin that provides the capability to log HTTP calls.
*/
class Logging private constructor(
val logger: Logger,
var level: LogLevel,
var filters: List<(HttpRequestBuilder) -> Boolean> = emptyList()
) {
companion object : HttpClientPlugin<Config, Logging> {
override val key: AttributeKey<Logging>
override fun prepare(block: Config.() -> Unit): Logging
override fun install(plugin: Logging, scope: HttpClient)
}
}
/**
* A configuration for the Logging plugin.
*/
class Logging.Config {
/** Specifies a Logger instance */
var logger: Logger
/** Specifies the logging level */
var level: LogLevel
/** Allows you to filter log messages for calls matching a predicate */
fun filter(predicate: (HttpRequestBuilder) -> Boolean)
/** Allows you to sanitize sensitive headers to avoid their values appearing in the logs */
fun sanitizeHeader(placeholder: String = "***", predicate: (String) -> Boolean)
}
/**
* Configures and installs Logging in HttpClient.
*/
fun HttpClientConfig<*>.Logging(block: Logging.Config.() -> Unit = {})Defines the verbosity and scope of HTTP logging operations.
/**
* Logging log level.
*/
enum class LogLevel(
val info: Boolean,
val headers: Boolean,
val body: Boolean
) {
/** Log everything: request/response info, headers, and body content */
ALL(true, true, true),
/** Log request/response info and headers, but not body content */
HEADERS(true, true, false),
/** Log request/response info and body content, but not headers */
BODY(true, false, true),
/** Log only basic request/response information */
INFO(true, false, false),
/** Disable all logging */
NONE(false, false, false)
}Core logging abstraction with platform-specific implementations.
/**
* HttpClient Logger interface.
*/
interface Logger {
/** Add message to log */
fun log(message: String)
companion object
}/**
* Default logger to use (platform-specific implementation).
*/
val Logger.Companion.DEFAULT: Logger
/**
* Logger using println for simple console output.
*/
val Logger.Companion.SIMPLE: Logger
/**
* Empty Logger for test purposes - logs nothing.
*/
val Logger.Companion.EMPTY: Logger/**
* Message Length Limiting Logger: Breaks up log messages into multiple logs no longer than maxLength.
* Useful for platforms with log message length limitations.
*/
class MessageLengthLimitingLogger(
private val maxLength: Int = 4000,
private val minLength: Int = 3000,
private val delegate: Logger = Logger.DEFAULT
) : Logger {
override fun log(message: String)
}/**
* HTTP request builder type for filtering predicates.
*/
typealias HttpRequestBuilder = io.ktor.client.request.HttpRequestBuilderimport io.ktor.client.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
val client = HttpClient {
install(Logging) {
level = LogLevel.INFO
}
}
// This will log basic request/response information
val response = client.get("https://httpbin.org/get")val client = HttpClient {
install(Logging) {
level = LogLevel.ALL
logger = Logger.SIMPLE
}
}
// This will log complete request/response including headers and body
val response = client.post("https://httpbin.org/post") {
setBody("Request body content")
}val client = HttpClient {
install(Logging) {
level = LogLevel.HEADERS
logger = Logger.DEFAULT
// Only log requests to specific domains
filter { request ->
request.url.host.endsWith("example.com")
}
// Sanitize authorization headers
sanitizeHeader("***") { headerName ->
headerName.equals("Authorization", ignoreCase = true)
}
// Sanitize multiple header types
sanitizeHeader("[REDACTED]") { headerName ->
headerName in listOf("API-Key", "X-Auth-Token", "Cookie")
}
}
}// On Native platforms, use simple console logging
val client = HttpClient {
install(Logging) {
level = LogLevel.HEADERS
logger = Logger.SIMPLE // Console logging for Native platforms
}
}class CustomLogger : Logger {
override fun log(message: String) {
// Custom logging logic - could write to file, send to analytics, etc.
println("[CUSTOM] $message")
}
}
val client = HttpClient {
install(Logging) {
level = LogLevel.ALL
logger = CustomLogger()
}
}val client = HttpClient {
install(Logging) {
level = LogLevel.HEADERS
// Log only successful responses
filter { request ->
// This will be evaluated for each request
request.url.host.contains("api")
}
// Add multiple filters
filter { request ->
request.method.value == "POST"
}
}
}The Logging plugin handles errors gracefully: