Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Reduce logging overhead in hosting #403

Closed
wants to merge 1 commit into from
Closed

Conversation

lodejard
Copy link
Contributor

  • TraceIdentifier is done at the last moment, or not at all
  • Request starting and finished messages are added
  • This pair provide many of the top-level values that you would have
    found in server log files.


public HostingRequestScope(HttpContext httpContext)
{
this._httpContext = httpContext;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🆗

@lodejard lodejard force-pushed the lodejard/perf-logging branch from 2796353 to 7921894 Compare October 13, 2015 21:29
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.Log(LogLevel.Information, 1, new HostingRequestStarting(httpContext), null, HostingRequestStarting.Callback);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null and 1 should use the optional args syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🆗

@davidfowl
Copy link
Member

This ci broke

@lodejard
Copy link
Contributor Author

See also aspnet/Logging#261

{
private readonly HttpContext _httpContext;

private FeatureReference<IHttpRequestIdentifierFeature> _requestIdentifierFeatureReference;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With aspnet/HttpAbstractions#440 merged, remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Hmm... Why don't I see it yet? I'm using 1.0.0-rc1-15826... Must still be working its way through the system

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will merge back into other PR, and add comment changes - hopefully it will flow though soon :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, updated #409 with all the changes but isn't picking up TraceIdentifier on HttpContextyet :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coherence hasn't passed, but you can reference https://www.myget.org/F/aspnetvolatiledev/api/v2 instead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was test break, applied fix; build is now happy against aspnetvolatiledev for other PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is working now! 💃

@benaadams
Copy link
Contributor

PR #409 is working now; which you'll need to merge as the HttpAbstraction changes look like they have flowed through; so currently this PR will break the CI. Added all my comment changes from this to it - as they were around the upcoming break.

@benaadams
Copy link
Contributor

Sorry, was wrong, don't think this PR will break the CI as it stands (without the other changes)

}
}

private class HostingRequestScope : ILogValues
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HostingLogScope. RequestScope sounds like DI

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, but the other two are still HostingRequestXxx

lodejard added a commit that referenced this pull request Oct 16, 2015
@benaadams
Copy link
Contributor

Rebased #409 onto last commit and picked up remaining clean up and ci break


private class HostingLogScope : ILogValues
{
private readonly HttpContext _httpContext;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could move this up to HttpAbstractions implement in safe general way (but not alloc free), and thus drop the HostingLogScope class create in RequestScope(...)

public abstract class HttpContext : ILogValues
{
    ...

    public override string ToString() => $"RequestId:{TraceIdentifier} RequestPath:{Request.Path}";

    IEnumerable<KeyValuePair<string, object>> ILogValues.GetValues()
    {
        yield return new KeyValuePair<string, object>("RequestId", TraceIdentifier);
        yield return new KeyValuePair<string, object>("RequestPath", Request.Path.ToString());
    }
}

Specific derived classes could then override with caching as per HostingLogScope

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't recommend it. Hosting has an opinion on what is appropriate to log at this moment in the request's execution. That opinion is not valid or useful elsewhere in the app.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, then switch

public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext)
{
    return logger.BeginScopeImpl(new HostingLogScope(httpContext));
}

for

public static IDisposable RequestScope(this ILogger logger, HttpContext httpContext)
{
    return logger.IsEnabled(LogLevel.Critical) 
                ? logger.BeginScopeImpl(new HostingLogScope(httpContext)) 
                : null;
}

Would that work? Else might regress on perf.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per discussion with lou, that's not really correct. Scopes are relevant to all loggers, not just to the current one. We'd need a sort of global 'all loggers disabled' check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't it go via Microsoft.Extensions.Logging.Logger which enumerates all loggers in the IsEnabled method bailing on first true?

Also have fast path PR for no loggers for the check: https://github.com/aspnet/Logging/pull/254/files

An IsEnabled with no params would be prettier, but would change the interface.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you mean because its an extension method so can be used in multiple places rather than just on the top level logger?

