-
Notifications
You must be signed in to change notification settings - Fork 10.1k
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
Efficient telemetry for requests that are rejected at Kestrel layer. #33949
Comments
This feature would be useful for multiple services. Having visibility in the logs pipeline to requests that are rejected by Kestrel, is very important for telemetry, debuggability and diagnostics. While migrating to Kestrel, we found a few regressions (e.g. headers unsupported encoding) that were not detected ahead of time because there were no signs of them in the logs. |
Do you want an EventSource event(s), specific log event(s) (or category) or something else? Would we want events for anything that looks like requests but don't get to middleware for whatever reason (e.g. invalid host header, unexpected character when parsing, etc...)? Do you want something specific for just invalid host headers? We do currently have the ConnectionBadRequest log for all invalid requests on an otherwise healthy connection (Note: Middleware might still have run for a something logged as We could consider trying to formalize Kestrel's internal RequestRejectionReasons as part of this but I'm hesitant given we've gotten by without doing so this far. A lot of the reasons are specific to a certain versions of HTTP and not something you'd ever expect to see from non-buggy HTTP clients. We've found that logging a message describing the problem is sufficient for most use cases. I don't know why any app-level logic would care about things like whether the client sent a In any case, what details would you want for these events? The less specific the event, the harder it will be to always provide details, but maybe some of the details could be optional. |
@halter73 EventSource event or a callback would be great. Regarding the schema for these error events, the Http.sys error log schema is a pretty good starting point. https://docs.microsoft.com/en-us/troubleshoot/aspnet/error-logging-http-apis#format-of-the-http-api-error-logs Any requests that are not handed off to the worker process (for various reasons) are all logged in the above schema. Most of the schema in the above link is self-explanatory, except for "Reason phrase". (possible values for "Reason phrase" are listed below, (not exhaustive)) :
Link to reasons and the explanation : https://docs.microsoft.com/en-us/troubleshoot/aspnet/error-logging-http-apis#kinds-of-errors-that-the-http-api-logs The Http.Sys error schema does not translate as-is to Kestrel obviously, but I believe the below schema would contain what I'm looking for in a error log for requests/connections that are not handed off to the application middleware. As you mentioned, for some of the requests (connections), these could be well be optional/empty.
|
Based on our offline discussion: Let's look at emitting new events from
Open questions:
Given that this doesn't require new API surface, we can consider doing this in 6.0 after the preview7 release. |
What do we want to name the event?
I think this is okay, but I also think that only raising these invents if we don't invoke middleware is okay. The only difference is whether we raise the event for request body errors. Only raising the event for requests that are rejected before reaching middleware might make it easier to consume from something like W3CLogger. |
What does DTO mean here? EventSource only supports primitive types. We will just have a list of primitive type arguments for the event source method.
As long as it has enough information to communicate to the log reader about why the request was rejected. Might need a field for additional detail (which I'm sure will be ripe for abuse over the years from now 😄). |
If a request makes it to middleware, does that mean it is accepted? So would that mean this event would only fire for requests rejected before middleware? Also, if a request makes it to middleware then it is simple enough to write some middleware that catches any exceptions and logs them. An event like this isn't as important once the request has made it that far. |
Or more general
A request can make it to middleware and still hit a few bad request conditions like bad chunked formatting in the body. Yes those should be reported to the application as an Exception from Stream.ReadAsync, though intercepting that at all points in the app might require wrapping the stream. |
Triage: We can add a rejected reason phrase with failure details to a new feature and then pass the feature through a DiagnosticSource |
When running on Kestrel, requests typically fall into two buckets:
This is a feature request to enable efficient telemetry/logging for the 2nd category to increase observability into such failures.
Let's take a look at IIS/Http.Sys's approach to such failures:
In the case of Http.Sys, from https://learning.oreilly.com/library/view/internet-information-services/9780735624412/ch15s06.html, "HTTPERR log records all errors that are not handed off to a valid worker process, typically responses to clients, connection time-outs, and orphaned requests." In other words, requests that are not serviced by the application/rejected at the Http.Sys layer are logged.
Schema of a typical Http.Sys error log looks like this : https://docs.microsoft.com/en-us/troubleshoot/aspnet/error-logging-http-apis#format-of-the-http-api-error-logs
Similarly, in IIS, it is possible to configure FailedRequestTracing to log requests that fail in IIS layer and never reach the application middleware : https://www.jeremymorgan.com/blog/iis-devops/failed-request-tracing-iis/
A concrete example of where such logging is useful:
When Kestrel receives an authority form request where the request start line and host header are mismatched, Kestrel throws the following exception and returns a 400.0 (Stacktrace shows "google.com because that's the Host header I sent, point is valid for any mismatch). This request does not enter the application middleware and there is no observability for this error (unless Trace logging is turned on).
Specifically, this particular error is coming from this line : https://github.com/dotnet/aspnetcore/blob/be5ba495b4872fa055385463da655ae4c4318898/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs#L606-607
Repro:
Download ASP.NET Core sample app and fire up Kestrel in Visual Studio.
Use any client (I used wrk2), send a authority form request to Kestrel with mismatched HostHeader and request start line as shown below.
Your client will observe a 400.0 Status Code, but on the Server side, since the request does not enter the application middleware, there is no logging of this error.
The above is just one example, there are other examples (please let me know if you'd want me to provide more examples) where requests are terminated/rejected within Kestrel code and not handed off to application middleware.
The ask is to have functionality, where requests that are not serviced by the application middleware are logged efficiently. This telemetry will be hugely beneficial to critical large-scale distributed services.
The text was updated successfully, but these errors were encountered: