-
Notifications
You must be signed in to change notification settings - Fork 351
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
allow tagFilter to use response data #2607
allow tagFilter to use response data #2607
Conversation
2de97b1
to
2e2f52e
Compare
Looks like it attempts to fix #2316 |
This change introduces a new filter tracingTagOnResponse that works just like the tracingTag filter, but is applied only after ther request has been processed. This allows using properties of the response (a header value) in the tag. The use case for this is that users might want to consider an operation as failed even if it technically succeeds, e.g. because fallbacks were used. With this change, a response header can be sent, e.g. `"X-Fallback": "true"`, and then the filter `tracingTag("error", "${response.header.X-Fallback}")` would result in the span being marked as error. Another use cases could be that metrics should be captured by use case, but the use case is not apparent from the request and instead only defined by the result of the request processing. Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
2e2f52e
to
02a0c6d
Compare
In the test, the span tag was obtained before the response filter method was executed, resulting in no tags being found. This commit moves obtaining the tags to after the incovaction of the response filter method. Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
c518803
to
40a2214
Compare
You also need to register the spec into the builtins https://github.com/zalando/skipper/blob/master/filters/builtin/builtin.go#L210 to make it available for use in skipper. |
Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com> response
02c8a60
to
10ba4b6
Compare
@szuecs Thanks for your review. I addressed your comments. |
Only one tiny nit and it's ready to merge, thanks |
Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
Looks ok, couple of ideas. Since the filter matches 99% with existing you could also add a flag like here https://github.com/zalando/skipper/blob/master/filters/diag/histogram.go
Should we name it |
@AlexanderYastrebov yeah makes sense to have "typ" like in https://github.com/zalando/skipper/blob/master/filters/diag/histogram.go#L39 and check in Request/Response https://github.com/zalando/skipper/blob/master/filters/diag/histogram.go#L104. |
@AlexanderYastrebov @szuecs I'll try to implement it like that. |
This commit refactors the tracingTagOnResponse filter to use the same class as the tracingTag filter. It follows the same pattern as histogram.go. Also, the filter is renamed to tracingTagFromResponse and the documentation simplified. Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
👍 |
filters/tracing/tag_test.go
Outdated
}) | ||
} | ||
} | ||
|
||
func TestTagFilterIgnoresResponse(t *testing.T) { |
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.
I think this could be a test case in the TestTracingTag
{
"tag ignores response",
NewTag(),
"${response.header.X-Fallback}",
&filtertest.Context{
FRequest: &http.Request{
Header: http.Header{
"X-Fallback": []string{"true"},
},
},
},
"",
}
and likely we need the symmetric that NewTagFromResponse ignores request.
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.
Not sure about this. Wouldn't the header in the request only match "${request.header.X-Fallback}"
, not the provided template for the response? So in any case the result would be nil
, right?
My reasoning was that we need to have a case where a header is only present in the response, not in the request.
Will add a test for the symmetrical case, though.
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.
Sorry, I meant to use FResponse of course, i.e. filter is NewTag but template is "${response.header.X-Fallback}"
and X-Fallback
is a response header
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.
This does not really work because the context is only created once in the test and is the same for the whole duration of the test. This means that the response header is already present at request time. To replicate the real behavior, we have to provide a different context for the f.Response
call than for the f.Request
call, where the header was added. This cannot be done within the structure of this test.
I could generalize the template to provide both a context at request time and one at response time. But this seems a bit overkill to me given that it is a global construct.
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.
We can have request
and response
fields in the test cases instead of context
, create context at the start of the test and set response after f.Request(ctx) but before f.Response(ctx):
ctx := &filtertest.Context{
FRequest: ti.request,
}
...
f.Request(ctx)
ctx.FResponse = ti.response
f.Response(ctx)
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.
This works for a test that show tracingTag
only runs on the request. It does not work for the symmetric case to test that tracingTagFromResponse
only runs on the response. To prove this, the request in the context has to be changed (header removed) to prove that tracingTagFromResponse
cannot make use of headers that are only present at request time. It is a bit artificial anyway.
Would you prefer to just have one test according to the method you described, or separate tests as they are now? Or a different change?
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.
Alternatively, I could change the test code to reset the context to blank after the request call. But this would also be a bit strange, because in a real scenario the request context would be available also at response time, if I understand it correctly.
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.
Lets have a single additional test case then.
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.
In the additional test you can also have a real backend httptest.Server to create the response header to test it.
Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
Signed-off-by: lukas-c-wilhelm <11819719+lukas-c-wilhelm@users.noreply.github.com>
👍 |
@lukas-c-wilhelm Thank you for your contribution. |
👍 |
Fixes #2316
This change introduces a new filter
tracingTagOnResponse
that works just like the tracingTag filter, but is applied only after ther request has been processed. This allows using properties of the response (a header value) in the tag.The use case for this is that users might want to consider an operation as failed even if it technically succeeds, e.g. because fallbacks were used. With this change, a response header can be sent, e.g.
"X-Fallback": "true"
, and then the filtertracingTagOnResponse("error", "${response.header.X-Fallback}")
would result in the span being marked as error.Another use cases could be that metrics should be captured by use case, but the use case is not apparent from the request and instead only defined by the result of the request processing.