Cleanup WebProfiler from 8.x
This commit is contained in:
@@ -1,159 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using StackExchange.Profiling;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Profiling
|
||||
{
|
||||
/// <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 StartupPhase.Request then the base class (default) provider will handle all
|
||||
/// profiling data and this sub class no longer performs any logic.
|
||||
/// </remarks>
|
||||
internal class StartupWebProfilerProvider : WebRequestProfilerProvider
|
||||
{
|
||||
public StartupWebProfilerProvider()
|
||||
{
|
||||
_startupPhase = StartupPhase.Boot;
|
||||
//create the startup profiler
|
||||
_startupProfiler = new MiniProfiler("http://localhost/umbraco-startup", ProfileLevel.Verbose)
|
||||
{
|
||||
Name = "StartupProfiler"
|
||||
};
|
||||
}
|
||||
|
||||
private MiniProfiler _startupProfiler;
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine which phase the boot process is in
|
||||
/// </summary>
|
||||
private enum StartupPhase
|
||||
{
|
||||
None = 0,
|
||||
Boot = 1,
|
||||
Request = 2
|
||||
}
|
||||
|
||||
private volatile StartupPhase _startupPhase;
|
||||
|
||||
/// <summary>
|
||||
/// Executed once the application boot process is complete and changes the phase to Request
|
||||
/// </summary>
|
||||
public void BootComplete()
|
||||
{
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
if (_startupPhase != StartupPhase.Boot) return;
|
||||
}
|
||||
|
||||
using (var l = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
if (_startupPhase == StartupPhase.Boot)
|
||||
{
|
||||
l.UpgradeToWriteLock();
|
||||
_startupPhase = StartupPhase.Request;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executed when a profiling operation is completed
|
||||
/// </summary>
|
||||
/// <param name="discardResults"></param>
|
||||
/// <remarks>
|
||||
/// This checks if the bootup phase is None, if so, it just calls the base class, otherwise it checks
|
||||
/// if a profiler is active (i.e. in startup), then sets the phase to None so that the base class will be used
|
||||
/// for all subsequent calls.
|
||||
/// </remarks>
|
||||
public override void Stop(bool discardResults)
|
||||
{
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
if (_startupPhase == StartupPhase.None)
|
||||
{
|
||||
base.Stop(discardResults);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
using (var l = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
if (_startupPhase > 0 && base.GetCurrentProfiler() == null)
|
||||
{
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
_startupPhase = StartupPhase.None;
|
||||
|
||||
//This is required to pass the mini profiling context from before a request
|
||||
// to the current startup request.
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Items[":mini-profiler:"] = _startupProfiler;
|
||||
base.Stop(discardResults);
|
||||
_startupProfiler = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Stop(discardResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executed when a profiling operation is started
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This checks if the startup phase is not None, if this is the case and the current profiler is NULL
|
||||
/// then this sets the startup profiler to be active. Otherwise it just calls the base class Start method.
|
||||
/// </remarks>
|
||||
public override MiniProfiler Start(ProfileLevel level)
|
||||
{
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
if (_startupPhase > 0 && base.GetCurrentProfiler() == null)
|
||||
{
|
||||
SetProfilerActive(_startupProfiler);
|
||||
return _startupProfiler;
|
||||
}
|
||||
|
||||
return base.Start(level);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This returns the current profiler
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// If the boot phase is not None, then this will return the startup profiler (this), otherwise
|
||||
/// returns the base class
|
||||
/// </remarks>
|
||||
public override MiniProfiler GetCurrentProfiler()
|
||||
{
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
if (_startupPhase > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var current = base.GetCurrentProfiler();
|
||||
if (current == null) return _startupProfiler;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return _startupProfiler;
|
||||
}
|
||||
}
|
||||
|
||||
return base.GetCurrentProfiler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using StackExchange.Profiling;
|
||||
using StackExchange.Profiling.SqlFormatters;
|
||||
@@ -14,22 +15,23 @@ namespace Umbraco.Web.Profiling
|
||||
/// </summary>
|
||||
internal class WebProfiler : IProfiler
|
||||
{
|
||||
private StartupWebProfilerProvider _startupWebProfilerProvider;
|
||||
private const string BootRequestItemKey = "Umbraco.Web.Profiling.WebProfiler__isBootRequest";
|
||||
private WebProfilerProvider _provider;
|
||||
private int _first;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
internal WebProfiler()
|
||||
{
|
||||
//setup some defaults
|
||||
// create our own provider, which can provide a profiler even during boot
|
||||
// MiniProfiler's default cannot because there's no HttpRequest in HttpContext
|
||||
_provider = new WebProfilerProvider();
|
||||
|
||||
// settings
|
||||
MiniProfiler.Settings.SqlFormatter = new SqlServerFormatter();
|
||||
MiniProfiler.Settings.StackMaxLength = 5000;
|
||||
|
||||
//At this point we know that we've been constructed during app startup, there won't be an HttpRequest in the HttpContext
|
||||
// since it hasn't started yet. So we need to do some hacking to enable profiling during startup.
|
||||
_startupWebProfilerProvider = new StartupWebProfilerProvider();
|
||||
//this should always be the case during startup, we'll need to set a custom profiler provider
|
||||
MiniProfiler.Settings.ProfilerProvider = _startupWebProfilerProvider;
|
||||
MiniProfiler.Settings.ProfilerProvider = _provider;
|
||||
|
||||
//Binds to application events to enable the MiniProfiler with a real HttpRequest
|
||||
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
|
||||
@@ -57,43 +59,33 @@ namespace Umbraco.Web.Profiling
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the begin request event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void UmbracoApplicationEndRequest(object sender, EventArgs e)
|
||||
{
|
||||
if (_startupWebProfilerProvider != null)
|
||||
{
|
||||
Stop();
|
||||
_startupWebProfilerProvider = null;
|
||||
}
|
||||
else if (CanPerformProfilingAction(sender))
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the end request event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void UmbracoApplicationBeginRequest(object sender, EventArgs e)
|
||||
{
|
||||
if (_startupWebProfilerProvider != null)
|
||||
// if this is the first request, notify our own provider that this request is the boot request
|
||||
var first = Interlocked.Exchange(ref _first, 1) == 0;
|
||||
if (first)
|
||||
{
|
||||
_startupWebProfilerProvider.BootComplete();
|
||||
_provider.BeginBootRequest();
|
||||
((HttpApplication)sender).Context.Items[BootRequestItemKey] = true;
|
||||
// and no need to start anything, profiler is already there
|
||||
}
|
||||
|
||||
if (CanPerformProfilingAction(sender))
|
||||
{
|
||||
// else start a profiler, the normal way
|
||||
else if (ShouldProfile(sender))
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanPerformProfilingAction(object sender)
|
||||
void UmbracoApplicationEndRequest(object sender, EventArgs e)
|
||||
{
|
||||
// if this is the boot request, or if we should profile this request, stop
|
||||
// (the boot request is always profiled, no matter what)
|
||||
var isBootRequest = ((HttpApplication)sender).Context.Items[BootRequestItemKey] != null; // fixme perfs
|
||||
if (isBootRequest)
|
||||
_provider.EndBootRequest();
|
||||
if (isBootRequest || ShouldProfile(sender))
|
||||
Stop();
|
||||
}
|
||||
|
||||
private bool ShouldProfile(object sender)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false)
|
||||
return false;
|
||||
@@ -108,10 +100,10 @@ namespace Umbraco.Web.Profiling
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrEmpty(request.Result.QueryString["umbDebug"]))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
if (request.Result.Url.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
121
src/Umbraco.Web/Profiling/WebProfilerProvider.cs
Normal file
121
src/Umbraco.Web/Profiling/WebProfilerProvider.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using StackExchange.Profiling;
|
||||
|
||||
namespace Umbraco.Web.Profiling
|
||||
{
|
||||
/// <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 StartupPhase.Request 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>
|
||||
/// Executed when a profiling operation is started
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This checks if the startup phase is not None, if this is the case and the current profiler is NULL
|
||||
/// then this sets the startup profiler to be active. Otherwise it just calls the base class Start method.
|
||||
/// </remarks>
|
||||
public override MiniProfiler Start(ProfileLevel level)
|
||||
{
|
||||
var first = Interlocked.Exchange(ref _first, 1) == 0;
|
||||
if (first == false) return base.Start(level);
|
||||
|
||||
_startupProfiler = new MiniProfiler("http://localhost/umbraco-startup") { Name = "StartupProfiler" };
|
||||
SetProfilerActive(_startupProfiler);
|
||||
return _startupProfiler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This returns the current profiler
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// If the boot phase is not None, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -382,7 +382,7 @@
|
||||
<Compile Include="Mvc\UmbracoRequireHttpsAttribute.cs" />
|
||||
<Compile Include="Mvc\ValidateMvcAngularAntiForgeryTokenAttribute.cs" />
|
||||
<Compile Include="OwinMiddlewareConfiguredEventArgs.cs" />
|
||||
<Compile Include="Profiling\StartupWebProfilerProvider.cs" />
|
||||
<Compile Include="Profiling\WebProfilerProvider.cs" />
|
||||
<Compile Include="Profiling\WebProfiler.cs" />
|
||||
<Compile Include="PropertyEditors\DatePreValueEditor.cs" />
|
||||
<Compile Include="PropertyEditors\DateTimePreValueEditor.cs" />
|
||||
|
||||
Reference in New Issue
Block a user