using System;
using System.Web;
using StackExchange.Profiling;
using StackExchange.Profiling.SqlFormatters;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Profiling
{
///
/// A profiler used for web based activity based on the MiniProfiler framework
///
internal class WebProfiler : IProfiler
{
///
/// Constructor
///
///
/// Binds to application events to enable the MiniProfiler
///
internal WebProfiler()
{
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
}
///
/// Handle the Init event o fthe UmbracoApplication which allows us to subscribe to the HttpApplication events
///
///
///
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("Cannot start the WebProfiler since the application is running in Medium trust");
}
else
{
app.BeginRequest += UmbracoApplicationBeginRequest;
app.EndRequest += UmbracoApplicationEndRequest;
}
}
///
/// Handle the begin request event
///
///
///
void UmbracoApplicationEndRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
{
Stop();
}
}
///
/// Handle the end request event
///
///
///
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;
}
///
/// Render the UI to display the profiler
///
///
///
/// Generally used for HTML displays
///
public string Render()
{
return MiniProfiler.RenderIncludes().ToString();
}
///
/// Profile a step
///
///
///
///
/// Use the 'using(' syntax
///
public IDisposable Step(string name)
{
return GlobalSettings.DebugMode == false ? null : MiniProfiler.Current.Step(name);
}
///
/// Start the profiler
///
public void Start()
{
MiniProfiler.Settings.SqlFormatter = new SqlServerFormatter();
MiniProfiler.Settings.StackMaxLength = 5000;
MiniProfiler.Start();
}
///
/// Start the profiler
///
///
/// 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.
///
public void Stop(bool discardResults = false)
{
MiniProfiler.Stop(discardResults);
}
///
/// Gets the request object from the app instance if it is available
///
/// The application object
///
private Attempt TryGetRequest(object sender)
{
var app = sender as HttpApplication;
if (app == null) return Attempt.Fail();
try
{
var req = app.Request;
return Attempt.Succeed(new HttpRequestWrapper(req));
}
catch (HttpException ex)
{
return Attempt.Fail(ex);
}
}
}
}