Official Kotlin SDK for LogTide 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)
dependencies {
implementation("io.github.logtide-dev:logtide-sdk-kotlin:0.2.0")
} Gradle (Groovy)
dependencies {
implementation 'io.github.logtide-dev:logtide-sdk-kotlin:0.2.0'
} Maven
<dependency>
<groupId>io.github.logtide-dev</groupId>
<artifactId>logtide-sdk-kotlin</artifactId>
<version>0.2.0</version>
</dependency> Quick Start
import dev.logtide.sdk.LogTideClient
import dev.logtide.sdk.models.LogTideClientOptions
val client = LogTideClient(
LogTideClientOptions(
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
val client = LogTideClient(LogTideClientOptions(
// 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
// 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
// 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
// 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.
import dev.logtide.sdk.middleware.LogTidePlugin
import io.ktor.server.application.*
fun Application.module() {
install(LogTidePlugin) {
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[LogTideClientKey]
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.
import dev.logtide.sdk.LogTideClient
import dev.logtide.sdk.middleware.LogTideInterceptor
import dev.logtide.sdk.models.LogTideClientOptions
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 LogTideConfig : WebMvcConfigurer {
@Bean
fun logTideClient() = LogTideClient(
LogTideClientOptions(
apiUrl = "http://localhost:8080",
apiKey = "lp_your_api_key_here"
)
)
@Bean
fun logTideInterceptor(client: LogTideClient) = LogTideInterceptor(
client = client,
serviceName = "spring-boot-app",
logRequests = true,
logResponses = true,
skipHealthCheck = true
)
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(logTideInterceptor(logTideClient()))
}
} Jakarta Servlet Filter
Automatically log HTTP requests and responses in Jakarta Servlet applications (Tomcat, Jetty, etc.).
import dev.logtide.sdk.LogTideClient
import dev.logtide.sdk.middleware.LogTideFilter
import dev.logtide.sdk.models.LogTideClientOptions
// Create client
val client = LogTideClient(
LogTideClientOptions(
apiUrl = "http://localhost:8080",
apiKey = "lp_your_api_key_here"
)
)
// Create filter
val filter = LogTideFilter(
client = client,
serviceName = "servlet-app",
logRequests = true,
logResponses = true,
skipHealthCheck = true
)
// Add to servlet context
servletContext.addFilter("logTide", filter) Query API
Basic Query
// 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
val result = client.query(
q = "timeout OR connection", // Full-text search
level = "error",
limit = 50
) Get Logs by Trace ID
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)
// 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
// 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.