Klogging

Standalone logging library built in pure Kotlin. Supports structured log events by default through deep integration with Kotlin coroutines. Provides asynchronous event dispatching and automatic context information capture.

Logging LibraryKotlinCoroutinesStructured LoggingAsynchronousKotlin Native

Library

Klogging

Overview

Klogging is a standalone logging library built in pure Kotlin, providing "easy and powerful logging with Kotlin idioms" and addressing modern Kotlin development needs through deep integration with Kotlin coroutines. Supporting structured log events by default, it enables high-performance log management in environments where microservices and asynchronous processing are important through asynchronous event dispatching and automatic context information capture. It's a Kotlin-first logging solution that transcends traditional Java logging frameworks.

Details

Klogging is a next-generation logging library gaining attention in coroutine-based Kotlin applications in 2025. Equipped with features addressing modern distributed system requirements including information storage in coroutine scopes and automatic context management, microsecond-level high-precision timestamps, and JDK platform logging implementation. With excellent Spring Boot integration, it significantly improves structured logging and traceability in server-side Kotlin development, positioning itself as an important complement and evolution of traditional SLF4J+Logback approaches.

Key Features

  • Coroutine Native: Deep integration with Kotlin coroutines and automatic context management
  • Structured Logging by Default: Automatic structured event generation through message templates
  • Asynchronous Event Dispatching: High-performance asynchronous log processing functionality
  • High-Precision Timestamps: Precise time recording from microsecond to nanosecond level
  • Kotlin First: Optimized API design through pure Kotlin implementation
  • Spring Boot Integration: Integration functionality supporting enterprise-level adoption

Pros and Cons

Pros

  • Context management automated through integration with Kotlin coroutines
  • Structured logging by default adapts to modern log analysis and monitoring environments
  • Performance improvement in high-load environments through asynchronous processing
  • Natural API fully compliant with Kotlin idioms through pure Kotlin implementation
  • Advantages in traceability and distributed log management for microservice environments
  • Enterprise-level development adoption ease through Spring Boot integration

Cons

  • Specialized in Kotlin ecosystem with limited compatibility with other languages
  • Relatively new library with smaller maturity and community size compared to SLF4J
  • No API compatibility with traditional Java logging, creating learning costs during migration
  • Possibility of over-engineering in small-scale projects due to many advanced features
  • Less debugging and troubleshooting information available compared to traditional libraries
  • High adoption hurdles in conservative organizations due to limited enterprise track record

Reference Pages

Usage Examples

Installation and Basic Setup

// build.gradle.kts
dependencies {
    implementation("io.klogging:klogging-jvm:0.10.1")
    // For Spring Boot integration
    implementation("io.klogging:slf4j-klogging:0.10.1")
}
<!-- Maven pom.xml -->
<dependency>
    <groupId>io.klogging</groupId>
    <artifactId>klogging-jvm</artifactId>
    <version>0.10.1</version>
</dependency>
import io.klogging.Klogging
import io.klogging.NoCoLogging
import io.klogging.config.loggingConfiguration
import kotlinx.coroutines.*

// Basic Klogging configuration
fun main() = runBlocking {
    // Console output configuration
    loggingConfiguration {
        ANSI_CONSOLE()
    }
    
    // Simple log output test
    val logger = NoCoLogging.logger()
    logger.info { "Klogging initialized successfully" }
    
    // Logging in coroutine environment
    launch {
        val coLogger = Klogging.logger()
        coLogger.info { "Coroutine-based logging ready" }
    }
}

// Advanced configuration example
fun setupAdvancedKlogging() {
    loggingConfiguration {
        // Multiple output destination configuration
        sink("console", ANSI_CONSOLE())
        sink("file", FILE("logs/app.log"))
        sink("json", FILE("logs/app.json", JSON_FORMAT))
        
        // Log level configuration
        minLevel(Level.INFO)
        
        // Structured logging configuration
        logger("com.example.service") {
            minLevel(Level.DEBUG)
            stopOnMatch = true
        }
        
        // Asynchronous dispatch configuration
        asyncDispatcher {
            bufferSize = 1000
            dropOnOverflow = false
        }
    }
}

Coroutine Integration (Basic Usage)

import io.klogging.Klogging
import io.klogging.NoCoLogging
import io.klogging.events.logContext
import kotlinx.coroutines.*

// Coroutine-integrated logging class
class UserService : Klogging {
    