Or adding a logger at a particular point in the pipeline, to only log specific bits?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out it was a bug to check the IsEnabled to short-circuit the scope. Even if messages in the logger's category are entirely disabled, there can be other messages in the application that will be logged and will need the logger scope available... We might be able to optimize the BeginScopeImpl a little bit more and get the per-request overhead down to a single object with one field, then measure it from there to see how much impact that is having

@rynowak rynowak force-pushed the lodejard/perf-logging branch from d2feb06 to 3845e33 Compare October 22, 2015 23:10
lodejard added a commit that referenced this pull request Oct 22, 2015
@rynowak
Copy link
Member

rynowak commented Oct 22, 2015

@Tratcher updated

throw;
finally
{
logger.RequestFinished(httpContext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still weird that this fires for unhandled exceptions and logs 200 OK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you feel about just logging the elapsed time on failure then - no contenttype/status code. It really seems like the best we can do for now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better, but you don't have the elapsed time here, do you? I would expect logger.RequestFailed(), with or without the exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative is to hook the request completed event to have the correct status code and possibly more accurate overall time. That would need to be weighed against the overhead of the event hook per request - but it can be done only if that level is enabled - so it's no cost at all when no loggers aren't added.

@rynowak rynowak force-pushed the lodejard/perf-logging branch from 3845e33 to 561b10b Compare October 23, 2015 19:57
lodejard added a commit that referenced this pull request Oct 23, 2015
@rynowak
Copy link
Member

rynowak commented Oct 23, 2015

@Tratcher updated

@benaadams
Copy link
Contributor

#409 changes:

  • Remove src/Microsoft.AspNet.Hosting/Internal/FastHttpRequestIdentifierFeature.cs
  • Remove function private string GetRequestIdentifier(HttpContext httpContext) from src/Microsoft.AspNet.Hosting/Internal/HostingEngine.cs
  • Remove call var requestIdentifier = GetRequestIdentifier(httpContext); from same file
  • Remove "allowUnsafe": true from src/Microsoft.AspNet.Hosting/project.json
  • Remove test/Microsoft.AspNet.Hosting.Tests/Internal/FastHttpRequestIdentifierFeatureTests.cs
  • Change function HostingEngine_CreatesDefaultRequestIdentifierFeature_IfNotPresent in test/Microsoft.AspNet.Hosting.Tests/HostingEngineTests.cs from
Assert.NotNull(httpContext);
Assert.IsType<FastHttpRequestIdentifierFeature>(httpContext.Features.Get<IHttpRequestIdentifierFeature>());

to

Assert.NotNull(httpContext);
Assert.IsType<HttpRequestIdentifierFeature>(httpContext.Features.Get<IHttpRequestIdentifierFeature>());
Assert.False(string.IsNullOrWhiteSpace(httpContext.TraceIdentifier));
Assert.Same(httpContext.TraceIdentifier, httpContext.Features.Get<IHttpRequestIdentifierFeature>().TraceIdentifier);

@@ -93,27 +93,40 @@ public virtual IApplication Start()
{
var httpContext = contextFactory.CreateHttpContext(features);
httpContext.ApplicationServices = _applicationServices;

var requestIdentifier = GetRequestIdentifier(httpContext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line.

@Tratcher
Copy link
Member

:shipit:

* TraceIdentifier is done at the last moment, or not at all
* Request starting and finished messages are added
* This pair provide many of the top-level values that you would have
  found in server log files.
@rynowak rynowak force-pushed the lodejard/perf-logging branch from 5085cce to 8cdff72 Compare October 23, 2015 21:10
@rynowak
Copy link
Member

rynowak commented Oct 23, 2015

Will wait until CI for hosting is green to push. Currently broken due to issues not related to this change.

@rynowak rynowak closed this Oct 23, 2015
@rynowak rynowak deleted the lodejard/perf-logging branch October 23, 2015 21:11
@rynowak
Copy link
Member

rynowak commented Oct 23, 2015

f37375f

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants