Fixes 3713

Moved the UmbracoApplicationBase from Core to Web
Moved the WebProfiler from Core to Web
Removed UmbracoApplicationBase from the CoreRuntime, it's still in the WebRuntime (and registered there in DI)
This commit is contained in:
Aaron Powell
2018-11-19 21:23:08 +11:00
parent 889e48ea4a
commit 71026d6d15
11 changed files with 38 additions and 22 deletions

View File

@@ -0,0 +1,127 @@
using System;
using System.Threading;
using System.Web;
using StackExchange.Profiling;
namespace Umbraco.Web.Logging
{
/// <summary>
/// This is a custom MiniProfiler WebRequestProfilerProvider (which is generally the default) that allows
/// us to profile items during app startup - before an HttpRequest is created
/// </summary>
/// <remarks>
/// Once the boot phase is changed to BootPhase.BootRequest then the base class (default) provider will handle all
/// profiling data and this sub class no longer performs any logic.
/// </remarks>
internal class WebProfilerProvider : WebRequestProfilerProvider
{
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
private MiniProfiler _startupProfiler;
private int _first;
private volatile BootPhase _bootPhase;
public WebProfilerProvider()
{
// booting...
_bootPhase = BootPhase.Boot;
}
/// <summary>
/// Indicates the boot phase.
/// </summary>
private enum BootPhase
{
Boot = 0, // boot phase (before the 1st request even begins)
BootRequest = 1, // request boot phase (during the 1st request)
Booted = 2 // done booting
}
public void BeginBootRequest()
{
_locker.EnterWriteLock();
try
{
if (_bootPhase != BootPhase.Boot)
throw new InvalidOperationException("Invalid boot phase.");
_bootPhase = BootPhase.BootRequest;
// assign the profiler to be the current MiniProfiler for the request
// is's already active, starting and all
HttpContext.Current.Items[":mini-profiler:"] = _startupProfiler;
}
finally
{
_locker.ExitWriteLock();
}
}
public void EndBootRequest()
{
_locker.EnterWriteLock();
try
{
if (_bootPhase != BootPhase.BootRequest)
throw new InvalidOperationException("Invalid boot phase.");
_bootPhase = BootPhase.Booted;
_startupProfiler = null;
}
finally
{
_locker.ExitWriteLock();
}
}
/// <summary>
/// Starts a new MiniProfiler.
/// </summary>
/// <remarks>
/// <para>This is called when WebProfiler calls MiniProfiler.Start() so,
/// - as a result of WebRuntime starting the WebProfiler, and
/// - assuming profiling is enabled, on every BeginRequest that should be profiled,
/// - except for the very first one which is the boot request.</para>
/// </remarks>
public override MiniProfiler Start(string sessionName = null)
{
var first = Interlocked.Exchange(ref _first, 1) == 0;
if (first == false) return base.Start(sessionName);
_startupProfiler = new MiniProfiler("http://localhost/umbraco-startup") { Name = "StartupProfiler" };
SetProfilerActive(_startupProfiler);
return _startupProfiler;
}
// obsolete but that's the one that's called ;-(
[Obsolete]
public override MiniProfiler Start(ProfileLevel level, string sessionName = null)
{
return Start(sessionName);
}
/// <summary>
/// Gets the current profiler.
/// </summary>
/// <remarks>
/// If the boot phase is not Booted, then this will return the startup profiler (this), otherwise
/// returns the base class
/// </remarks>
public override MiniProfiler GetCurrentProfiler()
{
// if not booting then just use base (fast)
// no lock, _bootPhase is volatile
if (_bootPhase == BootPhase.Booted)
return base.GetCurrentProfiler();
// else
try
{
var current = base.GetCurrentProfiler();
return current ?? _startupProfiler;
}
catch
{
return _startupProfiler;
}
}
}
}