1
0
mirror of https://github.com/redis/go-redis.git synced 2025-04-17 20:17:02 +03:00
go-redis/extra/redisotel/redisotel.go
Kristinn Björgvin Árdal 065b200070 fix(extra/redisotel): set span.kind attribute to client
According to the opentelemetry specification this should always be set to client for database client
libraries.

I've also removed the SetAttributes call and instead set the attributes during creation of the span.
This is what the library SHOULD be doing according to the opentelemetry api specification.
2021-10-27 10:28:48 +02:00

90 lines
2.1 KiB
Go

package redisotel
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"github.com/go-redis/redis/extra/rediscmd/v8"
"github.com/go-redis/redis/v8"
)
var tracer = otel.Tracer("github.com/go-redis/redis")
type TracingHook struct{}
var _ redis.Hook = (*TracingHook)(nil)
func NewTracingHook() *TracingHook {
return new(TracingHook)
}
func (TracingHook) BeforeProcess(ctx context.Context, cmd redis.Cmder) (context.Context, error) {
if !trace.SpanFromContext(ctx).IsRecording() {
return ctx, nil
}
attrs := []attribute.KeyValue{
attribute.String("db.system", "redis"),
attribute.String("db.statement", rediscmd.CmdString(cmd)),
}
opts := []trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(attrs...),
}
ctx, _ = tracer.Start(ctx, cmd.FullName(), opts...)
return ctx, nil
}
func (TracingHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error {
span := trace.SpanFromContext(ctx)
if err := cmd.Err(); err != nil {
recordError(ctx, span, err)
}
span.End()
return nil
}
func (TracingHook) BeforeProcessPipeline(ctx context.Context, cmds []redis.Cmder) (context.Context, error) {
if !trace.SpanFromContext(ctx).IsRecording() {
return ctx, nil
}
summary, cmdsString := rediscmd.CmdsString(cmds)
attrs := []attribute.KeyValue{
attribute.String("db.system", "redis"),
attribute.Int("db.redis.num_cmd", len(cmds)),
attribute.String("db.statement", cmdsString),
}
opts := []trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(attrs...),
}
ctx, _ = tracer.Start(ctx, "pipeline "+summary, opts...)
return ctx, nil
}
func (TracingHook) AfterProcessPipeline(ctx context.Context, cmds []redis.Cmder) error {
span := trace.SpanFromContext(ctx)
if err := cmds[0].Err(); err != nil {
recordError(ctx, span, err)
}
span.End()
return nil
}
func recordError(ctx context.Context, span trace.Span, err error) {
if err != redis.Nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
}