1
0
mirror of https://github.com/etcd-io/etcd.git synced 2026-02-05 15:46:51 +01:00

Add OTEL tracing to Range and Txn

Signed-off-by: Aleksander Mistewicz <amistewicz@google.com>
This commit is contained in:
Aleksander Mistewicz
2025-07-09 10:55:13 +02:00
parent 5af30121bf
commit a291faad71
5 changed files with 50 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ require (
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0
go.opentelemetry.io/otel/trace v1.37.0
go.uber.org/zap v1.27.0
google.golang.org/grpc v1.73.0
)

View File

@@ -22,9 +22,19 @@ import (
"strings"
"time"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"go.uber.org/zap"
)
const instrumentationScope = "go.etcd.io/etcd"
var Tracer trace.Tracer = noop.NewTracerProvider().Tracer(instrumentationScope)
func Init(tp trace.TracerProvider) {
Tracer = tp.Tracer(instrumentationScope)
}
// TraceKey is used as a key of context for Trace.
type TraceKey struct{}

View File

@@ -25,6 +25,8 @@ import (
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
"go.uber.org/zap"
"go.etcd.io/etcd/pkg/v3/traceutil"
)
const maxSamplingRatePerMillion = 1000000
@@ -81,6 +83,8 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err
),
)
traceutil.Init(traceProvider)
options := []otelgrpc.Option{
otelgrpc.WithPropagators(
propagation.NewCompositeTextMapPropagator(

View File

@@ -24,6 +24,8 @@ import (
"time"
"github.com/gogo/protobuf/proto"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
@@ -102,6 +104,16 @@ type Authenticator interface {
}
func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
var span trace.Span
ctx, span = traceutil.Tracer.Start(ctx, "range", trace.WithAttributes(
attribute.String("range_begin", string(r.GetKey())),
attribute.String("range_end", string(r.GetRangeEnd())),
attribute.Int64("rev", r.GetRevision()),
attribute.Int64("limit", r.GetLimit()),
attribute.Bool("count_only", r.GetCountOnly()),
))
defer span.End()
ctx, trace := traceutil.EnsureTrace(ctx, s.Logger(), "range",
traceutil.Field{Key: "range_begin", Value: string(r.Key)},
traceutil.Field{Key: "range_end", Value: string(r.RangeEnd)},
@@ -156,8 +168,30 @@ func (s *EtcdServer) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest)
return resp.(*pb.DeleteRangeResponse), nil
}
// firstCompareKey returns first non-empty key in the list of comparison operations.
func firstCompareKey(c []*pb.Compare) string {
for _, op := range c {
key := string(op.GetKey())
if key != "" {
return key
}
}
return ""
}
func (s *EtcdServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
readOnly := txn.IsTxnReadonly(r)
var span trace.Span
ctx, span = traceutil.Tracer.Start(ctx, "txn", trace.WithAttributes(
attribute.String("compare_first_key", firstCompareKey(r.GetCompare())),
attribute.Int("compare_len", len(r.GetCompare())),
attribute.Int("success_len", len(r.GetSuccess())),
attribute.Int("failure_len", len(r.GetFailure())),
attribute.Bool("read_only", readOnly),
))
defer span.End()
ctx, trace := traceutil.EnsureTrace(ctx, s.Logger(), "transaction",
traceutil.Field{Key: "read_only", Value: readOnly},
)

View File

@@ -35,6 +35,7 @@ require (
go.opentelemetry.io/otel v1.37.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0
go.opentelemetry.io/otel/sdk v1.37.0
go.opentelemetry.io/otel/trace v1.37.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.39.0
golang.org/x/net v0.41.0
@@ -67,7 +68,6 @@ require (
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect