-
Notifications
You must be signed in to change notification settings - Fork 8
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
feat: update filter interface to process only based on spans #223
Changes from all commits
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 |
---|---|---|
|
@@ -2,9 +2,7 @@ package http // import "github.com/hypertrace/goagent/sdk/instrumentation/net/ht | |
|
||
import ( | ||
"bytes" | ||
"encoding/base64" | ||
"io" | ||
"io/ioutil" | ||
"net/http" | ||
|
||
config "github.com/hypertrace/agent-config/gen/go/v1" | ||
|
@@ -72,23 +70,15 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
host := r.Host | ||
span.SetAttribute("http.request.header.host", host) | ||
|
||
headers := r.Header | ||
// Sets an attribute per each request header. | ||
if h.dataCaptureConfig.HttpHeaders.Request.Value { | ||
SetAttributesFromHeaders("request", NewHeaderMapAccessor(r.Header), span) | ||
} | ||
|
||
// run filters on headers | ||
filterResult := h.filter.EvaluateURLAndHeaders(span, url, headers) | ||
if filterResult.Block { | ||
w.WriteHeader(int(filterResult.ResponseStatusCode)) | ||
return | ||
} | ||
|
||
// nil check for body is important as this block turns the body into another | ||
// object that isn't nil and that will leverage the "Observer effect". | ||
if r.Body != nil && h.dataCaptureConfig.HttpBody.Request.Value && ShouldRecordBodyOfContentType(headerMapAccessor{r.Header}) { | ||
body, err := ioutil.ReadAll(r.Body) | ||
body, err := io.ReadAll(r.Body) | ||
if err != nil { | ||
return | ||
} | ||
|
@@ -103,25 +93,14 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
isMultipartFormDataBody) | ||
} | ||
|
||
processingBody := body | ||
if int(h.dataCaptureConfig.BodyMaxProcessingSizeBytes.Value) < len(body) { | ||
processingBody = body[:h.dataCaptureConfig.BodyMaxProcessingSizeBytes.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.
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. Yes, I'm ok with that. 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. Can you help open a ticket to deprecate body max processing size throughout? Thanks! 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. |
||
} | ||
// if body is multipart/form-data, base64 encode it before passing it on to the filter | ||
if isMultipartFormDataBody { | ||
origProcessingBody := processingBody | ||
processingBody = make([]byte, base64.RawStdEncoding.EncodedLen(len(origProcessingBody))) | ||
base64.RawStdEncoding.Encode(processingBody, origProcessingBody) | ||
} | ||
|
||
// run body filters | ||
filterResult := h.filter.EvaluateBody(span, processingBody, headers) | ||
if filterResult.Block { | ||
w.WriteHeader(int(filterResult.ResponseStatusCode)) | ||
return | ||
} | ||
r.Body = io.NopCloser(bytes.NewBuffer(body)) | ||
} | ||
|
||
r.Body = ioutil.NopCloser(bytes.NewBuffer(body)) | ||
// single evaluation call to filter after capturing the configured parameters | ||
filterResult := h.filter.Evaluate(span) | ||
if filterResult.Block { | ||
w.WriteHeader(int(filterResult.ResponseStatusCode)) | ||
return | ||
} | ||
|
||
// create http.ResponseWriter interceptor for tracking status code | ||
|
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.
@ryanericson @puneet-traceable @tim-mwangi This reordering was required because we now only have a single method in filter interface and the scenario of blocking based on headers was failing since the only call to filter was done on body first.
I think we should make similar changes to all instrumentations so that our issue of allow rule not taking precedence over blocking rules also will be solved.
Or we can pass flowvariable to
Evaluate
method to specify if we're calling for header eval or body evalThere 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.
So libtraceable interface only has one method called
Evaluate
now? Do the conditions that had it split up into various methods no longer apply?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.
Yes, libtraceable interface has only one method
Evaluate
now.This I'm not really sure. I looked through the code and couldn't find any reason why we had separate calls (maybe for consistency across agents). In both the cases we call the delegate after the body capture. I'll test with actual apps over the weekend.
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.
@tim-mwangi I tested with both a
net/http
app and and agrpc
app, both of them are blocking with and w/o body, testing the remaining instrumentations as well