forked from woggioni/rbcs
Add OpenTelemetry tracing support for Redis commands
- Add RedisSpan interface in rbcs-api for opaque span handles - Extend TelemetryController with startRedisSpan/endRedisSpan methods - Implement Redis tracing in rbcs-server-otel via OtelController and RedisOtelSpan - Instrument RedisCacheHandler to create spans around GET and SET commands - Add uses directive in rbcs-server-redis module-info for ServiceLoader discovery Redis spans are created as CLIENT spans with attributes: db.system=redis, db.operation=GET|SET, server.address, server.port
This commit is contained in:
@@ -2,10 +2,13 @@ package net.woggioni.rbcs.server.otel
|
||||
|
||||
import io.netty.channel.ChannelHandler
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry
|
||||
import io.opentelemetry.api.trace.SpanKind
|
||||
import io.opentelemetry.api.trace.StatusCode
|
||||
import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender
|
||||
import io.opentelemetry.instrumentation.netty.v4_1.NettyServerTelemetry
|
||||
import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry
|
||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk
|
||||
import net.woggioni.rbcs.api.RedisSpan
|
||||
import net.woggioni.rbcs.api.TelemetryController
|
||||
import net.woggioni.rbcs.common.createLogger
|
||||
import net.woggioni.rbcs.common.info
|
||||
@@ -14,6 +17,10 @@ class OtelController : TelemetryController {
|
||||
|
||||
private val log = createLogger<OtelController>()
|
||||
|
||||
private val tracer by lazy {
|
||||
GlobalOpenTelemetry.getTracer("net.woggioni.rbcs.server.redis", "0.5.0")
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
log.info { "Initializing OpenTelemetry SDK with auto-configuration" }
|
||||
|
||||
@@ -36,4 +43,24 @@ class OtelController : TelemetryController {
|
||||
override fun createHandler(): ChannelHandler {
|
||||
return NettyServerTelemetry.create(GlobalOpenTelemetry.get()).createCombinedHandler()
|
||||
}
|
||||
|
||||
override fun startRedisSpan(command: String, key: String): RedisSpan? {
|
||||
val span = tracer.spanBuilder(command)
|
||||
.setSpanKind(SpanKind.CLIENT)
|
||||
.setAttribute("db.system", "redis")
|
||||
.setAttribute("db.operation", command)
|
||||
.startSpan()
|
||||
return RedisOtelSpan(span)
|
||||
}
|
||||
|
||||
override fun endRedisSpan(span: RedisSpan?) {
|
||||
(span as? RedisOtelSpan)?.delegate?.end()
|
||||
}
|
||||
|
||||
override fun endRedisSpan(span: RedisSpan?, error: Throwable) {
|
||||
val s = (span as? RedisOtelSpan)?.delegate ?: return
|
||||
s.recordException(error)
|
||||
s.setStatus(StatusCode.ERROR)
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.woggioni.rbcs.server.otel
|
||||
|
||||
import io.opentelemetry.api.trace.Span
|
||||
import net.woggioni.rbcs.api.RedisSpan
|
||||
|
||||
internal class RedisOtelSpan(
|
||||
val delegate: Span,
|
||||
) : RedisSpan {
|
||||
|
||||
override fun setAttribute(key: String, value: String) {
|
||||
delegate.setAttribute(key, value)
|
||||
}
|
||||
|
||||
override fun setAttribute(key: String, value: Long) {
|
||||
delegate.setAttribute(key, value)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user