CtrlK
BlogDocsLog inGet started
Tessl Logo

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

HTTP client logging plugin for Ktor client framework with configurable logging formats, levels, and platform-specific logger integrations

Pending
Overview
Eval results
Files

platform-features.mddocs/

Platform-Specific Features

The Ktor Client Logging plugin provides platform-optimized implementations and features tailored to different runtime environments.

Required Imports

import io.ktor.client.*
import io.ktor.client.plugins.logging.*
import kotlinx.coroutines.*
import org.slf4j.MDC // JVM only
import kotlin.coroutines.CoroutineContext

JVM Platform Features

SLF4J Integration

The JVM implementation seamlessly integrates with SLF4J, the standard logging facade for Java applications.

val Logger.Companion.DEFAULT: Logger

JVM Implementation Details:

  • Uses LoggerFactory.getLogger(HttpClient::class.java)
  • Logs at INFO level through SLF4J
  • Respects your SLF4J configurations (logback.xml, log4j2.xml, etc.)
  • Thread-safe for concurrent HTTP clients

Configuration Example:

// Inherits your SLF4J configuration
Logging {
    logger = Logger.DEFAULT  // Uses SLF4J
    level = LogLevel.ALL
}

Android Logcat Support

Special Android-optimized logger with Logcat integration and automatic message chunking.

val Logger.Companion.ANDROID: Logger

Features:

  • Automatic Logcat Detection: Uses android.util.Log when available
  • SLF4J Fallback: Falls back to SLF4J if Logcat is unavailable
  • Message Length Limiting: Breaks long messages to fit Android's log constraints
  • Tag Management: Uses "Ktor Client" as the log tag
  • Lazy Initialization: Created on first access for optimal performance

Android-Specific Behavior:

  • Maximum message length: 4000 characters
  • Prefers newline breaks between 3000-4000 characters
  • Graceful fallback if android.util.Log class not found
  • Thread-safe for Android's multi-threaded environment

Usage in Android Projects:

val client = HttpClient {
    install(Logging) {
        logger = Logger.ANDROID
        level = LogLevel.HEADERS
    }
}

MDC Context Propagation

Maintain Mapped Diagnostic Context (MDC) across coroutine boundaries for enhanced logging correlation.

// JVM Platform
actual fun MDCContext(): CoroutineContext.Element

// JavaScript/WASM Platform  
actual fun MDCContext(): CoroutineContext.Element

// Native/Posix Platform
actual fun MDCContext(): CoroutineContext.Element

Purpose:

  • Preserves SLF4J MDC context in coroutine-based HTTP operations
  • Enables request correlation across async operations
  • Supports structured logging and distributed tracing

Usage with Coroutines:

// Set up MDC context
MDC.put("requestId", "req-123")
MDC.put("userId", "user-456")

// Create client with MDC context preservation
val client = HttpClient {
    install(Logging) {
        logger = Logger.DEFAULT  // Will include MDC context
        level = LogLevel.INFO
    }
}

// MDC context is automatically propagated through coroutines
runBlocking(MDCContext()) {
    val response = client.get("https://api.example.com/data")
    // Logs will include requestId and userId from MDC
}

Integration with Structured Logging:

// Example with logback-structured-config
MDC.put("traceId", UUID.randomUUID().toString())
MDC.put("operation", "user-creation")

val client = HttpClient {
    install(Logging) {
        logger = Logger.DEFAULT
        level = LogLevel.ALL
        filter { request ->
            request.url.pathSegments.contains("users")
        }
    }
}

withContext(MDCContext()) {
    // All HTTP logs will include traceId and operation
    client.post("https://api.example.com/users") {
        contentType(ContentType.Application.Json)
        setBody(userCreateRequest)
    }
}

JavaScript/WASM Platform Features

Console Integration

val Logger.Companion.DEFAULT: Logger  // Points to Logger.SIMPLE

Features:

  • Uses browser console or Node.js console
  • Simple console.log implementation
  • No additional dependencies
  • Works in both browser and Node.js environments

Browser Example:

val client = HttpClient {
    install(Logging) {
        logger = Logger.DEFAULT  // Uses console
        level = LogLevel.INFO
    }
}

Native/Posix Platform Features

Standard Output Integration

