Skip to content

stats/opentelemetry: separate out interceptors for tracing and metrics #8063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 62 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7ddbe46
replace dial with newclient
janardhankrishna-sai Dec 23, 2024
0486355
Merge branch 'master' of https://github.com/janardhanvissa/grpc-go
janardhankrishna-sai Jan 1, 2025
53fa9cd
Merge branch 'grpc:master' into master
janardhanvissa Jan 8, 2025
4435b8a
Merge branch 'grpc:master' into master
janardhanvissa Jan 13, 2025
a413555
Merge branch 'grpc:master' into master
janardhanvissa Jan 20, 2025
4e203c3
Merge branch 'grpc:master' into master
janardhanvissa Jan 30, 2025
e9ad552
Merge branch 'grpc:master' into master
janardhanvissa Jan 30, 2025
71804b4
refactor tracing and metrics interceptors separately
janardhankrishna-sai Feb 3, 2025
4b3bd26
adding opentelemetry tracing for client-server
janardhankrishna-sai Jan 30, 2025
69df069
fixing vet issues
janardhankrishna-sai Feb 3, 2025
770f430
reverting newclient changes and fixing vet issues
janardhankrishna-sai Feb 3, 2025
b97a3ca
reverting otel trace for client/server changes
janardhankrishna-sai Feb 3, 2025
c89f3c9
fixing vet issue
janardhankrishna-sai Feb 3, 2025
3f07e48
renaming receiver name
janardhankrishna-sai Feb 5, 2025
5e8a4a5
unused param fix
janardhankrishna-sai Feb 5, 2025
76e422a
fixing vet issue
janardhankrishna-sai Feb 5, 2025
8fa0b03
refactor client interceptor separately for traces and metrics
janardhankrishna-sai Feb 12, 2025
1f41a49
moving tracing code to client_tracing.go file
janardhankrishna-sai Feb 12, 2025
d74c61d
revert previous commit
janardhankrishna-sai Feb 12, 2025
170eef6
adding separate interceptors for traces and metrics of server
janardhankrishna-sai Feb 17, 2025
7f5f539
separating HandleRPC interceptors of traces and metrics
janardhankrishna-sai Feb 17, 2025
50999a0
updating client and server metrics
janardhankrishna-sai Feb 18, 2025
68b8966
removing metrics code from tracingstatshandler and unused parameters
janardhankrishna-sai Feb 19, 2025
8b56f0f
addressing review comments
janardhankrishna-sai Feb 24, 2025
ac6080f
addressing review comments
janardhankrishna-sai Feb 25, 2025
ed5506c
Merge branch 'master' into refactor-tracing-metrics
janardhanvissa Feb 25, 2025
be72377
updating go.sum
janardhankrishna-sai Feb 25, 2025
a5ed115
fixing linter issue
janardhankrishna-sai Feb 25, 2025
f243b43
addressing review comments for client
janardhankrishna-sai Mar 7, 2025
efb738f
addressing review comments for client
janardhankrishna-sai Mar 7, 2025
7b97c65
Merge branch 'master' into refactor-tracing-metrics
janardhanvissa Mar 7, 2025
e8b0180
addressing review comments for server
janardhankrishna-sai Mar 7, 2025
f70274b
fixing vet issue
janardhankrishna-sai Mar 7, 2025
5e607c5
updating newServerStatsHandler
janardhankrishna-sai Mar 7, 2025
a850532
updating var name
janardhankrishna-sai Mar 7, 2025
0f39f8d
moving tracing code to a separate file and adding comments
janardhankrishna-sai Mar 10, 2025
2a914e3
removing unused isMetricsEnabled()
janardhankrishna-sai Mar 10, 2025
05b4278
addressing review comments and updating doc string
janardhankrishna-sai Mar 10, 2025
105efe9
addressing review comments
janardhankrishna-sai Mar 10, 2025
3d78d59
creating helper func for rpcinfo
janardhankrishna-sai Mar 10, 2025
44fce2d
addressing review comments
janardhankrishna-sai Mar 13, 2025
e5f50b7
updating logger
janardhankrishna-sai Mar 13, 2025
ffcc0fa
Merge branch 'master' into refactor-tracing-metrics
janardhanvissa Mar 13, 2025
67e5b24
update unaryInterceptor
janardhankrishna-sai Mar 13, 2025
8cf7f15
revert doc string
janardhankrishna-sai Mar 13, 2025
7949501
fixing vet issue
janardhankrishna-sai Mar 13, 2025
ad22a22
update clientStatsHandler unaryInterceptor
janardhankrishna-sai Mar 13, 2025
dd179fb
updating verbosity level and removing redundant code
janardhankrishna-sai Mar 13, 2025
3201805
reverting logger.Info from logger.Error
janardhankrishna-sai Mar 13, 2025
a3915ef
Update server_metrics.go
janardhanvissa Mar 13, 2025
1ff5159
addressing review comments
janardhankrishna-sai Mar 18, 2025
4133dd3
updating the comment
janardhankrishna-sai Mar 18, 2025
f8e0cac
addressing review comments
janardhankrishna-sai Mar 20, 2025
0b89cf6
fixing vet issue
janardhankrishna-sai Mar 20, 2025
42c08a0
fixing linter issue
janardhankrishna-sai Mar 20, 2025
5bb48b3
addressing review comments
janardhankrishna-sai Mar 25, 2025
fb8025d
addressing review comments
janardhankrishna-sai Mar 26, 2025
cc39d1a
addressing review comments
janardhankrishna-sai Apr 1, 2025
eb8321f
Initializes ri to &rpcInfo{} when it's nil, separating the initializa…
janardhankrishna-sai Apr 2, 2025
c858ed2
Merge branch 'master' into refactor-tracing-metrics
janardhanvissa Apr 4, 2025
5c57489
fixing vet issue
janardhankrishna-sai Apr 4, 2025
cc12a84
addressing review comments
janardhankrishna-sai Apr 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 61 additions & 72 deletions stats/opentelemetry/client_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,23 @@
"sync/atomic"
"time"

