-
Notifications
You must be signed in to change notification settings - Fork 30
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
[SLT-331] feat(omnirpc): omnirpc request tracing #3289
base: master
Are you sure you want to change the base?
Changes from 7 commits
305dde4
275dfaa
fc96c21
81a732e
9055ff6
54eacfa
151d6cd
ad40ff4
7eb7448
fc15e54
cf9763f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,21 +3,26 @@ package http | |||||||||||||||||||||||
import ( | ||||||||||||||||||||||||
"context" | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
"github.com/ethereum/go-ethereum/common" | ||||||||||||||||||||||||
"github.com/synapsecns/sanguine/core/bytemap" | ||||||||||||||||||||||||
"github.com/synapsecns/sanguine/core/metrics" | ||||||||||||||||||||||||
"go.opentelemetry.io/otel/attribute" | ||||||||||||||||||||||||
"go.opentelemetry.io/otel/trace" | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// CaptureClient is a mock client used for checking response values. | ||||||||||||||||||||||||
type CaptureClient struct { | ||||||||||||||||||||||||
requests []*CapturedRequest | ||||||||||||||||||||||||
responseFunc MakeResponseFunc | ||||||||||||||||||||||||
handler metrics.Handler | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// MakeResponseFunc is used for mocking responses. | ||||||||||||||||||||||||
type MakeResponseFunc func(c *CapturedRequest) (Response, error) | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// NewCaptureClient creates anew client for testing. | ||||||||||||||||||||||||
func NewCaptureClient(responseFunc MakeResponseFunc) *CaptureClient { | ||||||||||||||||||||||||
return &CaptureClient{requests: []*CapturedRequest{}, responseFunc: responseFunc} | ||||||||||||||||||||||||
func NewCaptureClient(handler metrics.Handler, responseFunc MakeResponseFunc) *CaptureClient { | ||||||||||||||||||||||||
return &CaptureClient{requests: []*CapturedRequest{}, responseFunc: responseFunc, handler: handler} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// Requests turns a list of sent requests. These are not mutation safe. | ||||||||||||||||||||||||
|
@@ -30,6 +35,7 @@ func (c *CaptureClient) NewRequest() Request { | |||||||||||||||||||||||
request := CapturedRequest{ | ||||||||||||||||||||||||
Client: c, | ||||||||||||||||||||||||
StringHeaders: make(map[string]string), | ||||||||||||||||||||||||
Handler: c.handler, | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
c.requests = append(c.requests, &request) | ||||||||||||||||||||||||
return &request | ||||||||||||||||||||||||
|
@@ -56,44 +62,102 @@ type CapturedRequest struct { | |||||||||||||||||||||||
// RequestURIBytes is the request uri bytes. Notably, this will not include | ||||||||||||||||||||||||
// RequestURI's set by SetRequestURI | ||||||||||||||||||||||||
RequestURIBytes []byte | ||||||||||||||||||||||||
// Metrics is the metrics handler | ||||||||||||||||||||||||
Handler metrics.Handler | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
var _ Client = &CaptureClient{} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// SetBody stores the body for testing. | ||||||||||||||||||||||||
func (c *CapturedRequest) SetBody(body []byte) Request { | ||||||||||||||||||||||||
_, span := c.Handler.Tracer().Start( | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i wouldn't do this here. I'd have a single trace around when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||||||||||||||||
c.Context, | ||||||||||||||||||||||||
"SetBody", | ||||||||||||||||||||||||
trace.WithAttributes(attribute.String("SetBody", common.Bytes2Hex(body))), | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
defer func() { | ||||||||||||||||||||||||
metrics.EndSpan(span) | ||||||||||||||||||||||||
}() | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle potential nil references for In the methods Consider adding a nil check at the beginning of each method: + if c.Handler == nil {
+ // Handle nil Handler appropriately, e.g., initialize it or return an error.
+ return c
+ } Alternatively, ensure that Also applies to: 99-107, 114-122, 129-136, 143-159 Ensure In methods like Initialize // During CapturedRequest initialization
CapturedRequest{
Client: c,
StringHeaders: make(map[string]string),
+ Context: context.Background(),
} Alternatively, check for nil and initialize within each method: + if c.Context == nil {
+ c.Context = context.Background()
+ } Also applies to: 99-107, 114-122, 129-136, 143-159 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential nil dereference of In the Consider initializing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure 'Handler' is not nil before usage to prevent nil pointer dereference In the methods Consider initializing func (c *CaptureClient) NewRequest() Request {
request := CapturedRequest{
Client: c,
StringHeaders: make(map[string]string),
+ Handler: metrics.NoopHandler(),
}
c.requests = append(c.requests, &request)
return &request
} Alternatively, add nil checks before using if c.Handler != nil {
// Proceed to start the span
} else {
// Handle the case where Handler is nil, possibly by initializing it or skipping tracing
} Also applies to: 85-92, 99-107, 114-122, 129-136, 143-149 |
||||||||||||||||||||||||
c.Body = body | ||||||||||||||||||||||||
return c | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// SetContext stores the context for testing. | ||||||||||||||||||||||||
func (c *CapturedRequest) SetContext(ctx context.Context) Request { | ||||||||||||||||||||||||
_, span := c.Handler.Tracer().Start( | ||||||||||||||||||||||||
ctx, | ||||||||||||||||||||||||
"SetContext", | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
span.AddEvent("SetContext") | ||||||||||||||||||||||||
defer func() { | ||||||||||||||||||||||||
metrics.EndSpan(span) | ||||||||||||||||||||||||
}() | ||||||||||||||||||||||||
c.Context = ctx | ||||||||||||||||||||||||
return c | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// SetHeader sets the header for testing. | ||||||||||||||||||||||||
func (c *CapturedRequest) SetHeader(key, value string) Request { | ||||||||||||||||||||||||
_, span := c.Handler.Tracer().Start( | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see above |
||||||||||||||||||||||||
c.Context, | ||||||||||||||||||||||||
"SetHeader", | ||||||||||||||||||||||||
trace.WithAttributes(attribute.String("SetHeader", key)), | ||||||||||||||||||||||||
trace.WithAttributes(attribute.String("value", value)), | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Combine multiple attributes into a single In the Combine all attributes into a single _, span := c.Handler.Tracer().Start(
c.Context,
"SetHeader",
- trace.WithAttributes(attribute.String("SetHeader", key)),
- trace.WithAttributes(attribute.String("value", value)),
+ trace.WithAttributes(
+ attribute.String("SetHeader", key),
+ attribute.String("value", value),
+ ),
) This applies to similar cases in other methods as well. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||
defer func() { | ||||||||||||||||||||||||
metrics.EndSpan(span) | ||||||||||||||||||||||||
}() | ||||||||||||||||||||||||
c.StringHeaders[key] = value | ||||||||||||||||||||||||
return c | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// SetHeaderBytes sets header bytes for testing. | ||||||||||||||||||||||||
func (c *CapturedRequest) SetHeaderBytes(key, value []byte) Request { | ||||||||||||||||||||||||
_, span := c.Handler.Tracer().Start( | ||||||||||||||||||||||||
c.Context, | ||||||||||||||||||||||||
"SetHeaderBytes", | ||||||||||||||||||||||||
trace.WithAttributes(attribute.String("key", common.Bytes2Hex(key))), | ||||||||||||||||||||||||
trace.WithAttributes(attribute.String("value", common.Bytes2Hex(value))), | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
defer func() { | ||||||||||||||||||||||||
metrics.EndSpan(span) | ||||||||||||||||||||||||
}() | ||||||||||||||||||||||||
c.ByteHeaders.Put(key, value) | ||||||||||||||||||||||||
return c | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// SetRequestURI stores the request uri. | ||||||||||||||||||||||||
func (c *CapturedRequest) SetRequestURI(uri string) Request { | ||||||||||||||||||||||||
_, span := c.Handler.Tracer().Start( | ||||||||||||||||||||||||
c.Context, | ||||||||||||||||||||||||
"SetRequestURI", | ||||||||||||||||||||||||
trace.WithAttributes(attribute.String("uri", uri)), | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
defer func() { | ||||||||||||||||||||||||
metrics.EndSpan(span) | ||||||||||||||||||||||||
}() | ||||||||||||||||||||||||
c.RequestURI = uri | ||||||||||||||||||||||||
return c | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// Do calls responseFunc for testing. | ||||||||||||||||||||||||
func (c *CapturedRequest) Do() (Response, error) { | ||||||||||||||||||||||||
//nolint: wrapcheck | ||||||||||||||||||||||||
return c.Client.responseFunc(c) | ||||||||||||||||||||||||
_, span := c.Handler.Tracer().Start( | ||||||||||||||||||||||||
c.Context, | ||||||||||||||||||||||||
"Do", | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
defer func() { | ||||||||||||||||||||||||
metrics.EndSpan(span) | ||||||||||||||||||||||||
}() | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
resp, err := c.Client.responseFunc(c) | ||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||
return nil, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
span.SetAttributes(attribute.String("response", common.Bytes2Hex(resp.Body()))) | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle potential nil response body in 'Do' method In the Apply this diff: - span.SetAttributes(attribute.String("response", common.Bytes2Hex(resp.Body())))
+ if resp != nil && resp.Body() != nil {
+ span.SetAttributes(attribute.String("response", common.Bytes2Hex(resp.Body())))
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||
return resp, err | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
var _ Request = &CapturedRequest{} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ package http | |
import ( | ||
"context" | ||
"strings" | ||
|
||
"github.com/synapsecns/sanguine/core/metrics" | ||
) | ||
|
||
// Client contains a post client for interacting with json rpc servers. | ||
|
@@ -62,14 +64,14 @@ func init() { | |
|
||
// NewClient creates a client from the client type | ||
// defaults to fast http. | ||
func NewClient(clientType ClientType) Client { | ||
func NewClient(handler metrics.Handler, clientType ClientType) Client { | ||
switch clientType { | ||
case FastHTTP: | ||
return NewFastHTTPClient() | ||
return NewFastHTTPClient(handler) | ||
case Resty: | ||
return NewRestyClient() | ||
return NewRestyClient(handler) | ||
default: | ||
return NewRestyClient() | ||
return NewRestyClient(handler) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle unknown In the
Comment on lines
+67
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Action Required: Update Several instances of
Please ensure that each 🔗 Analysis chainEnsure all call sites of The Run the following script to find all usages of 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Find all call sites of NewClient that need to be updated.
# Search for usage of 'NewClient(' in Go files
rg --type go 'NewClient\('
Length of output: 5031 Script: #!/bin/bash
# Description: Find all call sites of NewClient that do not include the handler parameter.
# Search for 'NewClient(' in Go files with fewer than expected arguments
rg --type go 'NewClient\s*\(\s*(?!handler\s*,).*?\)'
Length of output: 312 Script: #!/bin/bash
# Description: Find all call sites of NewClient that include only one argument.
# Search for 'NewClient(' in Go files with only one argument
rg --type go 'NewClient\s*\(\s*[^,()]+\s*\)'
Length of output: 990 |
||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enforce the association of
metrics.Handler
withCapturedRequest
.To prevent issues with uninitialized
c.Handler
, consider requiring themetrics.Handler
to be set during the creation ofCapturedRequest
instances.Modify the
NewRequest
method to accept ametrics.Handler
parameter:This ensures that every
CapturedRequest
has a validHandler
andContext
from the beginning.Also applies to: 161-164