or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

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

Ktor HTTP client logging plugin for JavaScript targets providing comprehensive request/response logging capabilities with configurable levels, formats, and header sanitization

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/io.ktor/ktor-client-logging-js@3.2.x

To install, run

npx @tessl/cli install tessl/maven-io-ktor--ktor-client-logging-js@3.2.0

index.mddocs/

Ktor Client Logging Plugin

Ktor Client Logging Plugin provides comprehensive HTTP request and response logging capabilities for Ktor HTTP client applications targeting JavaScript environments. It offers configurable logging levels, multiple output formats, header sanitization, and platform-specific logger implementations optimized for browser and Node.js environments.

Package Information

  • Package Name: ktor-client-logging-js
  • Package Type: maven
  • Language: Kotlin (JavaScript targets)
  • Installation: implementation("io.ktor:ktor-client-logging-js:3.2.0")

Core Imports

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

For HttpClient configuration:

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

Basic Usage

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

// Basic setup with default configuration
val client = HttpClient {
    install(Logging)
}

// Configured setup
val client = HttpClient {
    install(Logging) {
        level = LogLevel.ALL
        logger = Logger.SIMPLE
    }
}

// Advanced configuration
val client = HttpClient {
    install(Logging) {
        level = LogLevel.HEADERS
        format = LoggingFormat.OkHttp
        logger = Logger.DEFAULT
        
        // Filter requests
        filter { request ->
            request.url.host == "api.example.com"
        }
        
        // Sanitize sensitive headers
        sanitizeHeader { header ->
            header == "Authorization"
        }
    }
}

Capabilities

Plugin Installation and Configuration

Install and configure the logging plugin for HTTP clients.

/**
 * Main logging plugin that provides HTTP call logging capabilities
 */
val Logging: ClientPlugin<LoggingConfig>

/**
 * Convenience function to configure and install the Logging plugin
 */
fun HttpClientConfig<*>.Logging(block: LoggingConfig.() -> Unit = {})

/**
 * Configuration for the Logging plugin
 */
@KtorDsl
class LoggingConfig {
    /** General format for logging requests and responses */
    var format: LoggingFormat
    
    /** Logger instance for output */
    var logger: Logger
    
    /** Logging level controlling what gets logged */
    var level: LogLevel
    
    /** Add a filter predicate for conditional logging */
    fun filter(predicate: (HttpRequestBuilder) -> Boolean)
    
    /** Sanitize sensitive headers to avoid values appearing in logs */
    fun sanitizeHeader(placeholder: String = "***", predicate: (String) -> Boolean)
}

Log Levels

Control the amount of information logged for HTTP requests and responses.

/**
 * Logging level enumeration with boolean properties
 */
enum class LogLevel(
    val info: Boolean,
    val headers: Boolean, 
    val body: Boolean
) {
    /** Log everything: info, headers, and body */
    ALL(true, true, true),
    
    /** Log info and headers, but not body */
    HEADERS(true, true, false),
    
    /** Log info and body, but not headers */
    BODY(true, false, true),
    
    /** Log only basic request/response info */
    INFO(true, false, false),
    
    /** No logging */
    NONE(false, false, false)
}

Logging Formats

Choose between different output formats for logged messages.

/**
 * Output format for logged messages
 */
enum class LoggingFormat {
    /** Standard Ktor logging format */
    Default,
    
    /** 
     * OkHttp-compatible logging format for application-level logs
     * Writes only application-level logs because low-level HTTP communication 
     * is hidden within engine implementations
     */
    OkHttp
}

Logger Interface and Implementations

Core logging interface and built-in implementations for different environments.

/**
 * Core logging interface for HTTP client
 */
interface Logger {
    /** Add message to log */
    fun log(message: String)
    
    companion object
}

/** Default logger for JS/WASM platforms (delegates to SIMPLE) */
val Logger.Companion.DEFAULT: Logger

/** Simple logger using println with "HttpClient:" prefix */
val Logger.Companion.SIMPLE: Logger

/** Empty logger for testing (no-op implementation) */
val Logger.Companion.EMPTY: Logger

Usage Examples:

// Using default logger
val client = HttpClient {
    install(Logging) {
        logger = Logger.DEFAULT
    }
}

// Using simple console logger
val client = HttpClient {
    install(Logging) {
        logger = Logger.SIMPLE
    }
}

// Using empty logger for tests
val client = HttpClient {
    install(Logging) {
        logger = Logger.EMPTY
    }
}

// Custom logger implementation
val customLogger = object : Logger {
    override fun log(message: String) {
        console.log("MyApp HTTP: $message")
    }
}

val client = HttpClient {
    install(Logging) {
        logger = customLogger
    }
}

Request and Response Filtering

Control which HTTP calls get logged using predicate functions.

/**
 * Add a filter predicate for conditional logging
 * @param predicate Function that returns true if the request should be logged
 */
fun LoggingConfig.filter(predicate: (HttpRequestBuilder) -> Boolean)

Usage Examples:

