Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miniprofiler for v13 #13841

Merged
merged 5 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public static IUmbracoBuilder AddUmbraco(
services.ConfigureOptions<ConfigureKestrelServerOptions>();
services.ConfigureOptions<ConfigureFormOptions>();

IProfiler profiler = GetWebProfiler(config);
IProfiler profiler = GetWebProfiler(config, httpContextAccessor);

services.AddLogger(webHostEnvironment, config);

Expand Down Expand Up @@ -200,15 +200,8 @@ public static IUmbracoBuilder AddUmbracoProfiler(this IUmbracoBuilder builder)
{
builder.Services.AddSingleton<WebProfilerHtml>();

builder.Services.AddMiniProfiler(options =>
{
// WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile
options.ShouldProfile = request => false;

// this is a default path and by default it performs a 'contains' check which will match our content controller
// (and probably other requests) and ignore them.
options.IgnoredPaths.Remove("/content/");
});
builder.Services.AddMiniProfiler();
builder.Services.ConfigureOptions<ConfigureMiniProfilerOptions>();

builder.AddNotificationHandler<UmbracoApplicationStartingNotification, InitializeWebProfiling>();
return builder;
Expand Down Expand Up @@ -385,7 +378,7 @@ public static IUmbracoBuilder AddWebServer(this IUmbracoBuilder builder)
return builder;
}

private static IProfiler GetWebProfiler(IConfiguration config)
private static IProfiler GetWebProfiler(IConfiguration config, IHttpContextAccessor httpContextAccessor)
{
var isDebug = config.GetValue<bool>($"{Constants.Configuration.ConfigHosting}:Debug");

Expand All @@ -397,7 +390,7 @@ private static IProfiler GetWebProfiler(IConfiguration config)
return new NoopProfiler();
}

var webProfiler = new WebProfiler();
var webProfiler = new WebProfiler(httpContextAccessor);
webProfiler.StartBoot();

return webProfiler;
Expand Down
43 changes: 43 additions & 0 deletions src/Umbraco.Web.Common/Profiler/ConfigureMiniProfilerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using StackExchange.Profiling;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Security;
using Umbraco.Extensions;

namespace Umbraco.Cms.Web.Common.Profiler;

internal sealed class ConfigureMiniProfilerOptions : IConfigureOptions<MiniProfilerOptions>
{
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly string _backOfficePath;

public ConfigureMiniProfilerOptions(
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IOptions<GlobalSettings> globalSettings,
IHostingEnvironment hostingEnvironment)
{
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_backOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment);
}

public void Configure(MiniProfilerOptions options)
{
options.RouteBasePath = WebPath.Combine(_backOfficePath, "profiler");
// WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile
options.ShouldProfile = request => false;

options.IgnoredPaths.Clear();
options.IgnoredPaths.Add(WebPath.Combine(_backOfficePath, "swagger"));
options.IgnoredPaths.Add(WebPath.Combine(options.RouteBasePath, "results-list"));
options.IgnoredPaths.Add(WebPath.Combine(options.RouteBasePath, "results-index"));
options.IgnoredPaths.Add(WebPath.Combine(options.RouteBasePath, "results"));

options.ResultsAuthorize = IsBackofficeUserAuthorized;
options.ResultsListAuthorize = IsBackofficeUserAuthorized;
}

private bool IsBackofficeUserAuthorized(HttpRequest request) => true;// FIXME when we can get current backoffice user, _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser is not null;
}
24 changes: 20 additions & 4 deletions src/Umbraco.Web.Common/Profiler/WebProfiler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using StackExchange.Profiling;
Expand All @@ -14,6 +15,14 @@ namespace Umbraco.Cms.Web.Common.Profiler;

public class WebProfiler : IProfiler
{
private readonly IHttpContextAccessor _httpContextAccessor;

public WebProfiler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}


public static readonly AsyncLocal<MiniProfiler> MiniProfilerContext = new(x =>
{
_ = x;
Expand All @@ -24,11 +33,12 @@ public class WebProfiler : IProfiler
private int _first;
private MiniProfiler? _startupProfiler;

public IDisposable? Step(string name) => MiniProfiler.Current?.Step(name);
public IDisposable? Step(string name) =>
MiniProfiler.Current?.Step(name);

public void Start()
{
MiniProfiler.StartNew();
MiniProfiler.StartNew(_httpContextAccessor.HttpContext?.Request.Path);
MiniProfilerContext.Value = MiniProfiler.Current;
}

Expand Down Expand Up @@ -75,7 +85,6 @@ public void UmbracoApplicationEndRequest(HttpContext context, RuntimeLevel runti
{
AddSubProfiler(_startupProfiler);
}

_startupProfiler = null;
}

Expand All @@ -102,13 +111,20 @@ public void UmbracoApplicationEndRequest(HttpContext context, RuntimeLevel runti
private static ICookieManager GetCookieManager(HttpContext context) =>
context.RequestServices.GetRequiredService<ICookieManager>();

private static bool ShouldProfile(HttpRequest request)
private bool ShouldProfile(HttpRequest request)
{
if (request.IsClientSideRequest())
{
return false;
}

var miniprofilerOptions = _httpContextAccessor.HttpContext?.RequestServices?.GetService<IOptions<MiniProfilerOptions>>();
if (miniprofilerOptions is not null && miniprofilerOptions.Value.IgnoredPaths.Contains(request.Path))
{
return false;
}


if (bool.TryParse(request.Query["umbDebug"], out var umbDebug))
{
return umbDebug;
Expand Down