Skip to content
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

Add ability to extend HttpTraceWebFilter (e.g. to include req/resp body) #23907

Closed
gberche-orange opened this issue Oct 26, 2020 · 4 comments
Closed
Assignees
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@gberche-orange
Copy link

gberche-orange commented Oct 26, 2020

Expected behavior

As a springboot user

Current behavior

While a custom implementation of HttpTraceWebFilter can be injected thanks to

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.REACTIVE)
static class ReactiveTraceFilterConfiguration {
@Bean
@ConditionalOnMissingBean
HttpTraceWebFilter httpTraceWebFilter(HttpTraceRepository repository, HttpExchangeTracer tracer,
HttpTraceProperties traceProperties) {
return new HttpTraceWebFilter(repository, tracer, traceProperties.getInclude());
}

it requires the following workarounds:

  • the custom HttpTraceWebFilter class needs to extend HttpTraceWebFilter

  • the ServerWebExchangeTraceableRequest and TraceableServerHttpResponse objects can't be injected as beans and are instead hard coded

  • the ServerWebExchangeTraceableRequest and TraceableServerHttpResponse classes are package protected preventing them from being subclassed to enrich their behavior.


  • finally, the request is inserted into the tracer synchronously when the filter is invoked. This prevents other filters (such as spring cloud gateway filters capturing request body) for executing before. There is a need to insert the request into the tracer as a response precommit step (along with the response).

private Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain, Principal principal,
WebSession session) {
ServerWebExchangeTraceableRequest request = new ServerWebExchangeTraceableRequest(exchange);
HttpTrace trace = this.tracer.receivedRequest(request);
exchange.getResponse().beforeCommit(() -> {
TraceableServerHttpResponse response = new TraceableServerHttpResponse(exchange.getResponse());
this.tracer.sendingResponse(trace, response, () -> principal, () -> getStartedSessionId(session));
this.repository.add(trace);
return Mono.empty();
});
return chain.filter(exchange);
}

Here is the full resulting duplicated webfilter along with associated spring cloud gateway configuration https://gist.github.com/gberche-orange/06c26477a313df9d19d20a4e115f079f that injects request and response bodies as respectively request_body and response_body http headers

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 26, 2020
@wilkinsona
Copy link
Member

The scope of HTTP tracing was deliberately narrowed and locked down in 2.0 so that both the repository that stores the traces and the endpoint that returns them would have predictable data to deal with. Opening up the API as you have suggested will remove the predictability which is something that I don't think we want to do. I'm also not keen on opening things up to record request and response bodies as doing so is generally not recommended as it requires buffering the entire body in memory. This is only my opinion so I'll mark this one for team attention to see what the rest of the team thinks.

As we mention in the documentation, if your needs have outgrown the capabilities of the built-in HTTP tracing they may be better served by using something like Zipkin or Spring Cloud Sleuth.

@wilkinsona wilkinsona added the for: team-attention An issue we'd like other members of the team to review label Oct 27, 2020
@gberche-orange
Copy link
Author

@wilkinsona thanks for your response.

As we mention in the documentation, if your needs have outgrown the capabilities of the built-in HTTP tracing they may be better served by using something like Zipkin or Spring Cloud Sleuth.

yes, I had noticed the mention and have investigated this approach, however the requirement to trace http request/response bodies is not supported either brave and zipkin and likely to be even more complex

See https://gitter.im/openzipkin/zipkin?at=5ca0156693fb4a7dc2a9e791 march 2019

@kirenjolly right now we don't expose getting the http body generically.
We probably should add a comment to that file as to why. Not only does this likely result in things too big to put into a span, but also it can cause problems in your production requests. For example, not all http bodies are replayable.. ex if it is a stream and we consume it, the app couldn't.
you can ask here about "blob service" which is what @jcchavezs was referring to.

Brave seems to abstract out the http client and server and hide away the ServerWebExchange, see https://github.com/openzipkin/brave/tree/master/instrumentation/http#span-data-policy

 By default, the following are added to both http client and server spans:
     Span.name is the http method in lowercase: ex "get" or a route described below
     Tags:
         "http.method", eg "GET"
         "http.path", which does not include query parameters.
         "http.status_code" when the status is not success.
         "error", when there is an exception or status is >=400
     Remote IP and port information

Logging req/resp body in brave would possibly require

the repository that stores the traces and the endpoint that returns them would have predictable data to deal with. Opening up the API as you have suggested will remove the predictability which is something that I don't think we want to do.

I do agree that blindly adding request and response body to the actuator httptracing regardless of served traffic will impact predictability and isn't a desired goal for a general purpose usage.

My specific use-case is a reverse proxy based on spring-cloud-gateway, proxifying low traffic and small API requests/responses where inspection of proxied traffic is necessary. The side effect on memory (denial of service or predictability) is also mitigated by abbreviating the recorded bodies and removing them from the exchange attributes (as to favor GC).

Maybe there is room to support users in http tracing extensions for such specific use-cases.

@philwebb philwebb removed the for: team-attention An issue we'd like other members of the team to review label Oct 28, 2020
@wilkinsona
Copy link
Member

We've discussed this today and the team agreed that we don't want to increase the surface area of the public API to support this use case. Our recommendation is that you maintain your own copy of the current code, modified to suit your specific needs. Thanks anyway for the suggestion.

@wilkinsona wilkinsona added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 28, 2020
@gberche-orange
Copy link
Author

thanks for your response and for having considering the suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

4 participants