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

Merged
merged 67 commits into from
May 5, 2025

Conversation

janardhanvissa
Copy link
Contributor

@janardhanvissa janardhanvissa commented Feb 3, 2025

RELEASE NOTES: None

Copy link

codecov bot commented Feb 3, 2025

Codecov Report

Attention: Patch coverage is 87.66234% with 19 lines in your changes missing coverage. Please review.

Project coverage is 82.18%. Comparing base (eb4b687) to head (f4b4fd6).
Report is 20 commits behind head on master.

Files with missing lines Patch % Lines
stats/opentelemetry/client_tracing.go 82.22% 6 Missing and 2 partials ⚠️
stats/opentelemetry/server_tracing.go 60.00% 6 Missing and 2 partials ⚠️
stats/opentelemetry/client_metrics.go 93.87% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8063      +/-   ##
==========================================
+ Coverage   81.96%   82.18%   +0.22%     
==========================================
  Files         412      419       +7     
  Lines       40491    41898    +1407     
==========================================
+ Hits        33188    34435    +1247     
- Misses       5915     5998      +83     
- Partials     1388     1465      +77     
Files with missing lines Coverage Δ
stats/opentelemetry/opentelemetry.go 77.90% <100.00%> (+2.90%) ⬆️
stats/opentelemetry/server_metrics.go 87.26% <100.00%> (-2.56%) ⬇️
stats/opentelemetry/client_metrics.go 85.08% <93.87%> (-4.32%) ⬇️
stats/opentelemetry/client_tracing.go 87.50% <82.22%> (+3.50%) ⬆️
stats/opentelemetry/server_tracing.go 73.33% <60.00%> (-26.67%) ⬇️

... and 73 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@janardhanvissa janardhanvissa force-pushed the refactor-tracing-metrics branch from 69df069 to 71804b4 Compare February 3, 2025 11:48
@purnesh42H
Copy link
Contributor

@janardhanvissa its not clear what is the intention of this refactor. The follow up from opentelemetry tracing API PR was to create separate interceptors for metrics and traces. Right now, single interceptor is handling both trace and metrics options. Once we have separate unary and stream interceptor each for tracing and metrics, we don't have to check for options disabled/enabled everytime.

Copy link
Contributor

@purnesh42H purnesh42H left a comment

Choose a reason for hiding this comment

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

Please see this discussion https://github.com/grpc/grpc-go/pull/7852/files#r1909469701 and modify accordingly.

@dfawley dfawley removed their assignment Mar 28, 2025
@@ -130,7 +130,7 @@ func (h *clientTracingHandler) HandleConn(context.Context, stats.ConnStats) {}
func (h *clientTracingHandler) TagRPC(ctx context.Context, _ *stats.RPCTagInfo) context.Context {
ri := getRPCInfo(ctx)
var ai *attemptInfo
if ri == nil {
if ri.ai == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think here also we can't assume ri is not nil if the order of stats handlers changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

metricsHandler := &clientMetricsHandler{options: o}
metricsHandler.initializeMetrics()
unaryInterceptors = append(unaryInterceptors, metricsHandler.unaryInterceptor)
streamInterceptors = append(streamInterceptors, metricsHandler.streamInterceptor)
Copy link
Contributor

Choose a reason for hiding this comment

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

this is changing the current order. Let's avoid that. Keep only 2 variables metricsInterceptors and tracesInterceptors and add metricsInterceptors before traces

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

streamInterceptors = append(streamInterceptors, tracingHandler.streamInterceptor)
do = append(do, grpc.WithStatsHandler(tracingHandler))
}
if len(unaryInterceptors) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

these ifs will change to metrics and traces

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

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

Choose a reason for hiding this comment

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

same here. We can't assume ri to be not nil here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@janardhanvissa janardhanvissa removed their assignment Apr 4, 2025
@janardhanvissa janardhanvissa requested a review from dfawley April 4, 2025 23:51
Comment on lines 181 to 185
var ai *attemptInfo
if ri.ai == nil {
ai = &attemptInfo{}
} else {
ai = ri.ai
Copy link
Member

Choose a reason for hiding this comment

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

Go style:

Suggested change
var ai *attemptInfo
if ri.ai == nil {
ai = &attemptInfo{}
} else {
ai = ri.ai
ai := ri.ai
if ai == nil {
ai = &attemptInfo{}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 71 to 81
ci := getCallInfo(ctx)
if ci == nil {
if logger.V(2) {
logger.Info("Creating new CallInfo since its not present in context in clientStatsHandler unaryInterceptor")
}
ci = &callInfo{
target: cc.CanonicalTarget(),
method: determineMethod(method, opts...),
}
ctx = setCallInfo(ctx, ci)
}
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.

Comment on lines 178 to 180
var ai *attemptInfo
if ri == nil {
ai = &attemptInfo{}
Copy link
Member

Choose a reason for hiding this comment

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

So this is the same as the interceptor call info thing?

Then similar: can we have a single function that does this, and is called from both TagRPC implementations?

@dfawley dfawley assigned janardhanvissa and unassigned dfawley Apr 16, 2025
@janardhanvissa janardhanvissa requested a review from dfawley April 17, 2025 21:05
@janardhanvissa janardhanvissa removed their assignment Apr 24, 2025
Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

LGTM except for the changes mentioned.

Comment on lines 160 to 166
if ri == nil {
ri = &rpcInfo{}
}
ai := ri.ai
if ai == nil {
ai = &attemptInfo{}
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if ri == nil {
ri = &rpcInfo{}
}
ai := ri.ai
if ai == nil {
ai = &attemptInfo{}
}
if ri == nil {
ri = &rpcInfo{ai: &attemptInfo{}}
}

Does this not work?

if ai == nil {
ai = &attemptInfo{}
}
return setRPCInfo(ctx, &rpcInfo{ai: ai}), ai
Copy link
Member

Choose a reason for hiding this comment

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

This is adding it into the context a second time if it's already in there.

I think you want something more like:

	ri := getRPCInfo(ctx)
	if ri != nil {
		return ctx, ri.ai
	}
	ri := &rpcInfo{ai: &attemptInfo{}}
	return setRPCInfo(ctx, ri), ri.ai

@dfawley dfawley assigned purnesh42H and janardhanvissa and unassigned dfawley May 2, 2025
@purnesh42H purnesh42H merged commit d2f02e5 into grpc:master May 5, 2025
15 checks passed
purnesh42H pushed a commit to purnesh42H/grpc-go that referenced this pull request May 8, 2025
vinothkumarr227 pushed a commit to vinothkumarr227/grpc-go that referenced this pull request May 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Observability Includes Stats, Tracing, Channelz, Healthz, Binlog, Reflection, Admin, GCP Observability Type: Internal Cleanup Refactors, etc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants