LokiClient
0.7.0indexedImplements Grafana Loki HTTP API for sending, querying, and analyzing logs. Supports flexible log analysis, pattern detection, and log volume monitoring with structured metadata.
Implements Grafana Loki HTTP API for sending, querying, and analyzing logs. Supports flexible log analysis, pattern detection, and log volume monitoring with structured metadata.
LokiClient implements the Grafana Loki HTTP API for all Kotlin Multiplatform targets.
It lets you send logs, query log streams, and analyze log data from any Kotlin target. So you can build cross-platform logging tools or dashboards and integrate logging into monitoring and alerting workflows.
implementation("net.codinux.log.loki:loki-client:0.7.0")
<dependency>
<groupId>net.codinux.log.loki</groupId>
<artifactId>loki-client-jvm</artifactId>
<version>0.7.0</version>
</dependency>
Add an implementation of the WebClient API like ktor-web-client (for Kotlin Multiplatform) or java-http-client-web-client (for dependency-less Java 11+ HttpClient, e.g. for native image):
implementation("net.dankito.web:ktor-web-client:1.6.0")
Now configure Loki base url and authentication and instantiate WebClient implementation:
private val webClient = KtorWebClient()
private val client = LokiClient("http://localhost:3100", webClient)
// or
private val config = LokiConfig(
baseUrl = "http://localhost:3100",
authentication = BasicAuthAuthentication("username", "password"),
internalEndpointsPathPrefix = null
)
private val clientAuthenticated = LokiClient(config, webClient)
LokiClient implements the Loki API as is. For a higher level abstraction use LokiService which uses LokiClient under the hood:
private val service = LokiService(client)
See examples below:
// query logs of namespace 'monitoring' of last 2 hours
val result = service.queryLogs(query = , start = LokiTimestamp(Instant.now().minusHours()))
result.mapBodyOnSuccess { logs ->
println()
logs.forEachIndexed { index, log -> println() }
}
service.queryLogs(, since = hours, end = LokiTimestamp.ofDate(, , ),
direction = SortOrder.Backward, limit = )
service.ingestLogs(
LogEntryToSave(timestamp = LokiTimestamp.now(), message = "Something important happened"),
LogEntryToSave(timestamp = LokiTimestamp.now(), message = "With Labels", labels = mapOf("namespace" to "monitoring", "job" to "podlogs")),
LogEntryToSave(timestamp = LokiTimestamp.now(), message = "With structured metadata", labels = mapOf("namespace" to "monitoring"),
structuredMetadata = mapOf("level" to "info", "pod" to "MonitoringApp-58f856b99-5gwtt")),
)
// all of the methods below can be restricted with query, start, end and since parameter
val allLabels = service.getAllLabels()
val valuesOfLabelNamespace = client.queryLabelValues("namespace")
// e.g. get Log volume of each namespace
service.getIndexVolume("namespace=~\".+\"").mapBodyOnSuccess { response, indexVolumes ->
indexVolumes.forEach { volume -> println("${volume.metrics["namespace"]}: ${volume.aggregatedValue}") }
}
// group log volume by labels like 'service_name' and aggregate by labels or series
service.getIndexVolume("", groupByLabels = listOf("service_name"), aggregateBy = AggregateBy.Labels)
// does the same as `logcli series --analyze-labels` does:
val results: LabelAnalyzationResults = service.analyzeLabels()
results.labels.forEach {
println("${it.label}: Unique values: ${it.uniqueValues}. Found in Streams: ${it.foundInStreams}")
}
val streamsInNamespaceMonitoring: Set<Map<String, String>> = service.getAllStreams("namespace=~\"monitoring\"")
Copyright 2025 codinux GmbH & Co. KG
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance the License.
You may obtain a copy of the License at
https:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.
Surfaced from shared tags and platforms — no rankings paid for.