Files
Umbraco-CMS/src/Umbraco.Core/Profiling/WebProfiler.cs
2013-09-11 09:30:00 +02:00

159 lines
5.2 KiB
C#

using System;
using System.Web;
using StackExchange.Profiling;
using StackExchange.Profiling.SqlFormatters;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Profiling
{
/// <summary>
/// A profiler used for web based activity based on the MiniProfiler framework
/// </summary>
internal class WebProfiler : IProfiler
{
/// <summary>
/// Constructor
/// </summary>
/// <remarks>
/// Binds to application events to enable the MiniProfiler
/// </remarks>
internal WebProfiler()
{
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
}
/// <summary>
/// Handle the Init event o fthe UmbracoApplication which allows us to subscribe to the HttpApplication events
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationApplicationInit(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app == null) return;
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
{
//If we don't have a high enough trust level we cannot bind to the events
LogHelper.Info<WebProfiler>("Cannot start the WebProfiler since the application is running in Medium trust");
}
else
{
app.BeginRequest += UmbracoApplicationBeginRequest;
app.EndRequest += UmbracoApplicationEndRequest;
}
}
/// <summary>
/// Handle the begin request event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationEndRequest(object sender, EventArgs e)
{
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 (CanPerformProfilingAction(sender))
{
Start();
}
}
private bool CanPerformProfilingAction(object sender)
{
if (GlobalSettings.DebugMode == false)
return false;
//will not run in medium trust
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
return false;
var request = TryGetRequest(sender);
if (request.Success == false || request.Result.Url.IsClientSideRequest() || string.IsNullOrEmpty(request.Result["umbDebug"]))
return false;
return true;
}
/// <summary>
/// Render the UI to display the profiler
/// </summary>
/// <returns></returns>
/// <remarks>
/// Generally used for HTML displays
/// </remarks>
public string Render()
{
return MiniProfiler.RenderIncludes().ToString();
}
/// <summary>
/// Profile a step
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
/// <remarks>
/// Use the 'using(' syntax
/// </remarks>
public IDisposable Step(string name)
{
return GlobalSettings.DebugMode == false ? null : MiniProfiler.Current.Step(name);
}
/// <summary>
/// Start the profiler
/// </summary>
public void Start()
{
MiniProfiler.Settings.SqlFormatter = new SqlServerFormatter();
MiniProfiler.Settings.StackMaxLength = 5000;
MiniProfiler.Start();
}
/// <summary>
/// Start the profiler
/// </summary>
/// <remarks>
/// set discardResults to false when you want to abandon all profiling, this is useful for
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
/// </remarks>
public void Stop(bool discardResults = false)
{
MiniProfiler.Stop(discardResults);
}
/// <summary>
/// Gets the request object from the app instance if it is available
/// </summary>
/// <param name="sender">The application object</param>
/// <returns></returns>
private Attempt<HttpRequestBase> TryGetRequest(object sender)
{
var app = sender as HttpApplication;
if (app == null) return Attempt<HttpRequestBase>.Fail();
try
{
var req = app.Request;
return Attempt<HttpRequestBase>.Succeed(new HttpRequestWrapper(req));
}
catch (HttpException ex)
{
return Attempt<HttpRequestBase>.Fail(ex);
}
}
}
}