CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-client-logging

Logging plugin for Ktor HTTP client that provides comprehensive request and response logging capabilities with configurable loggers, levels, and sanitization for sensitive data

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration

Comprehensive configuration options for the Ktor Client Logging plugin, including logging levels, output formats, filtering, and header sanitization.

Capabilities

Plugin Installation

Install and configure the logging plugin in your HttpClient.

/**
 * A client's plugin that provides the capability to log HTTP calls
 */
val Logging: ClientPlugin<LoggingConfig>

/**
 * Configures and installs Logging in HttpClient
 * @param block Configuration lambda for LoggingConfig
 */
fun HttpClientConfig<*>.Logging(block: LoggingConfig.() -> Unit = {})

Usage Examples:

import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.logging.*

// Basic installation
val client = HttpClient(CIO) {
    install(Logging)
}

// With configuration
val client = HttpClient(CIO) { 
    install(Logging) {
        level = LogLevel.ALL
        logger = Logger.SIMPLE
        format = LoggingFormat.OkHttp
    }
}

// Alternative syntax
val client = HttpClient(CIO) {
    Logging {
        level = LogLevel.HEADERS
    }
}

Configuration Class

The main configuration class providing DSL-style configuration options.

/**
 * A configuration for the Logging plugin
 */
@KtorDsl
class LoggingConfig {
    /**
     * A general format for logging requests and responses
     */
    var format: LoggingFormat
    
    /**
     * 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
     * @param predicate Function that receives HttpRequestBuilder and returns Boolean
     */
    fun filter(predicate: (HttpRequestBuilder) -> Boolean)
    
    /**
     * Allows you to sanitize sensitive headers to avoid their values appearing in the logs
     * @param placeholder String to replace sensitive header values (default: "***")
     * @param predicate Function that receives header name and returns Boolean
     */
    fun sanitizeHeader(placeholder: String = "***", predicate: (String) -> Boolean)
}

/**
 * Internal data class for header sanitization configuration
 */
internal class SanitizedHeader(
    val placeholder: String,
    val predicate: (String) -> Boolean
)

Logging Levels

Control the amount of information logged for each request/response.

/**
 * Logging log level
 * @param info Whether to log basic request/response info
 * @param headers Whether to log headers
 * @param body Whether to log request/response body
 */
enum class LogLevel(
    val info: Boolean,
    val headers: Boolean,
    val body: Boolean
) {
    /** Log everything: request info, headers, and body */
    ALL(true, true, true),
    /** Log request info and headers, but not body */
    HEADERS(true, true, false),
    /** Log request info and body, but not headers */
    BODY(true, false, true),
    /** Log only basic request info */
    INFO(true, false, false),
    /** Disable logging */
    NONE(false, false, false)
}

Usage Examples:

install(Logging) {
    level = LogLevel.ALL       // Log everything
    level = LogLevel.HEADERS   // Log info + headers (default)
    level = LogLevel.BODY      // Log info + body
    level = LogLevel.INFO      // Log basic info only
    level = LogLevel.NONE      // No logging
}

Logging Formats

Choose between different output formats for logged information.

/**
 * General format for logging requests and responses
 */
enum class LoggingFormat {
    /** Standard Ktor logging format */
    Default,
    
    /**
     * OkHttp logging format
     * Writes only application-level logs because the low-level HTTP communication 
     * is hidden within the engine implementations
     */
    OkHttp
}

Usage Examples:

install(Logging) {
    format = LoggingFormat.Default  // Standard Ktor format
    format = LoggingFormat.OkHttp   // OkHttp-compatible format
}

Request Filtering

Filter which requests should be logged based on custom criteria.

/**
 * Add a filter predicate to control which requests are logged
 * @param predicate Function receiving HttpRequestBuilder, returns true to log
 */
fun LoggingConfig.filter(predicate: (HttpRequestBuilder) -> Boolean)

Usage Examples:

import io.ktor.client.request.*
import io.ktor.http.*

install(Logging) {
    // Only log requests to specific host
    filter { request ->
        request.url.host == "api.example.com"
    }
    
    // Only log POST requests
    filter { request ->
        request.method == HttpMethod.Post
    }
    
    // Only log requests with specific header
    filter { request ->
        request.headers.contains("X-Debug")
    }
    
    // Combine multiple filters (all must return true)
    filter { request -> request.url.host == "api.example.com" }
    filter { request -> request.method == HttpMethod.Post }
}

Header Sanitization

Protect sensitive header values from appearing in logs.

/**
 * Sanitize sensitive headers to avoid their values appearing in the logs
 * @param placeholder String to replace sensitive values with (default: "***")
 * @param predicate Function receiving header name, returns true to sanitize
 */
fun LoggingConfig.sanitizeHeader(placeholder: String = "***", predicate: (String) -> Boolean)

Usage Examples:

import io.ktor.http.*

install(Logging) {
    // Sanitize Authorization header with default placeholder
    sanitizeHeader { header -> 
        header == HttpHeaders.Authorization 
    }
    
    // Sanitize multiple headers with custom placeholder
    sanitizeHeader("██") { header ->
        header == "X-API-Key" || header == "X-Secret-Token"
    }
    
    // Sanitize headers by pattern
    sanitizeHeader("[REDACTED]") { header ->
        header.lowercase().contains("auth") || 
        header.lowercase().contains("key") ||
        header.lowercase().contains("token")
    }
    
    // Multiple sanitization rules
    sanitizeHeader("***") { it == HttpHeaders.Authorization }
    sanitizeHeader("██") { it.startsWith("X-Secret-") }
}

Advanced Configuration Examples

Production Configuration

val client = HttpClient(CIO) {
    install(Logging) {
        level = LogLevel.INFO  // Basic info only in production
        logger = Logger.DEFAULT  // Use SLF4J/platform logger
        
        // Only log failed requests
        filter { request ->
            // This would require additional logic to detect failures
            true
        }
        
        // Sanitize all sensitive headers
        sanitizeHeader { header ->
            val sensitiveHeaders = setOf(
                "Authorization", "X-API-Key", "X-Auth-Token",
                "Cookie", "Set-Cookie", "X-Secret"
            )
            header in sensitiveHeaders
        }
    }
}

Development Configuration

val client = HttpClient(CIO) {
    install(Logging) {
        level = LogLevel.ALL  // Log everything for debugging
        logger = Logger.SIMPLE  // Console output
        format = LoggingFormat.OkHttp  // Readable format
        
        // Log only API calls (skip assets)
        filter { request ->
            !request.url.pathSegments.any { it.contains('.') }
        }
    }
}

Testing Configuration

val client = HttpClient(CIO) {
    install(Logging) {
        level = LogLevel.HEADERS  // Good balance for test visibility
        logger = Logger.EMPTY  // No output during tests
        
        // Only log specific test scenarios
        filter { request ->
            request.headers.contains("X-Test-Scenario")
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-client-logging

docs

configuration.md

index.md

loggers.md

utilities.md

tile.json