    suspend fun processUser(userId: String, userData: UserData) = coroutineScope {
        // Add log information to coroutine context
        launch(logContext("userId" to userId, "operation" to "processUser")) {
            logger.info { "Starting user processing" }
            
            try {
                // User data validation
                validateUserData(userData)
                logger.debug { "User data validation completed" }
                
                // Database save
                saveUserToDatabase(userData)
                logger.info { "User data saved successfully" }
                
                // External API notification
                notifyExternalSystems(userId)
                logger.info { "External systems notified" }
                
            } catch (e: Exception) {
                logger.error(e) { "User processing failed" }
                throw e
            }
        }
    }
    
    private suspend fun validateUserData(userData: UserData) {
        logger.debug { "Validating user data: ${userData.email}" }
        
        if (userData.email.isBlank()) {
            logger.warn { "Invalid email address provided" }
            throw IllegalArgumentException("Email is required")
        }
        
        if (userData.age < 0 || userData.age > 150) {
            logger.warn { "Invalid age: ${userData.age}" }
            throw IllegalArgumentException("Invalid age range")
        }
    }
    
    private suspend fun saveUserToDatabase(userData: UserData) {
        logger.debug { "Saving to database" }
        delay(100) // Database operation simulation
        logger.info { "Database save completed" }
    }
    
    private suspend fun notifyExternalSystems(userId: String) {
        logger.debug { "Notifying external systems" }
        delay(50) // API call simulation
        logger.info { "External notification completed" }
    }
}

// Usage in non-coroutine environment
class ConfigurationManager : NoCoLogging {
    
    fun loadConfiguration(configPath: String): Configuration {
        logger.info { "Loading configuration from: $configPath" }
        
        return try {
            val config = parseConfigFile(configPath)
            logger.info { "Configuration loaded successfully. Entries: ${config.entries.size}" }
            config
        } catch (e: Exception) {
            logger.error(e) { "Failed to load configuration" }
            throw ConfigurationException("Configuration loading failed", e)
        }
    }
    
    private fun parseConfigFile(path: String): Configuration {
        logger.debug { "Parsing configuration file" }
        // File parsing processing
        return Configuration()
    }
}

// Data classes
data class UserData(
    val email: String,
    val name: String,
    val age: Int
)

data class Configuration(
    val entries: Map<String, String> = emptyMap()
)

class ConfigurationException(message: String, cause: Throwable) : Exception(message, cause)

// Usage example
suspend fun main() {
    loggingConfiguration {
        ANSI_CONSOLE()
    }
    
    val userService = UserService()
    val configManager = ConfigurationManager()
    
    // Coroutine-based processing
    val userData = UserData("[email protected]", "John Doe", 30)
    userService.processUser("user123", userData)
    
    // Non-coroutine processing
    val config = configManager.loadConfiguration("/path/to/config.yaml")
}

Structured Logging and Context Management

import io.klogging.Klogging
import io.klogging.events.logContext
import io.klogging.events.LogEvent
import kotlinx.coroutines.*
import java.util.*

// API service utilizing structured logging
class ApiService : Klogging {
    
    suspend fun handleRequest(requestId: String, endpoint: String, payload: Any) = coroutineScope {
        // Request context configuration
        launch(logContext(
            "requestId" to requestId,
            "endpoint" to endpoint,
            "timestamp" to System.currentTimeMillis(),
            "service" to "ApiService"
        )) {
            logger.info { "API request received" }
            
            val startTime = System.nanoTime()
            
            try {
                // Authentication and authorization check
                authenticateRequest(requestId)
                
                // Business logic execution
                val result = processRequest(endpoint, payload)
                
                val duration = (System.nanoTime() - startTime) / 1_000_000.0
                
                // Success log (structured)
                logger.info {
                    "API request completed successfully. " +
                    "Duration: {duration}ms, Result: {resultType}"
                } withContext mapOf(
                    "duration" to duration,
                    "resultType" to result::class.simpleName,
                    "resultSize" to result.toString().length
                )
                
            } catch (e: AuthenticationException) {
                val duration = (System.nanoTime() - startTime) / 1_000_000.0
                logger.warn(e) {
                    "Authentication failed. Duration: {duration}ms"
                } withContext mapOf(
                    "duration" to duration,
                    "errorType" to "authentication",
                    "clientIp" to getCurrentClientIp()
                )
                throw e
                
            } catch (e: Exception) {
                val duration = (System.nanoTime() - startTime) / 1_000_000.0
                logger.error(e) {
                    "API request failed. Duration: {duration}ms, Error: {errorMessage}"
                } withContext mapOf(
                    "duration" to duration,
                    "errorMessage" to e.message,
                    "errorType" to e::class.simpleName
                )
                throw e
            }
        }
    }
    
