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); } } } }