Skip to content

Commit cf932ba

Browse files
authored
[Hot Reload] Only enable ASP.NET debug logging if logging level is Trace (#51137)
1 parent 41851dd commit cf932ba

File tree

7 files changed

+104
-4
lines changed

7 files changed

+104
-4
lines changed

src/BuiltInTools/HotReloadClient/Logging/LogEvents.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public static void Log(this ILogger logger, LogEvent logEvent, params object[] a
2525
public static readonly LogEvent HotReloadSucceeded = Create(LogLevel.Information, "Hot reload succeeded.");
2626
public static readonly LogEvent RefreshingBrowser = Create(LogLevel.Debug, "Refreshing browser.");
2727
public static readonly LogEvent ReloadingBrowser = Create(LogLevel.Debug, "Reloading browser.");
28+
public static readonly LogEvent SendingWaitMessage = Create(LogLevel.Debug, "Sending wait message.");
2829
public static readonly LogEvent NoBrowserConnected = Create(LogLevel.Debug, "No browser is connected.");
2930
public static readonly LogEvent FailedToReceiveResponseFromConnectedBrowser = Create(LogLevel.Debug, "Failed to receive response from a connected browser.");
3031
public static readonly LogEvent UpdatingDiagnostics = Create(LogLevel.Debug, "Updating diagnostics.");

src/BuiltInTools/HotReloadClient/Web/AbstractBrowserRefreshServer.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void ConfigureLaunchEnvironment(IDictionary<string, string> builder, bool
101101
builder[MiddlewareEnvironmentVariables.DotNetModifiableAssemblies] = "debug";
102102
}
103103

104-
if (logger.IsEnabled(LogLevel.Debug))
104+
if (logger.IsEnabled(LogLevel.Trace))
105105
{
106106
// enable debug logging from middleware:
107107
builder[MiddlewareEnvironmentVariables.LoggingLevel] = "Debug";
@@ -237,8 +237,12 @@ public ValueTask SendReloadMessageAsync(CancellationToken cancellationToken)
237237
}
238238

239239
public ValueTask SendWaitMessageAsync(CancellationToken cancellationToken)
240-
=> SendAsync(s_waitMessage, cancellationToken);
240+
{
241+
logger.Log(LogEvents.SendingWaitMessage);
242+
return SendAsync(s_waitMessage, cancellationToken);
243+
}
241244

245+
// obsolete: to be removed
242246
public ValueTask SendPingMessageAsync(CancellationToken cancellationToken)
243247
=> SendAsync(s_pingMessage, cancellationToken);
244248

src/BuiltInTools/dotnet-watch/Process/ProjectLauncher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public EnvironmentOptions EnvironmentOptions
9191
environmentBuilder[EnvironmentVariables.Names.DotnetWatch] = "1";
9292
environmentBuilder[EnvironmentVariables.Names.DotnetWatchIteration] = (Iteration + 1).ToString(CultureInfo.InvariantCulture);
9393

94-
if (Logger.IsEnabled(LogLevel.Debug))
94+
if (Logger.IsEnabled(LogLevel.Trace))
9595
{
9696
environmentBuilder[EnvironmentVariables.Names.HotReloadDeltaClientLogMessages] =
9797
(EnvironmentOptions.SuppressEmojis ? Emoji.Default : Emoji.Agent).GetLogMessagePrefix() + $"[{projectDisplayName}]";
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.DotNet.HotReload;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace Microsoft.DotNet.Watch.UnitTests;
8+
9+
public class BrowserRefreshServerTests
10+
{
11+
class TestListener : IDisposable
12+
{
13+
public void Dispose()
14+
{
15+
}
16+
}
17+
18+
[Theory]
19+
[CombinatorialData]
20+
public async Task ConfigureLaunchEnvironmentAsync(LogLevel logLevel, bool enableHotReload)
21+
{
22+
var middlewarePath = Path.GetTempPath();
23+
var middlewareFileName = Path.GetFileNameWithoutExtension(middlewarePath);
24+
25+
var server = new TestBrowserRefreshServer(middlewarePath)
26+
{
27+
CreateAndStartHostImpl = () => new WebServerHost(new TestListener(), ["http://test.endpoint"], virtualDirectory: "/test/virt/dir")
28+
};
29+
30+
((TestLogger)server.Logger).IsEnabledImpl = level => level == logLevel;
31+
32+
await server.StartAsync(CancellationToken.None);
33+
34+
var envBuilder = new Dictionary<string, string>();
35+
server.ConfigureLaunchEnvironment(envBuilder, enableHotReload);
36+
37+
Assert.True(envBuilder.Remove("ASPNETCORE_AUTO_RELOAD_WS_KEY"));
38+
39+
var expected = new List<string>()
40+
{
41+
"ASPNETCORE_AUTO_RELOAD_VDIR=/test/virt/dir",
42+
"ASPNETCORE_AUTO_RELOAD_WS_ENDPOINT=http://test.endpoint",
43+
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=" + middlewareFileName,
44+
"DOTNET_STARTUP_HOOKS=" + middlewarePath,
45+
};
46+
47+
if (enableHotReload)
48+
{
49+
expected.Add("DOTNET_MODIFIABLE_ASSEMBLIES=debug");
50+
}
51+
52+
if (logLevel == LogLevel.Trace)
53+
{
54+
expected.Add("Logging__LogLevel__Microsoft.AspNetCore.Watch=Debug");
55+
}
56+
57+
AssertEx.SequenceEqual(expected.Order(), envBuilder.OrderBy(e => e.Key).Select(e => $"{e.Key}={e.Value}"));
58+
}
59+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.DotNet.HotReload;
5+
6+
namespace Microsoft.DotNet.Watch.UnitTests;
7+
8+
internal class TestBrowserRefreshServer(string middlewareAssemblyPath)
9+
: AbstractBrowserRefreshServer(middlewareAssemblyPath, new TestLogger(), new TestLoggerFactory())
10+
{
11+
public Func<WebServerHost>? CreateAndStartHostImpl;
12+
13+
protected override ValueTask<WebServerHost> CreateAndStartHostAsync(CancellationToken cancellationToken)
14+
=> ValueTask.FromResult((CreateAndStartHostImpl ?? throw new NotImplementedException())());
15+
16+
protected override bool SuppressTimeouts => true;
17+
}

test/dotnet-watch.Tests/TestUtilities/TestLogger.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ internal class TestLogger(ITestOutputHelper? output = null) : ILogger
1111
public readonly Lock Guard = new();
1212
private readonly List<string> _messages = [];
1313

14+
public Func<LogLevel, bool>? IsEnabledImpl;
15+
1416
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
1517
{
1618
var message = $"[{logLevel}] {formatter(state, exception)}";
@@ -36,5 +38,5 @@ public ImmutableArray<string> GetAndClearMessages()
3638
where TState : notnull => throw new NotImplementedException();
3739

3840
public bool IsEnabled(LogLevel logLevel)
39-
=> true;
41+
=> IsEnabledImpl?.Invoke(logLevel) ?? true;
4042
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.Extensions.Logging;
5+
6+
namespace Microsoft.DotNet.Watch.UnitTests;
7+
8+
internal class TestLoggerFactory(ITestOutputHelper? output = null) : ILoggerFactory
9+
{
10+
public Func<string, ILogger>? CreateLoggerImpl;
11+
12+
public ILogger CreateLogger(string categoryName)
13+
=> CreateLoggerImpl?.Invoke(categoryName) ?? new TestLogger(output);
14+
15+
public void AddProvider(ILoggerProvider provider) {}
16+
public void Dispose() { }
17+
}

0 commit comments

Comments
 (0)