    private suspend fun authenticateRequest(requestId: String) {
        logger.debug { "Authenticating request" }
        
        // Authentication processing simulation
        delay(10)
        
        if (requestId.startsWith("invalid")) {
            throw AuthenticationException("Invalid request ID")
        }
        
        logger.debug { "Authentication successful" }
    }
    
    private suspend fun processRequest(endpoint: String, payload: Any): Any {
        logger.debug { "Processing business logic for endpoint: $endpoint" }
        
        return when (endpoint) {
            "/users" -> processUserRequest(payload)
            "/orders" -> processOrderRequest(payload)
            else -> {
                logger.warn { "Unknown endpoint: $endpoint" }
                throw IllegalArgumentException("Unsupported endpoint")
            }
        }
    }
    
    private suspend fun processUserRequest(payload: Any): Map<String, Any> {
        logger.debug { "Processing user request" }
        delay(50) // Processing time simulation
        
        return mapOf(
            "status" to "success",
            "userId" to UUID.randomUUID().toString(),
            "data" to payload
        )
    }
    
    private suspend fun processOrderRequest(payload: Any): Map<String, Any> {
        logger.debug { "Processing order request" }
        delay(100) // Processing time simulation
        
        return mapOf(
            "status" to "success",
            "orderId" to UUID.randomUUID().toString(),
            "data" to payload
        )
    }
    
    private fun getCurrentClientIp(): String {
        // Client IP acquisition (implementation depends on environment)
        return "192.168.1.100"
    }
}

// Custom exception
class AuthenticationException(message: String) : Exception(message)

// Extension function to add context information
infix fun String.withContext(context: Map<String, Any>): String {
    return this // In actual Klogging, context is automatically processed
}

// Performance monitoring logger
class PerformanceLogger : Klogging {
    
    suspend fun <T> measureOperation(
        operationName: String,
        additionalContext: Map<String, Any> = emptyMap(),
        operation: suspend () -> T
    ): T = coroutineScope {
        launch(logContext(
            "operation" to operationName,
            "startTime" to System.currentTimeMillis()
        ) + additionalContext) {
            
            val startTime = System.nanoTime()
            val startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
            
            logger.debug { "Starting operation: $operationName" }
            
            try {
                val result = operation()
                val duration = (System.nanoTime() - startTime) / 1_000_000.0
                val endMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
                val memoryDelta = endMemory - startMemory
                
                logger.info {
                    "Operation completed: {operation}. Duration: {duration}ms, Memory: {memoryDelta}KB"
                } withContext mapOf(
                    "operation" to operationName,
                    "duration" to duration,
                    "memoryDelta" to memoryDelta / 1024,
                    "success" to true
                )
                
                return@launch result
                
            } catch (e: Exception) {
                val duration = (System.nanoTime() - startTime) / 1_000_000.0
                
                logger.error(e) {
                    "Operation failed: {operation}. Duration: {duration}ms, Error: {error}"
                } withContext mapOf(
                    "operation" to operationName,
                    "duration" to duration,
                    "error" to e.message,
                    "success" to false
                )
                
                throw e
            }
        }
    }
}

// Usage example
suspend fun main() {
    loggingConfiguration {
        sink("console", ANSI_CONSOLE())
        sink("file", FILE("logs/structured.log", JSON_FORMAT))
    }
    
    val apiService = ApiService()
    val perfLogger = PerformanceLogger()
    
    // API processing with structured logging
    perfLogger.measureOperation(
        "api_request_processing",
        mapOf("endpoint" to "/users", "method" to "POST")
    ) {
        apiService.handleRequest(
            "req123",
            "/users",
            mapOf("name" to "John Doe", "email" to "[email protected]")
        )
    }
}

Spring Boot Integration and Practical Examples

import io.klogging.Klogging
import io.klogging.NoCoLogging
import io.klogging.config.loggingConfiguration
import io.klogging.events.logContext
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.*
import org.springframework.stereotype.Service
import org.springframework.stereotype.Repository
import kotlinx.coroutines.*
import javax.annotation.PostConstruct

@SpringBootApplication
class KloggingDemoApplication : NoCoLogging {
    
