Kotlin SDK

GitHub

Official Kotlin SDK for LogWard with coroutines support, automatic batching, retry logic, circuit breaker, query API, and middleware integrations for Ktor, Spring Boot, and Jakarta Servlet.

Installation

Gradle (Kotlin DSL)

kotlin
dependencies {
    implementation("io.github.logward-dev:logward-sdk-kotlin:0.2.0")
}

Gradle (Groovy)

groovy
dependencies {
    implementation 'io.github.logward-dev:logward-sdk-kotlin:0.2.0'
}

Maven

xml
<dependency>
    <groupId>io.github.logward-dev</groupId>
    <artifactId>logward-sdk-kotlin</artifactId>
    <version>0.2.0</version>
</dependency>

Quick Start

kotlin
import dev.logward.sdk.LogWardClient
import dev.logward.sdk.models.LogWardClientOptions

val client = LogWardClient(
    LogWardClientOptions(
        apiUrl = "http://localhost:8080",
        apiKey = "lp_your_api_key_here"
    )
)

// Send logs
client.info("api-gateway", "Server started", mapOf("port" to 3000))
client.error("database", "Connection failed", RuntimeException("Timeout"))

// Graceful shutdown (also automatic on JVM shutdown)
runBlocking {
    client.close()
}

Features

  • ✅ Automatic batching with configurable size and interval
  • ✅ Retry logic with exponential backoff
  • ✅ Circuit breaker pattern for fault tolerance
  • ✅ Max buffer size with drop policy to prevent memory leaks
  • ✅ Query API for searching and filtering logs
  • ✅ Live tail with Server-Sent Events (SSE)
  • ✅ Trace ID context for distributed tracing
  • ✅ Global metadata added to all logs
  • ✅ Structured error serialization
  • ✅ Internal metrics (logs sent, errors, latency)
  • ✅ Coroutines support for async operations
  • ✅ Ktor Plugin for automatic HTTP logging
  • ✅ Spring Boot Interceptor for automatic HTTP logging
  • ✅ Jakarta Servlet Filter for automatic HTTP logging
  • ✅ Kotlin Multiplatform ready

Configuration

kotlin
val client = LogWardClient(LogWardClientOptions(
    // Required
    apiUrl = "http://localhost:8080",
    apiKey = "lp_your_api_key",
    
    // Optional - Performance
    batchSize = 100,              // Max logs per batch (default: 100)
    flushInterval = 5.seconds,    // Flush interval (default: 5s)
    maxBufferSize = 10000,        // Max logs in buffer (default: 10000)
    
    // Optional - Reliability
    maxRetries = 3,               // Max retry attempts (default: 3)
    retryDelay = 1.seconds,       // Initial retry delay (default: 1s)
    circuitBreakerThreshold = 5,  // Failures before circuit opens (default: 5)
    circuitBreakerTimeout = 60.seconds, // Circuit reset timeout (default: 60s)
    
    // Optional - Metadata
    globalMetadata = mapOf(       // Added to all logs
        "environment" to "production",
        "version" to "1.0.0"
    ),
    
    // Optional - Features
    enableMetrics = true,         // Enable metrics collection (default: true)
    debug = false                 // Enable debug logging (default: false)
))

Logging Methods

Basic Logging

kotlin
// Log levels: debug, info, warn, error, critical
client.debug("service-name", "Debug message", mapOf("detail" to "value"))
client.info("api-gateway", "Request received", mapOf("method" to "GET", "path" to "/users"))
client.warn("cache", "Cache miss", mapOf("key" to "user:123"))
client.error("database", "Query failed", mapOf("query" to "SELECT *"))
client.critical("system", "Out of memory", mapOf("used" to "95%"))

Error Logging with Auto-Serialization

kotlin
// Automatically serializes exception details
try {
    database.connect()
} catch (e: SQLException) {
    client.error("database", "Connection failed", e)
    // Automatically includes: exception type, message, and stack trace
}

Trace ID Context

kotlin
// Manual trace ID
client.withTraceId("550e8400-e29b-41d4-a716-446655440000") {
    client.info("api", "Processing request")
    client.info("db", "Query executed")
}

// Scoped trace ID (coroutines)
coroutineScope {
    client.withTraceId("my-trace-id") {
        launch { client.info("worker-1", "Task started") }
        launch { client.info("worker-2", "Task started") }
    }
}

// Auto-generated trace ID
client.withTraceId { // generates UUID
    client.info("api", "Request processing")
}

Middleware Integration

Ktor Plugin

Automatically log HTTP requests and responses in Ktor applications.

