Betterize Hosting Log#10102
Conversation
|
This comment was made automatically. If there is a problem contact aspnetcore-build@microsoft.com. I've triaged the above build. I've created/commented on the following issue(s) |
There was a problem hiding this comment.
My remaining question is how often a Context is constructed without setting any of these properties to a non-default value.
This does seem like a ton of work to turn six properties into one lazy-allocated field with six properties.
Also, does this need to be thread safe? I hope not because new LogContext() could run multiple times if LoggingContext is accessed and initialized twice in a parallel.
There was a problem hiding this comment.
My remaining question is how often a Context is constructed without setting any of these properties to a non-default value.
If you don't want an Activity (152 bytes), 4 ExecutionContexts (160 bytes), 2 strings (76+66 bytes), 4 AsyncLocalMaps (160 bytes) and 3 Logging scope objects (144 bytes); => 758 bytes per request; when you aren't outputting any of it because you aren't at Information level; you might set "Microsoft.AspNetCore.Hosting.Diagnostics": "None" which will do it.
e.g.
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.AspNetCore.Hosting.Diagnostics": "None"
},
"EventLog": {
"LogLevel": {
"Microsoft.AspNetCore.Hosting.Diagnostics": "None"
}
}
},
And if you are picking up that extra 758 bytes per request, what's an extra object ;)
Also if you have no logging as per the TE benchmarks; which also benefits from the struct being 64 bytes rather than 82 bytes when passed.
Also, does this need to be thread safe?
No, its contained to before and after the request in hosting and not exposed to the user code in the application
There was a problem hiding this comment.
I completely forgot that the Context itself was a struct. Too bad it's public. It would have been sooo much easier to turn the Context into a class, but that's breaking.
There was a problem hiding this comment.
And if Logging is off for Hosting then the Activity and the LogContext will never be allocated as they are guarded by the Log Enabled check
There was a problem hiding this comment.
I completely forgot that the Context itself was a struct. Too bad it's public. It would have been sooo much easier to turn the Context into a class, but that's breaking.
Well LogContext is now a class if you can work out where to hang it rather than allocating it per request? (when logging or diagnostics is enabled)
There was a problem hiding this comment.
And if Logging is off for Hosting then the Activity and the LogContext will never be allocated as they are guarded by the Log Enabled check
I figured, but that's unrelated to the LogContext.
Well LogContext is now a class if you can work out where to hang it rather than allocating it per request? (when logging or diagnostics is enabled)
Pooling is an interesting idea. If Context itself was a class, could we pool that instead?
There was a problem hiding this comment.
The HttpContext is "pooled" via IHttpContextFactory (lives on connection); but the HostingApplication.Context is side-car'd over it and avoids allocation by living in the stack and being passed around by value.
There was a problem hiding this comment.
More @pranavkm points 😄 I see this was introduced "way back" in C# 6, but I haven't seen this used much.
There was a problem hiding this comment.
I was going to make this readonly get but the version of C# AspNetCore uses is too old.
I think updating it will make Code Check unhappy as every auto-property getter gets the [Readonly] attribute
|
Actually, would it really be too breaking to make HostingApplication.Context a class? Context seems to have turned into an overly-long, overly-complicated class anyway with almost everything being stored via LogContext reference. This PR changes the struct layout anyway which is why the reference assembly needed updating. |
Would need to introduce a service that the server implemented to not allocated it per request (as per HttpContext); so would be a lot more motion? And since it also contains the Could go with a double interface; if server implements HostContext pooling use that, otherwise use only HttpContext pooling and allocate the HostContext? |
Only removes the attributes |
Something like: |
|
Though... that might be part of a bigger issue. Like are some routing structures connection orientated rather than request; can scopes be reset and reused etc..? |
|
With pooling the HostContext #10180 |
|
I'd like to review this before merging. I haven't kept up to date with the changes. |
|
@davidfowl @halter73 what's the situation here? Are we ready to merge? Unfortunately it'll probably need another rebase :(. |
|
I'm fine with merging this. We'll want to keep a close eye on the benchmarks. |
|
With master targeting 5.0 now, I'm totally fine with that. I'll re-kick the build to force it to run against the latest master. If that works, I'm OK with merging without a rebase (since we'll rebase as it's merged). |
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
Imagine if we could run benchmarks before committing 😬 |
|
Someday... someday our dreams will come true :). @halter73 the rebuild looks to be fine, merge when you're ready. |
|
Rebased |
|
/azp run AspNetCore-ci |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Didn't seem to restart the |
Doesn't look to be related to this change. The failure isn't related to the contents of the logs, but the |
|
/azp run |
|
Commenter does not have sufficient privileges for PR 10102 in repo aspnet/AspNetCore |



Output something more useful for
HostingRequestFinishedLog(which can get intermixed when multiple parallel requests); so it becomes the more interesting event given context; since its kinda junky currently unless you are also outputting full scopes (even then you need to do matching).Before
After
Also improve the more detailed semantic logged output
Before

After

Resolves #10097
Resolves #10556
Resolves #10557
/cc @davidfowl