    @PostConstruct
    fun setupLogging() {
        loggingConfiguration {
            // Development environment configuration
            ANSI_CONSOLE()
            sink("file", FILE("logs/spring-app.log"))
            sink("json", FILE("logs/spring-app.json", JSON_FORMAT))
            
            // Package-specific log levels
            logger("com.example.controller") { minLevel(Level.DEBUG) }
            logger("com.example.service") { minLevel(Level.INFO) }
            logger("com.example.repository") { minLevel(Level.WARN) }
            
            // Detailed SQL log configuration
            logger("org.springframework.jdbc") { minLevel(Level.DEBUG) }
        }
        
        logger.info { "Klogging configuration completed for Spring Boot" }
    }
}

fun main(args: Array<String>) {
    runApplication<KloggingDemoApplication>(*args)
}

// REST controller
@RestController
@RequestMapping("/api/users")
class UserController(
    private val userService: UserService
) : Klogging {
    
    @PostMapping
    suspend fun createUser(@RequestBody userRequest: CreateUserRequest): UserResponse = coroutineScope {
        val requestId = java.util.UUID.randomUUID().toString()
        
        launch(logContext(
            "requestId" to requestId,
            "endpoint" to "/api/users",
            "method" to "POST",
            "controller" to "UserController"
        )) {
            logger.info { "Creating new user: ${userRequest.email}" }
            
            try {
                val user = userService.createUser(userRequest)
                
                logger.info {
                    "User created successfully. UserId: {userId}, Email: {email}"
                } withContext mapOf(
                    "userId" to user.id,
                    "email" to user.email,
                    "requestId" to requestId
                )
                
                UserResponse(user.id, user.email, user.name, "created")
                
            } catch (e: UserAlreadyExistsException) {
                logger.warn(e) {
                    "User creation failed - already exists: {email}"
                } withContext mapOf(
                    "email" to userRequest.email,
                    "requestId" to requestId
                )
                throw e
                
            } catch (e: Exception) {
                logger.error(e) {
                    "User creation failed: {error}"
                } withContext mapOf(
                    "error" to e.message,
                    "email" to userRequest.email,
                    "requestId" to requestId
                )
                throw e
            }
        }
    }
    
    @GetMapping("/{userId}")
    suspend fun getUser(@PathVariable userId: String): UserResponse = coroutineScope {
        launch(logContext(
            "userId" to userId,
            "endpoint" to "/api/users/{userId}",
            "method" to "GET"
        )) {
            logger.debug { "Retrieving user: $userId" }
            
            val user = userService.findUser(userId)
                ?: throw UserNotFoundException("User not found: $userId")
            
            logger.debug { "User retrieved successfully" }
            
            UserResponse(user.id, user.email, user.name, "retrieved")
        }
    }
}

// Business service
@Service
class UserService(
    private val userRepository: UserRepository,
    private val emailService: EmailService
) : Klogging {
    
    suspend fun createUser(request: CreateUserRequest): User = coroutineScope {
        launch(logContext("service" to "UserService", "operation" to "createUser")) {
            logger.info { "Creating user: ${request.email}" }
            
            // Duplicate check
            val existingUser = userRepository.findByEmail(request.email)
            if (existingUser != null) {
                logger.warn { "User already exists: ${request.email}" }
                throw UserAlreadyExistsException("User already exists")
            }
            
            // User creation
            val user = User(
                id = java.util.UUID.randomUUID().toString(),
                email = request.email,
                name = request.name
            )
            
            val savedUser = userRepository.save(user)
            logger.info { "User saved to database: ${savedUser.id}" }
            
            // Welcome email sending (asynchronous)
            launch {
                emailService.sendWelcomeEmail(savedUser)
            }
            
            logger.info { "User creation completed: ${savedUser.id}" }
            savedUser
        }
    }
    
    suspend fun findUser(userId: String): User? = coroutineScope {
        launch(logContext("service" to "UserService", "operation" to "findUser")) {
            logger.debug { "Finding user: $userId" }
            
            val user = userRepository.findById(userId)
            if (user != null) {
                logger.debug { "User found: ${user.email}" }
            } else {
                logger.debug { "User not found: $userId" }
            }
            
            user
        }
    }
}

// Repository
@Repository
class UserRepository : Klogging {
    
    // Simple in-memory storage
    private val users = mutableMapOf<String, User>()
    private val emailIndex = mutableMapOf<String, String>()
    
    suspend fun save(user: User): User = withContext(Dispatchers.IO) {
        launch(logContext("repository" to "UserRepository", "operation" to "save")) {
            logger.debug { "Saving user to database: ${user.id}" }
            
            users[user.id] = user
            emailIndex[user.email] = user.id
            
            // Database save simulation
            delay(10)
            
            logger.debug { "User saved successfully: ${user.id}" }
        }
        user
    }
    