kotlin
import dev.logward.sdk.middleware.LogWardPlugin
import io.ktor.server.application.*

fun Application.module() {
    install(LogWardPlugin) {
        apiUrl = "http://localhost:8080"
        apiKey = "lp_your_api_key_here"
        serviceName = "ktor-app"

        // Optional configuration
        logRequests = true
        logResponses = true
        logErrors = true
        skipHealthCheck = true
        skipPaths = setOf("/metrics", "/internal")

        // Client options
        batchSize = 100
        flushInterval = 5.seconds
        enableMetrics = true
        globalMetadata = mapOf("env" to "production")
    }
}

// Access client manually in routes
routing {
    get("/api/custom") {
        val client = call.application.attributes[LogWardClientKey]
        client.info("my-service", "Custom business logic executed",
            mapOf("userId" to 123, "action" to "custom_operation"))
        call.respondText("OK")
    }
}

Spring Boot Interceptor

Automatically log HTTP requests and responses in Spring Boot applications.

kotlin
import dev.logward.sdk.LogWardClient
import dev.logward.sdk.middleware.LogWardInterceptor
import dev.logward.sdk.models.LogWardClientOptions
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer

@Configuration
class LogWardConfig : WebMvcConfigurer {

    @Bean
    fun logWardClient() = LogWardClient(
        LogWardClientOptions(
            apiUrl = "http://localhost:8080",
            apiKey = "lp_your_api_key_here"
        )
    )

    @Bean
    fun logWardInterceptor(client: LogWardClient) = LogWardInterceptor(
        client = client,
        serviceName = "spring-boot-app",
        logRequests = true,
        logResponses = true,
        skipHealthCheck = true
    )

    override fun addInterceptors(registry: InterceptorRegistry) {
        registry.addInterceptor(logWardInterceptor(logWardClient()))
    }
}

Jakarta Servlet Filter

Automatically log HTTP requests and responses in Jakarta Servlet applications (Tomcat, Jetty, etc.).

kotlin
import dev.logward.sdk.LogWardClient
import dev.logward.sdk.middleware.LogWardFilter
import dev.logward.sdk.models.LogWardClientOptions

// Create client
val client = LogWardClient(
    LogWardClientOptions(
        apiUrl = "http://localhost:8080",
        apiKey = "lp_your_api_key_here"
    )
)

// Create filter
val filter = LogWardFilter(
    client = client,
    serviceName = "servlet-app",
    logRequests = true,
    logResponses = true,
    skipHealthCheck = true
)

// Add to servlet context
servletContext.addFilter("logWard", filter)

Query API

Basic Query

kotlin
// Search logs
val result = client.query(
    service = "api-gateway",
    level = "error",
    from = "2025-01-15T00:00:00Z",
    to = "2025-01-15T23:59:59Z",
    limit = 100
)

println("Found ${result.total} error logs")
result.logs.forEach { log ->
    println("[${log.time}] ${log.message}")
}

Full-Text Search

kotlin
val result = client.query(
    q = "timeout OR connection",  // Full-text search
    level = "error",
    limit = 50
)

Get Logs by Trace ID

kotlin
val logs = client.getLogsByTraceId(
    traceId = "550e8400-e29b-41d4-a716-446655440000"
)

// Returns all logs with the same trace_id
logs.forEach { log ->
    println("[${log.service}] ${log.message}")
}

Live Streaming (SSE)

kotlin
// Stream logs in real-time
client.liveTail(
    service = "api-gateway",
    level = "error"
) { log ->
    // Called for each new log
    println("[${log.time}] ${log.message}")
}

// Stream will automatically reconnect on connection loss

Metrics

kotlin
// Get internal metrics
val metrics = client.getMetrics()

println("Logs sent: ${metrics.logsSent}")
println("Logs failed: ${metrics.logsFailed}")
println("Avg latency: ${metrics.avgLatencyMs}ms")
println("Circuit breaker state: ${metrics.circuitBreakerState}")

Best Practices

1. Use Middleware for HTTP Logging
Leverage built-in middleware plugins (Ktor, Spring Boot, Jakarta Servlet) for automatic HTTP request/response logging instead of manual instrumentation.
2. Use Coroutines for Async
Leverage Kotlin coroutines for non-blocking log operations in high-concurrency applications.
3. Graceful Shutdown
Always call client.close() on shutdown to ensure buffered logs are flushed before JVM terminates. The SDK also registers an automatic shutdown hook.
4. Use Global Metadata
Set global metadata (environment, version) at initialization to avoid repeating it in every log call.