redis/extra/rediscensus/rediscensus.go

77 lines
1.7 KiB
Go

package rediscensus
import (
"context"
"net"
"go.opencensus.io/trace"
"github.com/redis/go-redis/extra/rediscmd/v9"
"github.com/redis/go-redis/v9"
)
type TracingHook struct{}
var _ redis.Hook = (*TracingHook)(nil)
func NewTracingHook() *TracingHook {
return new(TracingHook)
}
func (TracingHook) DialHook(next redis.DialHook) redis.DialHook {
return func(ctx context.Context, network, addr string) (net.Conn, error) {
ctx, span := trace.StartSpan(ctx, "dial")
defer span.End()
span.AddAttributes(
trace.StringAttribute("db.system", "redis"),
trace.StringAttribute("network", network),
trace.StringAttribute("addr", addr),
)
conn, err := next(ctx, network, addr)
if err != nil {
recordErrorOnOCSpan(ctx, span, err)
return nil, err
}
return conn, nil
}
}
func (TracingHook) ProcessHook(next redis.ProcessHook) redis.ProcessHook {
return func(ctx context.Context, cmd redis.Cmder) error {
ctx, span := trace.StartSpan(ctx, cmd.FullName())
defer span.End()
span.AddAttributes(
trace.StringAttribute("db.system", "redis"),
trace.StringAttribute("redis.cmd", rediscmd.CmdString(cmd)),
)
err := next(ctx, cmd)
if err != nil {
recordErrorOnOCSpan(ctx, span, err)
return err
}
if err = cmd.Err(); err != nil {
recordErrorOnOCSpan(ctx, span, err)
}
return nil
}
}
func (TracingHook) ProcessPipelineHook(next redis.ProcessPipelineHook) redis.ProcessPipelineHook {
return next
}
func recordErrorOnOCSpan(ctx context.Context, span *trace.Span, err error) {
if err != redis.Nil {
span.AddAttributes(trace.BoolAttribute("error", true))
span.Annotate([]trace.Attribute{trace.StringAttribute("Error", "redis error")}, err.Error())
}
}