    suspend fun findById(userId: String): User? = withContext(Dispatchers.IO) {
        launch(logContext("repository" to "UserRepository", "operation" to "findById")) {
            logger.debug { "Finding user by ID: $userId" }
            
            // Database search simulation
            delay(5)
            
            val user = users[userId]
            logger.debug { "User search result: ${if (user != null) "found" else "not found"}" }
            
            user
        }
    }
    
    suspend fun findByEmail(email: String): User? = withContext(Dispatchers.IO) {
        launch(logContext("repository" to "UserRepository", "operation" to "findByEmail")) {
            logger.debug { "Finding user by email: $email" }
            
            delay(5)
            
            val userId = emailIndex[email]
            val user = userId?.let { users[it] }
            
            logger.debug { "Email search result: ${if (user != null) "found" else "not found"}" }
            
            user
        }
    }
}

// Email service
@Service
class EmailService : Klogging {
    
    suspend fun sendWelcomeEmail(user: User) = coroutineScope {
        launch(logContext(
            "service" to "EmailService",
            "operation" to "sendWelcomeEmail",
            "userId" to user.id
        )) {
            logger.info { "Sending welcome email to: ${user.email}" }
            
            try {
                // Email sending process simulation
                delay(100)
                
                logger.info { "Welcome email sent successfully to: ${user.email}" }
                
            } catch (e: Exception) {
                logger.error(e) {
                    "Failed to send welcome email to: {email}"
                } withContext mapOf(
                    "email" to user.email,
                    "userId" to user.id,
                    "error" to e.message
                )
            }
        }
    }
}

// Data classes
data class CreateUserRequest(
    val email: String,
    val name: String
)

data class UserResponse(
    val id: String,
    val email: String,
    val name: String,
    val status: String
)

data class User(
    val id: String,
    val email: String,
    val name: String
)

// Custom exceptions
class UserAlreadyExistsException(message: String) : Exception(message)
class UserNotFoundException(message: String) : Exception(message)

Advanced Configuration and Customization

import io.klogging.Klogging
import io.klogging.config.*
import io.klogging.events.*
import io.klogging.rendering.*
import io.klogging.sending.*
import kotlinx.coroutines.*
import java.time.LocalDateTime

// Advanced Klogging configuration
object AdvancedKloggingConfig {
    
    fun setupProduction() {
        loggingConfiguration {
            // Custom rendering configuration
            rendering {
                // Custom rendering in JSON format
                custom("customJson") { event ->
                    buildString {
                        append("{")
                        append("\"timestamp\":\"${event.timestamp}\",")
                        append("\"level\":\"${event.level}\",")
                        append("\"logger\":\"${event.logger}\",")
                        append("\"message\":\"${event.message}\",")
                        append("\"thread\":\"${event.items["thread"]}\",")
                        append("\"context\":{")
                        event.items.filter { it.key != "thread" }
                            .entries.joinToString(",") { "\"${it.key}\":\"${it.value}\"" }
                        append("}}")
                    }
                }
                
                // Custom console output
                custom("colorConsole") { event ->
                    val color = when (event.level) {
                        Level.ERROR -> "\u001B[31m"  // Red
                        Level.WARN -> "\u001B[33m"   // Yellow
                        Level.INFO -> "\u001B[32m"   // Green
                        Level.DEBUG -> "\u001B[36m"  // Cyan
                        else -> "\u001B[0m"          // Reset
                    }
                    val reset = "\u001B[0m"
                    "$color[${event.timestamp}] [${event.level}] ${event.logger}: ${event.message}$reset"
                }
            }
            
            // Custom destination configuration
            sending {
                // File output configuration
                custom("rotatingFile") { events ->
                    events.forEach { event ->
                        val logFile = getLogFileForDate(LocalDateTime.now())
                        writeToFile(logFile, renderEvent(event, "customJson"))
                    }
                }
                
                // External system integration
                custom("elasticSearch") { events ->
                    // ElasticSearch sending implementation
                    sendToElasticSearch(events)
                }
                
                custom("metrics") { events ->
                    // Metrics collection
                    collectMetrics(events)
                }
            }
            
            // Composite sink configuration
            sink("production") {
                renderer = "customJson"
                dispatcher = listOf("rotatingFile", "elasticSearch", "metrics")
            }
            
            sink("development") {
                renderer = "colorConsole"
                dispatcher = listOf("CONSOLE")
            }
            
            // Logger-specific configuration
            logger("com.example.api") {
                minLevel(Level.INFO)
                sink("production")
                stopOnMatch = true
            }
            
            logger("com.example.service") {
                minLevel(Level.DEBUG)
                sink("development")
                stopOnMatch = false
            }
            
            // Performance monitoring configuration
            logger("performance") {
                minLevel(Level.DEBUG)
                sink("production")
                additionalContext = mapOf(
                    "application" to "myapp",
                    "version" to "1.0.0"
                )
            }
            
            // Filter configuration
            filter { event ->
                // Sensitive information masking
                event.copy(
                    message = maskSensitiveData(event.message),
                    items = event.items.mapValues { maskSensitiveData(it.value.toString()) }
                )
            }
        }
    }
    