val Logger.Companion.DEFAULT: Logger  // Points to Logger.SIMPLE

Features:

  • Uses platform's standard output
  • Minimal overhead implementation
  • Compatible with native compilation
  • Works across all supported native targets

Platform-Specific Logger Selection

Automatic Platform Detection

The Logger.DEFAULT implementation automatically selects the most appropriate logging mechanism for each platform:

// Same code works across all platforms
val client = HttpClient {
    install(Logging) {
        logger = Logger.DEFAULT
        level = LogLevel.HEADERS
    }
}

Platform Mappings:

  • JVM: SLF4J-based logger with HttpClient class logger
  • Android: Same as JVM (use Logger.ANDROID for Logcat)
  • JavaScript: Browser console or Node.js console
  • WASM: Browser console
  • Native: Platform standard output

Platform-Specific Optimizations

JVM Optimizations

val client = HttpClient {
    install(Logging) {
        // Leverage SLF4J configuration
        logger = Logger.DEFAULT
        
        // Use Android-specific features if needed
        logger = Logger.ANDROID
        
        // Or customize with message limiting
        logger = MessageLengthLimitingLogger(
            maxLength = 8000,  // Higher limit for JVM
            delegate = Logger.DEFAULT
        )
        
        level = LogLevel.ALL
    }
}

Mobile/Android Optimizations

val client = HttpClient {
    install(Logging) {
        // Optimized for Android Logcat
        logger = Logger.ANDROID
        
        // Conservative logging to preserve performance/battery
        level = LogLevel.INFO
        format = LoggingFormat.OkHttp  // More compact
        
        // Filter to reduce log volume
        filter { request ->
            !request.url.host.contains("analytics") &&
            !request.url.pathSegments.contains("ping")
        }
    }
}

Web/JavaScript Optimizations

val client = HttpClient {
    install(Logging) {
        logger = Logger.DEFAULT  // Console logging
        
        // Minimal logging for production builds
        level = when (js("process.env.NODE_ENV")) {
            "production" -> LogLevel.NONE
            "development" -> LogLevel.ALL
            else -> LogLevel.INFO
        }
    }
}

Cross-Platform Compatibility

Unified API

All platform-specific features maintain the same API surface:

// This code works identically across all platforms
class ApiClient {
    private val client = HttpClient {
        install(Logging) {
            logger = Logger.DEFAULT  // Platform-appropriate implementation
            level = LogLevel.HEADERS
            format = LoggingFormat.OkHttp
            
            filter { request -> 
                request.url.host == "api.myapp.com" 
            }
            
            sanitizeHeader { headerName ->
                headerName.equals("Authorization", ignoreCase = true)
            }
        }
    }
    
    suspend fun fetchUser(id: String): User {
        return client.get("https://api.myapp.com/users/$id").body()
    }
}

Platform Detection Example

val platformOptimizedClient = HttpClient {
    install(Logging) {
        // Platform-specific logger selection
        logger = when (Platform.Current) {
            is JvmPlatform -> if (isAndroid()) Logger.ANDROID else Logger.DEFAULT
            is JsPlatform -> Logger.SIMPLE
            is NativePlatform -> Logger.SIMPLE
        }
        
        // Platform-appropriate log levels
        level = when (Platform.Current) {
            is JvmPlatform -> LogLevel.ALL  // JVM can handle verbose logging
            else -> LogLevel.INFO           // Mobile/web prefer less verbose
        }
        
        format = LoggingFormat.OkHttp  // Compact format for all platforms
    }
}

Performance Considerations

JVM Platform

  • SLF4J Overhead: Minimal, delegates to configured logging framework
  • MDC Context: Small overhead for context propagation
  • Message Limiting: Optional, use only when needed

Mobile Platforms

  • Battery Impact: Use conservative log levels in production
  • Memory Usage: Avoid LogLevel.ALL with large payloads
  • Performance: Filter requests to reduce logging overhead

Web Platforms

  • Bundle Size: Logging adds minimal size overhead
  • Network Performance: Consider filtering frequent requests
  • Development vs Production: Use conditional logging levels

Install with Tessl CLI

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

docs

advanced-config.md

configuration.md

index.md

levels-formats.md

loggers.md

platform-features.md

tile.json