Skip to content

Commit 58b75c5

Browse files
authored
Fixes issue with miniprofiler losing the information when doing a redirect, e.g. in a successful surfacecontroller call. (#11939)
Now we store the profiler in a cookie on local redirects and pick it up on next request and add it as a child to that profiler
1 parent 7971f36 commit 58b75c5

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

src/Umbraco.Web.Common/Profiler/WebProfiler.cs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
using System;
22
using System.Linq;
3+
using System.Net;
34
using System.Threading;
45
using Microsoft.AspNetCore.Http;
6+
using Microsoft.AspNetCore.Mvc.ViewFeatures;
7+
using Microsoft.Extensions.DependencyInjection;
58
using StackExchange.Profiling;
9+
using StackExchange.Profiling.Internal;
610
using Umbraco.Cms.Core;
711
using Umbraco.Cms.Core.Logging;
812
using Umbraco.Cms.Core.Services;
13+
using Umbraco.Cms.Core.Web;
914
using Umbraco.Extensions;
1015

1116
namespace Umbraco.Cms.Web.Common.Profiler
1217
{
1318

1419
public class WebProfiler : IProfiler
1520
{
21+
private const string WebProfileCookieKey = "umbracoWebProfiler";
22+
1623
public static readonly AsyncLocal<MiniProfiler> MiniProfilerContext = new AsyncLocal<MiniProfiler>(x =>
1724
{
1825
_ = x;
@@ -39,7 +46,6 @@ public void Start()
3946

4047
public void Stop(bool discardResults = false) => MiniProfilerContext.Value?.Stop(discardResults);
4148

42-
4349
public void UmbracoApplicationBeginRequest(HttpContext context, RuntimeLevel runtimeLevel)
4450
{
4551
if (runtimeLevel != RuntimeLevel.Run)
@@ -50,9 +56,13 @@ public void UmbracoApplicationBeginRequest(HttpContext context, RuntimeLevel run
5056
if (ShouldProfile(context.Request))
5157
{
5258
Start();
59+
ICookieManager cookieManager = GetCookieManager(context);
60+
cookieManager.ExpireCookie(WebProfileCookieKey); //Ensure we expire the cookie, so we do not reuse the old potential value saved
5361
}
5462
}
5563

64+
private static ICookieManager GetCookieManager(HttpContext context) => context.RequestServices.GetRequiredService<ICookieManager>();
65+
5666
public void UmbracoApplicationEndRequest(HttpContext context, RuntimeLevel runtimeLevel)
5767
{
5868
if (runtimeLevel != RuntimeLevel.Run)
@@ -70,19 +80,42 @@ public void UmbracoApplicationEndRequest(HttpContext context, RuntimeLevel runti
7080
var first = Interlocked.Exchange(ref _first, 1) == 0;
7181
if (first)
7282
{
73-
74-
var startupDuration = _startupProfiler.Root.DurationMilliseconds.GetValueOrDefault();
75-
MiniProfilerContext.Value.DurationMilliseconds += startupDuration;
76-
MiniProfilerContext.Value.GetTimingHierarchy().First().DurationMilliseconds += startupDuration;
77-
MiniProfilerContext.Value.Root.AddChild(_startupProfiler.Root);
83+
AddSubProfiler(_startupProfiler);
7884

7985
_startupProfiler = null;
8086
}
87+
88+
ICookieManager cookieManager = GetCookieManager(context);
89+
var cookieValue = cookieManager.GetCookieValue(WebProfileCookieKey);
90+
91+
if (cookieValue is not null)
92+
{
93+
AddSubProfiler(MiniProfiler.FromJson(cookieValue));
94+
}
95+
96+
//If it is a redirect to a relative path (local redirect)
97+
if (context.Response.StatusCode == (int)HttpStatusCode.Redirect
98+
&& context.Response.Headers.TryGetValue(Microsoft.Net.Http.Headers.HeaderNames.Location, out var location)
99+
&& !location.Contains("://"))
100+
{
101+
MiniProfilerContext.Value.Root.Name = "Before Redirect";
102+
cookieManager.SetCookieValue(WebProfileCookieKey, MiniProfilerContext.Value.ToJson());
103+
}
104+
81105
}
82106

83107
}
84108
}
85109

110+
private void AddSubProfiler(MiniProfiler subProfiler)
111+
{
112+
var startupDuration = subProfiler.Root.DurationMilliseconds.GetValueOrDefault();
113+
MiniProfilerContext.Value.DurationMilliseconds += startupDuration;
114+
MiniProfilerContext.Value.GetTimingHierarchy().First().DurationMilliseconds += startupDuration;
115+
MiniProfilerContext.Value.Root.AddChild(subProfiler.Root);
116+
117+
}
118+
86119
private static bool ShouldProfile(HttpRequest request)
87120
{
88121
if (request.IsClientSideRequest()) return false;

0 commit comments

Comments
 (0)