val client = HttpClient {
    install(Logging) {
        // Only log API calls
        filter { request ->
            request.url.host.contains("api")
        }
        
        // 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") }
    }
}

Header Sanitization

Sanitize sensitive headers to prevent their values from appearing in logs.

/**
 * Sanitize sensitive headers to avoid their values appearing in the logs
 * @param placeholder Replacement text for sanitized values (default: "***")
 * @param predicate Function that returns true if the header should be sanitized
 */
fun LoggingConfig.sanitizeHeader(placeholder: String = "***", predicate: (String) -> Boolean)

Usage Examples:

val client = HttpClient {
    install(Logging) {
        level = LogLevel.HEADERS
        
        // Sanitize Authorization header with default placeholder
        sanitizeHeader { header ->
            header == "Authorization"
        }
        
        // Sanitize multiple headers with custom placeholder
        sanitizeHeader("█████") { header ->
            header in listOf("Authorization", "X-API-Key", "Cookie")
        }
        
        // Case-insensitive sanitization
        sanitizeHeader { header ->
            header.lowercase() == "authorization"
        }
    }
}

Types

/**
 * HTTP request builder used in filter predicates
 */
class HttpRequestBuilder {
    val url: URLBuilder
    val method: HttpMethod
    val headers: HeadersBuilder
    val body: Any
    val attributes: Attributes
}

/**
 * HTTP method enumeration
 */
class HttpMethod {
    companion object {
        val Get: HttpMethod
        val Post: HttpMethod
        val Put: HttpMethod
        val Delete: HttpMethod
        val Head: HttpMethod
        val Options: HttpMethod
        val Patch: HttpMethod
    }
}

/**
 * URL builder for constructing and examining URLs
 */
class URLBuilder {
    val protocol: URLProtocol
    var host: String
    var port: Int
    val pathSegments: List<String>
    val parameters: ParametersBuilder
}

/**
 * Headers builder for HTTP headers
 */
class HeadersBuilder {
    fun append(name: String, value: String)
    fun contains(name: String): Boolean
    operator fun get(name: String): String?
}

/**
 * URL protocol with name and default port
 */
data class URLProtocol(val name: String, val defaultPort: Int) {
    companion object {
        val HTTP: URLProtocol
        val HTTPS: URLProtocol
        val WS: URLProtocol  
        val WSS: URLProtocol
    }
}

/**
 * Check if the protocol is secure (HTTPS or WSS)
 */
fun URLProtocol.isSecure(): Boolean

/**
 * Parameters builder for URL parameters
 */
class ParametersBuilder {
    fun append(name: String, value: String)
    fun contains(name: String): Boolean
    operator fun get(name: String): String?
}

/**
 * Attributes container for request metadata
 */
class Attributes {
    fun <T : Any> put(key: AttributeKey<T>, value: T)
    operator fun <T : Any> get(key: AttributeKey<T>): T
    fun <T : Any> contains(key: AttributeKey<T>): Boolean
}

/**
 * Attribute key for type-safe attribute access
 */
class AttributeKey<T : Any>(val name: String)

Platform-Specific Features

JavaScript Environment Integration

The JavaScript version of the logging plugin provides optimized integration with browser and Node.js environments:

  • Browser Console: Logger.DEFAULT and Logger.SIMPLE output to browser console
  • Node.js Compatibility: Works seamlessly with Node.js logging mechanisms
  • Async/Await Support: Full integration with JavaScript async/await patterns
  • WebAssembly Support: Shared implementation works with both JS and WASM targets

Error Handling

The plugin gracefully handles various error conditions:

  • Malformed Content: Binary content detection prevents encoding errors
  • Network Failures: Exception logging for failed requests/responses
  • Coroutine Safety: Thread-safe logging operations in concurrent environments
  • Content Encoding: Automatic handling of gzip and other encodings

Content Processing

Advanced content handling capabilities:

  • Binary Detection: Automatically detects and handles binary content
  • Charset Support: Proper text encoding/decoding with charset detection
  • Streaming Content: Efficient logging of streaming responses
  • Content Length: Accurate size reporting for various content types

Common Usage Patterns

Development Setup

val client = HttpClient {
    install(Logging) {
        level = LogLevel.ALL
        logger = Logger.SIMPLE
    }
}

Production Setup

val client = HttpClient {
    install(Logging) {
        level = LogLevel.INFO
        logger = Logger.DEFAULT
        
        // Only log errors and important requests
        filter { request ->
            request.url.pathSegments.none { it == "health" }
        }
        
        // Sanitize all sensitive headers
        sanitizeHeader { header ->
            header.lowercase() in listOf("authorization", "x-api-key", "cookie")
        }
    }
}

OkHttp-Compatible Logging

val client = HttpClient {
    install(Logging) {
        level = LogLevel.BODY
        format = LoggingFormat.OkHttp
        logger = Logger.DEFAULT
    }
}

Testing Setup

val client = HttpClient {
    install(Logging) {
        logger = Logger.EMPTY  // No output during tests
    }
}