otelcodes "go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
otelattribute "go.opentelemetry.io/otel/attribute"
otelmetric "go.opentelemetry.io/otel/metric"
"google.golang.org/grpc"
grpccodes "google.golang.org/grpc/codes"
estats "google.golang.org/grpc/experimental/stats"
istats "google.golang.org/grpc/internal/stats"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"

otelattribute "go.opentelemetry.io/otel/attribute"
otelmetric "go.opentelemetry.io/otel/metric"
)

type clientStatsHandler struct {
type clientMetricsHandler struct {
estats.MetricsRecorder
options Options
clientMetrics clientMetrics
}

func (h *clientStatsHandler) initializeMetrics() {
func (h *clientMetricsHandler) initializeMetrics() {
// Will set no metrics to record, logically making this stats handler a
// no-op.
if h.options.MetricsOptions.MeterProvider == nil {
Expand Down Expand Up @@ -71,12 +67,18 @@
rm.registerMetrics(metrics, meter)
}

func (h *clientStatsHandler) unaryInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ci := &callInfo{
target: cc.CanonicalTarget(),
method: h.determineMethod(method, opts...),
func (h *clientMetricsHandler) unaryInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ci := getCallInfo(ctx)
if ci == nil {
if logger.V(2) {
logger.Info("Creating new CallInfo since its not present in context in clientStatsHandler unaryInterceptor")
}

Check warning on line 75 in stats/opentelemetry/client_metrics.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_metrics.go#L74-L75

Added lines #L74 - L75 were not covered by tests
ci = &callInfo{
target: cc.CanonicalTarget(),
method: determineMethod(method, opts...),
}
ctx = setCallInfo(ctx, ci)
}
Comment on lines +71 to 81
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we doing this? I would expect every unary interceptor start should be for a new call attempt, so there should never be anything in the context already? Am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, with this refactor, we have 2 stats handler now 1) metrics and 2) traces. The stats handlers are executed in the order in which they are added. So, if metrics handler executes first, we need to make sure that tracing handler doesn't create a new call info rather use the existing one and add the tracing stuff there. Vice-versa is also true if in future we change the order of interceptors. Basically, each interceptor needs to check if call info already exist or not and then add its info to existing one if present otherwise create a new one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so we are sharing the same data between the two interceptors.

In that case, can we pull it out into one function and call it from all four places? getOrCreateCallInfo or something? And a comment indicating that it may already be present if the other interceptor ran first.

ctx = setCallInfo(ctx, ci)

if h.options.MetricsOptions.pluginOption != nil {
md := h.options.MetricsOptions.pluginOption.GetMetadata()
Expand All @@ -88,19 +90,15 @@
}

startTime := time.Now()
var span trace.Span
if h.options.isTracingEnabled() {
ctx, span = h.createCallTraceSpan(ctx, method)
}
err := invoker(ctx, method, req, reply, cc, opts...)
h.perCallTracesAndMetrics(ctx, err, startTime, ci, span)
h.perCallMetrics(ctx, err, startTime, ci)
return err
}

// determineMethod determines the method to record attributes with. This will be
// "other" if StaticMethod isn't specified or if method filter is set and
// specifies, the method name as is otherwise.
func (h *clientStatsHandler) determineMethod(method string, opts ...grpc.CallOption) string {
func determineMethod(method string, opts ...grpc.CallOption) string {
for _, opt := range opts {
if _, ok := opt.(grpc.StaticMethodCallOption); ok {
return removeLeadingSlash(method)
Expand All @@ -109,12 +107,18 @@
return "other"
}

func (h *clientStatsHandler) streamInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
ci := &callInfo{
target: cc.CanonicalTarget(),
method: h.determineMethod(method, opts...),
func (h *clientMetricsHandler) streamInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
ci := getCallInfo(ctx)
if ci == nil {
if logger.V(2) {
logger.Info("Creating new CallInfo since its not present in context in clientStatsHandler streamInterceptor")
}

Check warning on line 115 in stats/opentelemetry/client_metrics.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_metrics.go#L114-L115

Added lines #L114 - L115 were not covered by tests
ci = &callInfo{
target: cc.CanonicalTarget(),
method: determineMethod(method, opts...),
}
ctx = setCallInfo(ctx, ci)
}
ctx = setCallInfo(ctx, ci)

if h.options.MetricsOptions.pluginOption != nil {
md := h.options.MetricsOptions.pluginOption.GetMetadata()
Expand All @@ -126,49 +130,34 @@
}

startTime := time.Now()
var span trace.Span
if h.options.isTracingEnabled() {
ctx, span = h.createCallTraceSpan(ctx, method)
}
callback := func(err error) {
h.perCallTracesAndMetrics(ctx, err, startTime, ci, span)
h.perCallMetrics(ctx, err, startTime, ci)
}
opts = append([]grpc.CallOption{grpc.OnFinish(callback)}, opts...)
return streamer(ctx, desc, cc, method, opts...)
}

// perCallTracesAndMetrics records per call trace spans and metrics.
func (h *clientStatsHandler) perCallTracesAndMetrics(ctx context.Context, err error, startTime time.Time, ci *callInfo, ts trace.Span) {
if h.options.isTracingEnabled() {
s := status.Convert(err)
if s.Code() == grpccodes.OK {
ts.SetStatus(otelcodes.Ok, s.Message())
} else {
ts.SetStatus(otelcodes.Error, s.Message())
}
ts.End()
}
if h.options.isMetricsEnabled() {
callLatency := float64(time.Since(startTime)) / float64(time.Second)
attrs := otelmetric.WithAttributeSet(otelattribute.NewSet(
otelattribute.String("grpc.method", ci.method),
otelattribute.String("grpc.target", ci.target),
otelattribute.String("grpc.status", canonicalString(status.Code(err))),
))
h.clientMetrics.callDuration.Record(ctx, callLatency, attrs)
}
// perCallMetrics records per call metrics for both unary and stream calls.
func (h *clientMetricsHandler) perCallMetrics(ctx context.Context, err error, startTime time.Time, ci *callInfo) {
callLatency := float64(time.Since(startTime)) / float64(time.Second)
attrs := otelmetric.WithAttributeSet(otelattribute.NewSet(
otelattribute.String("grpc.method", ci.method),
otelattribute.String("grpc.target", ci.target),
otelattribute.String("grpc.status", canonicalString(status.Code(err))),
))
h.clientMetrics.callDuration.Record(ctx, callLatency, attrs)
}

// TagConn exists to satisfy stats.Handler.
func (h *clientStatsHandler) TagConn(ctx context.Context, _ *stats.ConnTagInfo) context.Context {
func (h *clientMetricsHandler) TagConn(ctx context.Context, _ *stats.ConnTagInfo) context.Context {
return ctx
}

// HandleConn exists to satisfy stats.Handler.
func (h *clientStatsHandler) HandleConn(context.Context, stats.ConnStats) {}
func (h *clientMetricsHandler) HandleConn(context.Context, stats.ConnStats) {}

// TagRPC implements per RPC attempt context management.
func (h *clientStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
// TagRPC implements per RPC attempt context management for metrics.
func (h *clientMetricsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
// Numerous stats handlers can be used for the same channel. The cluster
// impl balancer which writes to this will only write once, thus have this
// stats handler's per attempt scoped context point to the same optional
Expand All @@ -185,34 +174,34 @@
}
ctx = istats.SetLabels(ctx, labels)
}
ai := &attemptInfo{
startTime: time.Now(),
xdsLabels: labels.TelemetryLabels,
method: removeLeadingSlash(info.FullMethodName),
ri := getRPCInfo(ctx)
if ri == nil {
ri = &rpcInfo{}
}
if h.options.isTracingEnabled() {
ctx, ai = h.traceTagRPC(ctx, ai, info.NameResolutionDelay)
var ai *attemptInfo
if ri.ai == nil {
ai = &attemptInfo{}
} else {
ai = ri.ai

Check warning on line 185 in stats/opentelemetry/client_metrics.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_metrics.go#L185

Added line #L185 was not covered by tests
}
return setRPCInfo(ctx, &rpcInfo{
ai: ai,
})
ai.startTime = time.Now()
ai.xdsLabels = labels.TelemetryLabels
ai.method = removeLeadingSlash(info.FullMethodName)

return setRPCInfo(ctx, &rpcInfo{ai: ai})
}

func (h *clientStatsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
// HandleRPC handles per RPC stats implementation.
func (h *clientMetricsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
ri := getRPCInfo(ctx)
if ri == nil {
logger.Error("ctx passed into client side stats handler metrics event handling has no client attempt data present")
return
}
if h.options.isMetricsEnabled() {
h.processRPCEvent(ctx, rs, ri.ai)
}
if h.options.isTracingEnabled() {
populateSpan(rs, ri.ai)
}
h.processRPCEvent(ctx, rs, ri.ai)
}

func (h *clientStatsHandler) processRPCEvent(ctx context.Context, s stats.RPCStats, ai *attemptInfo) {
func (h *clientMetricsHandler) processRPCEvent(ctx context.Context, s stats.RPCStats, ai *attemptInfo) {
switch st := s.(type) {
case *stats.Begin:
ci := getCallInfo(ctx)
Expand Down Expand Up @@ -240,7 +229,7 @@
}
}

func (h *clientStatsHandler) setLabelsFromPluginOption(ai *attemptInfo, incomingMetadata metadata.MD) {
func (h *clientMetricsHandler) setLabelsFromPluginOption(ai *attemptInfo, incomingMetadata metadata.MD) {
if ai.pluginOptionLabels == nil && h.options.MetricsOptions.pluginOption != nil {
labels := h.options.MetricsOptions.pluginOption.GetLabels(incomingMetadata)
if labels == nil {
Expand All @@ -250,7 +239,7 @@
}
}

func (h *clientStatsHandler) processRPCEnd(ctx context.Context, ai *attemptInfo, e *stats.End) {
func (h *clientMetricsHandler) processRPCEnd(ctx context.Context, ai *attemptInfo, e *stats.End) {
ci := getCallInfo(ctx)
if ci == nil {
logger.Error("ctx passed into client side stats handler metrics event handling has no metrics data present")
Expand Down
107 changes: 101 additions & 6 deletions stats/opentelemetry/client_tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,92 @@

import (
"context"
"log"
"strings"

otelcodes "go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc"
grpccodes "google.golang.org/grpc/codes"
"google.golang.org/grpc/stats"
otelinternaltracing "google.golang.org/grpc/stats/opentelemetry/internal/tracing"
"google.golang.org/grpc/status"
)

const (
delayedResolutionEventName = "Delayed name resolution complete"
tracerName = "grpc-go"
)

type clientTracingHandler struct {
options Options
}

func (h *clientTracingHandler) initializeTraces() {
if h.options.TraceOptions.TracerProvider == nil {
log.Printf("TracerProvider is not provided in client TraceOptions")
return
}

Check warning on line 46 in stats/opentelemetry/client_tracing.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_tracing.go#L44-L46

Added lines #L44 - L46 were not covered by tests
}

func (h *clientTracingHandler) unaryInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ci := getCallInfo(ctx)
if ci == nil {
if logger.V(2) {
logger.Info("Creating new CallInfo since its not present in context in clientTracingHandler unaryInterceptor")
}
ci = &callInfo{
target: cc.CanonicalTarget(),
method: determineMethod(method, opts...),
}
ctx = setCallInfo(ctx, ci)

Check warning on line 59 in stats/opentelemetry/client_tracing.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_tracing.go#L52-L59

Added lines #L52 - L59 were not covered by tests
}

var span trace.Span
ctx, span = h.createCallTraceSpan(ctx, method)
err := invoker(ctx, method, req, reply, cc, opts...)
h.finishTrace(err, span)
return err
}

func (h *clientTracingHandler) streamInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
ci := getCallInfo(ctx)
if ci == nil {
if logger.V(2) {
logger.Info("Creating new CallInfo since its not present in context in clientTracingHandler streamInterceptor")
}
ci = &callInfo{
target: cc.CanonicalTarget(),
method: determineMethod(method, opts...),
}
ctx = setCallInfo(ctx, ci)

Check warning on line 79 in stats/opentelemetry/client_tracing.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_tracing.go#L72-L79

Added lines #L72 - L79 were not covered by tests
}

var span trace.Span
ctx, span = h.createCallTraceSpan(ctx, method)
callback := func(err error) { h.finishTrace(err, span) }
opts = append([]grpc.CallOption{grpc.OnFinish(callback)}, opts...)
return streamer(ctx, desc, cc, method, opts...)
}

// finishTrace sets the span status based on the RPC result and ends the span.
// It is used to finalize tracing for both unary and streaming calls.
func (h *clientTracingHandler) finishTrace(err error, ts trace.Span) {
s := status.Convert(err)
if s.Code() == grpccodes.OK {
ts.SetStatus(otelcodes.Ok, s.Message())
} else {
ts.SetStatus(otelcodes.Error, s.Message())
}
ts.End()
}

// traceTagRPC populates provided context with a new span using the
// TextMapPropagator supplied in trace options and internal itracing.carrier.
// It creates a new outgoing carrier which serializes information about this
// span into gRPC Metadata, if TextMapPropagator is provided in the trace
// options. if TextMapPropagator is not provided, it returns the context as is.
func (h *clientStatsHandler) traceTagRPC(ctx context.Context, ai *attemptInfo, nameResolutionDelayed bool) (context.Context, *attemptInfo) {
func (h *clientTracingHandler) traceTagRPC(ctx context.Context, ai *attemptInfo, nameResolutionDelayed bool) (context.Context, *attemptInfo) {
// Add a "Delayed name resolution complete" event to the call span
// if there was name resolution delay. In case of multiple retry attempts,
// ensure that event is added only once.
Expand All @@ -55,13 +123,40 @@

// createCallTraceSpan creates a call span to put in the provided context using
// provided TraceProvider. If TraceProvider is nil, it returns context as is.
func (h *clientStatsHandler) createCallTraceSpan(ctx context.Context, method string) (context.Context, trace.Span) {
if h.options.TraceOptions.TracerProvider == nil {
logger.Error("TraceProvider is not provided in trace options")
return ctx, nil
}
func (h *clientTracingHandler) createCallTraceSpan(ctx context.Context, method string) (context.Context, trace.Span) {
mn := strings.Replace(removeLeadingSlash(method), "/", ".", -1)
tracer := h.options.TraceOptions.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(grpc.Version))
ctx, span := tracer.Start(ctx, mn, trace.WithSpanKind(trace.SpanKindClient))
return ctx, span
}

// TagConn exists to satisfy stats.Handler for tracing.
func (h *clientTracingHandler) TagConn(ctx context.Context, _ *stats.ConnTagInfo) context.Context {
return ctx
}

// HandleConn exists to satisfy stats.Handler for tracing.
func (h *clientTracingHandler) HandleConn(context.Context, stats.ConnStats) {}

// TagRPC implements per RPC attempt context management for traces.
func (h *clientTracingHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
ri := getRPCInfo(ctx)
var ai *attemptInfo
if ri == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

ai = &attemptInfo{}

Check warning on line 146 in stats/opentelemetry/client_tracing.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_tracing.go#L146

Added line #L146 was not covered by tests
} else {
ai = ri.ai
}
ctx, ai = h.traceTagRPC(ctx, ai, info.NameResolutionDelay)
return setRPCInfo(ctx, &rpcInfo{ai: ai})
}

// HandleRPC handles per RPC tracing implementation.
func (h *clientTracingHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
ri := getRPCInfo(ctx)
if ri == nil {
logger.Error("ctx passed into client side tracing handler trace event handling has no client attempt data present")
return
}

Check warning on line 160 in stats/opentelemetry/client_tracing.go

View check run for this annotation

Codecov / codecov/patch

stats/opentelemetry/client_tracing.go#L158-L160

Added lines #L158 - L160 were not covered by tests
populateSpan(rs, ri.ai)
}
4 changes: 2 additions & 2 deletions stats/opentelemetry/metricsregistry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ type metricsRecorderForTest interface {
}

func newClientStatsHandler(options MetricsOptions) metricsRecorderForTest {
return &clientStatsHandler{options: Options{MetricsOptions: options}}
return &clientMetricsHandler{options: Options{MetricsOptions: options}}
}

func newServerStatsHandler(options MetricsOptions) metricsRecorderForTest {
return &serverStatsHandler{options: Options{MetricsOptions: options}}
return &serverMetricsHandler{options: Options{MetricsOptions: options}}
}

// TestMetricsRegistryMetrics tests the OpenTelemetry behavior with respect to
Expand Down
Loading
Loading