Ktor HTTP client logging plugin for macOS x64 platform with configurable log levels and output formats
npx @tessl/cli install tessl/maven-io-ktor--ktor-client-logging-macosx64@3.2.0Ktor Client Logging is a plugin for the Ktor HTTP client that provides comprehensive logging capabilities for HTTP requests and responses. It offers configurable log levels, multiple output formats, header sanitization for security, and custom logger implementations with full coroutine safety.
implementation("io.ktor:ktor-client-logging:3.2.0")import io.ktor.client.plugins.logging.*
import io.ktor.client.*
import io.ktor.client.request.* // For HttpRequestBuilder (used in filters)
import io.ktor.http.* // For HttpMethod, ContentType (used in examples)import io.ktor.client.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
// Basic logging setup
val client = HttpClient {
install(Logging) {
level = LogLevel.ALL
logger = Logger.SIMPLE
}
}
// Make a request - will be automatically logged
val response = client.get("https://api.example.com/users")
client.close()The Ktor Client Logging plugin integrates seamlessly with Ktor's client plugin architecture:
install() mechanism with configuration DSLInstall and configure the logging plugin in your HTTP client.
fun HttpClientConfig<*>.Logging(block: LoggingConfig.() -> Unit = {})
val Logging: ClientPlugin<LoggingConfig>Usage Example:
val client = HttpClient {
install(Logging) {
level = LogLevel.HEADERS
logger = Logger.DEFAULT
format = LoggingFormat.Default
// Filter specific requests
filter { request ->
request.url.host == "api.example.com"
}
// Sanitize sensitive headers
sanitizeHeader { header ->
header == "Authorization"
}
}
}Configure logging behavior through the LoggingConfig class.
@KtorDsl
class LoggingConfig {
var format: LoggingFormat
var logger: Logger
var level: LogLevel
fun filter(predicate: (HttpRequestBuilder) -> Boolean)
fun sanitizeHeader(placeholder: String = "***", predicate: (String) -> Boolean)
}Control the amount of information logged with different log levels.
enum class LogLevel(
val info: Boolean,
val headers: Boolean,
val body: Boolean
) {
ALL(true, true, true),
HEADERS(true, true, false),
BODY(true, false, true),
INFO(true, false, false),
NONE(false, false, false)
}Usage Example:
install(Logging) {
level = LogLevel.ALL // Log everything
// level = LogLevel.HEADERS // Log info and headers only
// level = LogLevel.INFO // Log basic info only
// level = LogLevel.NONE // Disable logging
}Choose between different output formats for logged information.
enum class LoggingFormat {
Default,
OkHttp
}Usage Example:
install(Logging) {
format = LoggingFormat.Default // Standard Ktor format
// format = LoggingFormat.OkHttp // OkHttp-compatible format
}Implement custom logging behavior through the Logger interface.
interface Logger {
fun log(message: String)
companion object
}Platform-specific logger implementations for different environments.
// Common loggers available on all platforms
val Logger.Companion.SIMPLE: Logger
val Logger.Companion.EMPTY: Logger
// Platform-specific default logger
expect val Logger.Companion.DEFAULT: LoggerFor macOS (Native/POSIX platforms):
actual val Logger.Companion.DEFAULT: Logger // Uses SIMPLE loggerNote: Logger.DEFAULT uses Kotlin Multiplatform's expect/actual mechanism to provide platform-specific implementations. On macOS x64 (and other POSIX platforms), it delegates to Logger.SIMPLE which outputs to standard output. This is different from JVM platforms which may use more sophisticated logging frameworks.
Usage Examples:
install(Logging) {
logger = Logger.SIMPLE // Prints to stdout with "HttpClient:" prefix
// logger = Logger.DEFAULT // Platform-specific logger
// logger = Logger.EMPTY // No-op logger for testing
// Custom logger
logger = object : Logger {
override fun log(message: String) {
println("Custom: $message")
}
}
}Filter which requests should be logged based on custom criteria.
fun LoggingConfig.filter(predicate: (HttpRequestBuilder) -> Boolean)Usage Example:
install(Logging) {
// Only log requests to specific domains
filter { request ->
request.url.host.contains("api.example.com")
}
// Only log POST requests
filter { request ->
request.method == HttpMethod.Post
}
// Multiple filters (all must pass)
filter { request -> request.url.protocol.isSecure() }
filter { request -> !request.url.pathSegments.contains("health") }
}Sanitize sensitive header values to prevent exposure in logs.
fun LoggingConfig.sanitizeHeader(
placeholder: String = "***",
predicate: (String) -> Boolean
)Note: When using LoggingFormat.OkHttp, the plugin internally uses "██" as the default placeholder regardless of the configured placeholder value.
Usage Example:
install(Logging) {
// Sanitize Authorization headers
sanitizeHeader { header ->
header.equals("Authorization", ignoreCase = true)
}
// Sanitize multiple headers with custom placeholder
sanitizeHeader("████") { header ->
header in listOf("Authorization", "X-API-Key", "Cookie")
}
// Sanitize based on header patterns
sanitizeHeader { header ->
header.contains("token", ignoreCase = true) ||
header.contains("secret", ignoreCase = true)
}
}The logging plugin is designed to be resilient and will not throw exceptions that interrupt HTTP requests:
Common Patterns:
install(Logging) {
level = LogLevel.ALL
// The plugin will automatically:
// - Detect binary vs text content
// - Handle streaming responses
// - Sanitize specified headers
// - Log request/response exceptions
// - Preserve original request/response data
}