    private fun getLogFileForDate(date: LocalDateTime): String {
        return "logs/app-${date.toLocalDate()}.log"
    }
    
    private fun writeToFile(filename: String, content: String) {
        // File writing implementation
        java.io.File(filename).appendText(content + "\n")
    }
    
    private fun renderEvent(event: LogEvent, renderer: String): String {
        // Event rendering implementation
        return event.toString()
    }
    
    private suspend fun sendToElasticSearch(events: List<LogEvent>) {
        // ElasticSearch sending implementation
        withContext(Dispatchers.IO) {
            // POST to ElasticSearch with HTTP client
            events.forEach { event ->
                // Implementation details
            }
        }
    }
    
    private fun collectMetrics(events: List<LogEvent>) {
        // Metrics collection implementation
        events.forEach { event ->
            when (event.level) {
                Level.ERROR -> incrementErrorCounter()
                Level.WARN -> incrementWarningCounter()
                else -> incrementInfoCounter()
            }
        }
    }
    
    private fun maskSensitiveData(text: String): String {
        return text
            .replace(Regex("password[=:]\\s*\\S+", RegexOption.IGNORE_CASE), "password=***")
            .replace(Regex("token[=:]\\s*\\S+", RegexOption.IGNORE_CASE), "token=***")
            .replace(Regex("\\b\\d{4}-\\d{4}-\\d{4}-\\d{4}\\b"), "****-****-****-****")
    }
    
    private fun incrementErrorCounter() { /* Metrics implementation */ }
    private fun incrementWarningCounter() { /* Metrics implementation */ }
    private fun incrementInfoCounter() { /* Metrics implementation */ }
}

// Custom logger implementation
class AuditLogger : Klogging {
    
    suspend fun logSecurityEvent(
        eventType: String,
        userId: String?,
        details: Map<String, Any>
    ) = coroutineScope {
        launch(logContext(
            "eventType" to "security",
            "auditCategory" to eventType,
            "userId" to (userId ?: "anonymous"),
            "timestamp" to System.currentTimeMillis()
        )) {
            logger.info {
                "Security event: {eventType}. Details: {details}"
            } withContext mapOf(
                "eventType" to eventType,
                "details" to details,
                "severity" to determineSeverity(eventType)
            )
        }
    }
    
    suspend fun logBusinessEvent(
        operation: String,
        entityId: String,
        changes: Map<String, Any>
    ) = coroutineScope {
        launch(logContext(
            "eventType" to "business",
            "operation" to operation,
            "entityId" to entityId
        )) {
            logger.info {
                "Business operation: {operation} on entity {entityId}"
            } withContext mapOf(
                "operation" to operation,
                "entityId" to entityId,
                "changes" to changes,
                "changeCount" to changes.size
            )
        }
    }
    
    private fun determineSeverity(eventType: String): String {
        return when (eventType) {
            "login_failure", "unauthorized_access" -> "high"
            "login_success", "logout" -> "low"
            "password_change", "permission_change" -> "medium"
            else -> "low"
        }
    }
}

// Usage example
suspend fun main() {
    AdvancedKloggingConfig.setupProduction()
    
    val auditLogger = AuditLogger()
    
    // Security event
    auditLogger.logSecurityEvent(
        "login_failure",
        "user123",
        mapOf(
            "ip" to "192.168.1.100",
            "userAgent" to "Mozilla/5.0...",
            "reason" to "invalid_password"
        )
    )
    
    // Business event
    auditLogger.logBusinessEvent(
        "user_update",
        "user123",
        mapOf(
            "oldEmail" to "[email protected]",
            "newEmail" to "[email protected]",
            "updatedBy" to "admin"
        )
    )
}