diff --git a/src/Common/test/Hosting.Test/HostBuilderWrapperTest.cs b/src/Common/test/Hosting.Test/HostBuilderWrapperTest.cs index e9bebf9794..1e5b7ea4d1 100644 --- a/src/Common/test/Hosting.Test/HostBuilderWrapperTest.cs +++ b/src/Common/test/Hosting.Test/HostBuilderWrapperTest.cs @@ -22,7 +22,7 @@ public async Task WebApplicationBuilder_Wraps() ["foo"] = "bar" }; - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); @@ -57,7 +57,7 @@ public void HostApplicationBuilder_Wraps() ["foo"] = "bar" }; - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); HostApplicationBuilder builder = TestHostApplicationBuilderFactory.Create(); @@ -91,7 +91,7 @@ public void WebHostBuilder_Wraps() ["foo"] = "bar" }; - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); WebHostBuilder builder = TestWebHostBuilderFactory.Create(); @@ -128,7 +128,7 @@ public void GenericHostBuilder_Wraps() ["foo"] = "bar" }; - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Test", StringComparison.Ordinal)); HostBuilder builder = TestHostBuilderFactory.CreateWeb(); diff --git a/src/Common/test/Logging.Test/BootstrapperLoggerFactoryTest.cs b/src/Common/test/Logging.Test/BootstrapperLoggerFactoryTest.cs index 71bc7278f8..434e7feaeb 100644 --- a/src/Common/test/Logging.Test/BootstrapperLoggerFactoryTest.cs +++ b/src/Common/test/Logging.Test/BootstrapperLoggerFactoryTest.cs @@ -15,7 +15,7 @@ public sealed class BootstrapperLoggerFactoryTest [Fact] public async Task Upgrades_existing_loggers() { - var capturingLoggerProvider = new CapturingLoggerProvider(categoryName => categoryName.StartsWith("Test", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(categoryName => categoryName.StartsWith("Test", StringComparison.Ordinal)); var bootstrapLoggerFactory = BootstrapLoggerFactory.CreateEmpty(loggingBuilder => { diff --git a/src/Discovery/test/Eureka.Test/Transport/EurekaClientTest.cs b/src/Discovery/test/Eureka.Test/Transport/EurekaClientTest.cs index 74d424020c..b653071dea 100644 --- a/src/Discovery/test/Eureka.Test/Transport/EurekaClientTest.cs +++ b/src/Discovery/test/Eureka.Test/Transport/EurekaClientTest.cs @@ -131,7 +131,7 @@ public sealed class EurekaClientTest [Fact] public async Task RegisterAsync_ThrowsOnUnreachableServer() { - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); @@ -161,15 +161,15 @@ public async Task RegisterAsync_ThrowsOnUnreachableServer() IList logMessages = capturingLoggerProvider.GetAll(); logMessages.Should().BeEquivalentTo( - $"DBUG {typeof(EurekaClient).FullName}: Sending POST request to 'http://host-that-does-not-exist.net:9999/apps/FOOBAR' with body: " + + $"DBUG {typeof(EurekaClient)}: Sending POST request to 'http://host-that-does-not-exist.net:9999/apps/FOOBAR' with body: " + """{"instance":{"instanceId":"some","app":"FOOBAR","ipAddr":"127.0.0.1","port":{"@enabled":"true","$":8080},"securePort":{"@enabled":"false","$":9090},"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"localhost","overriddenstatus":"UNKNOWN","metadata":{"@class":"java.util.Collections$EmptyMap"},"lastUpdatedTimestamp":"1708427732823","lastDirtyTimestamp":"1708427732823"}}.""", - $"WARN {typeof(EurekaClient).FullName}: Failed to execute HTTP POST request to 'http://host-that-does-not-exist.net:9999/apps/FOOBAR' in attempt 1."); + $"WARN {typeof(EurekaClient)}: Failed to execute HTTP POST request to 'http://host-that-does-not-exist.net:9999/apps/FOOBAR' in attempt 1."); } [Fact] public async Task RegisterAsync_ThrowsOnErrorResponse() { - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); @@ -208,17 +208,17 @@ public async Task RegisterAsync_ThrowsOnErrorResponse() logMessages.Should().BeEquivalentTo( [ - $"DBUG {typeof(EurekaClient).FullName}: Sending POST request to 'http://localhost:8761/eureka/apps/FOOBAR' with body: " + + $"DBUG {typeof(EurekaClient)}: Sending POST request to 'http://localhost:8761/eureka/apps/FOOBAR' with body: " + """{"instance":{"instanceId":"some","app":"FOOBAR","ipAddr":"127.0.0.1","port":{"@enabled":"true","$":8080},"securePort":{"@enabled":"false","$":9090},"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"localhost","overriddenstatus":"UNKNOWN","metadata":{"@class":"java.util.Collections$EmptyMap"},"lastUpdatedTimestamp":"1708427732823","lastDirtyTimestamp":"1708427732823"}}.""", - $"DBUG {typeof(EurekaClient).FullName}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' returned status 404 in attempt 1.", - $"INFO {typeof(EurekaClient).FullName}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' failed with status 404: Sorry!" + $"DBUG {typeof(EurekaClient)}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' returned status 404 in attempt 1.", + $"INFO {typeof(EurekaClient)}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' failed with status 404: Sorry!" ], options => options.WithStrictOrdering()); } [Fact] public async Task RegisterAsync_ThrowsOnRetryLimitReached() { - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); @@ -254,10 +254,10 @@ public async Task RegisterAsync_ThrowsOnRetryLimitReached() logMessages.Should().BeEquivalentTo( [ - $"DBUG {typeof(EurekaClient).FullName}: Sending POST request to 'http://localhost:8761/eureka/apps/FOOBAR' with body: " + + $"DBUG {typeof(EurekaClient)}: Sending POST request to 'http://localhost:8761/eureka/apps/FOOBAR' with body: " + """{"instance":{"instanceId":"some","app":"FOOBAR","ipAddr":"127.0.0.1","port":{"@enabled":"true","$":8080},"securePort":{"@enabled":"false","$":9090},"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"localhost","overriddenstatus":"UNKNOWN","metadata":{"@class":"java.util.Collections$EmptyMap"},"lastUpdatedTimestamp":"1708427732823","lastDirtyTimestamp":"1708427732823"}}.""", - $"DBUG {typeof(EurekaClient).FullName}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' returned status 404 in attempt 1.", - $"INFO {typeof(EurekaClient).FullName}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' failed with status 404: " + $"DBUG {typeof(EurekaClient)}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' returned status 404 in attempt 1.", + $"INFO {typeof(EurekaClient)}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' failed with status 404: " ], options => options.WithStrictOrdering()); } @@ -266,7 +266,7 @@ public async Task RegisterAsync_LogsWarningOnCloudWithLocalhost() { using var scope = new EnvironmentVariableScope("VCAP_APPLICATION", "{}"); - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); @@ -293,13 +293,13 @@ public async Task RegisterAsync_LogsWarningOnCloudWithLocalhost() IList logMessages = capturingLoggerProvider.GetAll(); logMessages.Should().Contain( - $"WARN {typeof(EurekaClient).FullName}: Registering with hostname 'localhost' in containerized or cloud environments may not be valid. Please configure Eureka:Instance:HostName with a non-localhost address."); + $"WARN {typeof(EurekaClient)}: Registering with hostname 'localhost' in containerized or cloud environments may not be valid. Please configure Eureka:Instance:HostName with a non-localhost address."); } [Fact] public async Task RegisterAsync_SendsRequestToServer() { - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); using JsonDocument requestDocument = JsonDocument.Parse(""" { @@ -364,16 +364,16 @@ public async Task RegisterAsync_SendsRequestToServer() logMessages.Should().BeEquivalentTo( [ - $"DBUG {typeof(EurekaClient).FullName}: Sending POST request to 'http://localhost:8761/eureka/apps/FOOBAR' with body: " + + $"DBUG {typeof(EurekaClient)}: Sending POST request to 'http://localhost:8761/eureka/apps/FOOBAR' with body: " + """{"instance":{"instanceId":"some","app":"FOOBAR","ipAddr":"127.0.0.1","port":{"@enabled":"true","$":8080},"securePort":{"@enabled":"false","$":9090},"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"localhost","overriddenstatus":"UNKNOWN","metadata":{"@class":"java.util.Collections$EmptyMap"},"lastUpdatedTimestamp":"1708427732823","lastDirtyTimestamp":"1708427732823"}}.""", - $"DBUG {typeof(EurekaClient).FullName}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' returned status 204 in attempt 1." + $"DBUG {typeof(EurekaClient)}: HTTP POST request to 'http://localhost:8761/eureka/apps/FOOBAR' returned status 204 in attempt 1." ], options => options.WithStrictOrdering()); } [Fact] public async Task RegisterAsync_TriesSecondServerIfFirstOneFails() { - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); @@ -408,13 +408,13 @@ public async Task RegisterAsync_TriesSecondServerIfFirstOneFails() logMessages.Should().BeEquivalentTo( [ - $"DBUG {typeof(EurekaClient).FullName}: Sending POST request to 'http://server1:8761/apps/FOOBAR' with body: " + + $"DBUG {typeof(EurekaClient)}: Sending POST request to 'http://server1:8761/apps/FOOBAR' with body: " + """{"instance":{"instanceId":"some","app":"FOOBAR","ipAddr":"127.0.0.1","port":{"@enabled":"true","$":8080},"securePort":{"@enabled":"false","$":9090},"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"localhost","overriddenstatus":"UNKNOWN","metadata":{"@class":"java.util.Collections$EmptyMap"},"lastUpdatedTimestamp":"1708427732823","lastDirtyTimestamp":"1708427732823"}}.""", - $"DBUG {typeof(EurekaClient).FullName}: HTTP POST request to 'http://server1:8761/apps/FOOBAR' returned status 404 in attempt 1.", - $"INFO {typeof(EurekaClient).FullName}: HTTP POST request to 'http://server1:8761/apps/FOOBAR' failed with status 404: ", - $"DBUG {typeof(EurekaClient).FullName}: Sending POST request to 'http://server2:8761/apps/FOOBAR' with body: " + + $"DBUG {typeof(EurekaClient)}: HTTP POST request to 'http://server1:8761/apps/FOOBAR' returned status 404 in attempt 1.", + $"INFO {typeof(EurekaClient)}: HTTP POST request to 'http://server1:8761/apps/FOOBAR' failed with status 404: ", + $"DBUG {typeof(EurekaClient)}: Sending POST request to 'http://server2:8761/apps/FOOBAR' with body: " + """{"instance":{"instanceId":"some","app":"FOOBAR","ipAddr":"127.0.0.1","port":{"@enabled":"true","$":8080},"securePort":{"@enabled":"false","$":9090},"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"localhost","overriddenstatus":"UNKNOWN","metadata":{"@class":"java.util.Collections$EmptyMap"},"lastUpdatedTimestamp":"1708427732823","lastDirtyTimestamp":"1708427732823"}}.""", - $"DBUG {typeof(EurekaClient).FullName}: HTTP POST request to 'http://server2:8761/apps/FOOBAR' returned status 204 in attempt 2." + $"DBUG {typeof(EurekaClient)}: HTTP POST request to 'http://server2:8761/apps/FOOBAR' returned status 204 in attempt 2." ], options => options.WithStrictOrdering()); } @@ -606,7 +606,7 @@ public async Task GetApplicationsAsync_ThrowsOnBrokenJsonResponse() { const string jsonResponse = """{"applications": {"""; - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); @@ -630,11 +630,10 @@ public async Task GetApplicationsAsync_ThrowsOnBrokenJsonResponse() IList logMessages = capturingLoggerProvider.GetAll(); - logMessages.Should().BeEquivalentTo( - [ - $"DBUG {typeof(EurekaClient).FullName}: Sending GET request to 'http://localhost:8761/eureka/apps' without request body.", - $"DBUG {typeof(EurekaClient).FullName}: HTTP GET request to 'http://localhost:8761/eureka/apps' returned status 200 in attempt 1.", - $"DBUG {typeof(EurekaClient).FullName}: Failed to deserialize HTTP response from GET 'http://localhost:8761/eureka/apps'." + logMessages.Should().BeEquivalentTo([ + $"DBUG {typeof(EurekaClient)}: Sending GET request to 'http://localhost:8761/eureka/apps' without request body.", + $"DBUG {typeof(EurekaClient)}: HTTP GET request to 'http://localhost:8761/eureka/apps' returned status 200 in attempt 1.", + $"DBUG {typeof(EurekaClient)}: Failed to deserialize HTTP response from GET 'http://localhost:8761/eureka/apps'." ], options => options.WithStrictOrdering()); } @@ -713,7 +712,8 @@ public async Task GetByVipAsync_SendsRequestToServer() [Fact] public async Task Redacts_HTTP_headers() { - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("System.Net.Http.HttpClient", StringComparison.Ordinal)); + using var capturingLoggerProvider = + new CapturingLoggerProvider(category => category.StartsWith("System.Net.Http.HttpClient", StringComparison.Ordinal)); var services = new ServiceCollection(); services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace).AddProvider(capturingLoggerProvider)); diff --git a/src/Discovery/test/HttpClients.Test/RegisterMultipleDiscoveryClientsTest.cs b/src/Discovery/test/HttpClients.Test/RegisterMultipleDiscoveryClientsTest.cs index 24812b8fd8..07ef73750c 100644 --- a/src/Discovery/test/HttpClients.Test/RegisterMultipleDiscoveryClientsTest.cs +++ b/src/Discovery/test/HttpClients.Test/RegisterMultipleDiscoveryClientsTest.cs @@ -424,7 +424,7 @@ public void MultipleEurekaVCAPs_LogsWarning() using var appScope = new EnvironmentVariableScope("VCAP_APPLICATION", env1); using var servicesScope = new EnvironmentVariableScope("VCAP_SERVICES", env2); - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); using var loggerFactory = new LoggerFactory([capturingLoggerProvider]); var configurationBuilder = new ConfigurationBuilder(); @@ -434,7 +434,7 @@ public void MultipleEurekaVCAPs_LogsWarning() IList logMessages = capturingLoggerProvider.GetAll(); logMessages.Should().BeEquivalentTo( - $"WARN {typeof(EurekaCloudFoundryPostProcessor).FullName}: Multiple Eureka service bindings found, which is not supported. Using the first binding from VCAP_SERVICES."); + $"WARN {typeof(EurekaCloudFoundryPostProcessor)}: Multiple Eureka service bindings found, which is not supported. Using the first binding from VCAP_SERVICES."); } [Fact] diff --git a/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs b/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs index d1804c2e89..fa38276223 100644 --- a/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs +++ b/src/Logging/test/DynamicSerilog.Test/HostBuilderTest.cs @@ -92,12 +92,12 @@ public async Task CanPreserveDefaultConsoleLoggerProvider() logOutput.Should().Contain("SERILOG [ERR] TestError"); logOutput.Should().Contain($""" - info: {typeof(HostBuilderTest).FullName}[0] + info: {typeof(HostBuilderTest)}[0] TestInfo """); logOutput.Should().Contain($""" - fail: {typeof(HostBuilderTest).FullName}[0] + fail: {typeof(HostBuilderTest)}[0] TestError """); } @@ -376,7 +376,7 @@ public async Task DynamicLevelChangeDoesNotAffectUsageOfNativeSerilogApi() Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger(); Log.Logger.Information("TestInfoBefore"); - var loggerProvider = host.Services.GetRequiredService(); + using var loggerProvider = host.Services.GetRequiredService(); loggerProvider.SetLogLevel(string.Empty, LogLevel.Critical); Log.Logger.Information("TestInfoAfter"); diff --git a/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointHandler.cs b/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointHandler.cs index 49e9dfda00..cf4b71401a 100644 --- a/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointHandler.cs +++ b/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointHandler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Steeltoe.Common; @@ -19,6 +20,7 @@ internal sealed class CloudFoundryEndpointHandler : ICloudFoundryEndpointHandler { private readonly IOptionsMonitor _managementOptionsMonitor; private readonly IOptionsMonitor _endpointOptionsMonitor; + private readonly IHttpContextAccessor _httpContextAccessor; private readonly IEndpointOptionsMonitorProvider[] _optionsMonitorProviderArray; private readonly ILogger _hypermediaServiceLogger; @@ -26,11 +28,12 @@ internal sealed class CloudFoundryEndpointHandler : ICloudFoundryEndpointHandler public CloudFoundryEndpointHandler(IOptionsMonitor managementOptionsMonitor, IOptionsMonitor endpointOptionsMonitor, IEnumerable endpointOptionsMonitorProviders, - ILoggerFactory loggerFactory) + IHttpContextAccessor httpContextAccessor, ILoggerFactory loggerFactory) { ArgumentNullException.ThrowIfNull(managementOptionsMonitor); ArgumentNullException.ThrowIfNull(endpointOptionsMonitor); ArgumentNullException.ThrowIfNull(endpointOptionsMonitorProviders); + ArgumentNullException.ThrowIfNull(httpContextAccessor); ArgumentNullException.ThrowIfNull(loggerFactory); IEndpointOptionsMonitorProvider[] optionsMonitorProviderArray = endpointOptionsMonitorProviders.ToArray(); @@ -38,6 +41,7 @@ public CloudFoundryEndpointHandler(IOptionsMonitor management _managementOptionsMonitor = managementOptionsMonitor; _endpointOptionsMonitor = endpointOptionsMonitor; + _httpContextAccessor = httpContextAccessor; _optionsMonitorProviderArray = optionsMonitorProviderArray; _hypermediaServiceLogger = loggerFactory.CreateLogger(); } @@ -46,8 +50,8 @@ public async Task InvokeAsync(string baseUrl, CancellationToken cancellat { ArgumentException.ThrowIfNullOrWhiteSpace(baseUrl); - var hypermediaService = - new HypermediaService(_managementOptionsMonitor, _endpointOptionsMonitor, _optionsMonitorProviderArray, _hypermediaServiceLogger); + var hypermediaService = new HypermediaService(_managementOptionsMonitor, _endpointOptionsMonitor, _optionsMonitorProviderArray, _httpContextAccessor, + _hypermediaServiceLogger); Links result = hypermediaService.Invoke(new Uri(baseUrl)); return await Task.FromResult(result); diff --git a/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointMiddleware.cs b/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointMiddleware.cs index d265774afb..f37fa3df42 100644 --- a/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointMiddleware.cs +++ b/src/Management/src/Endpoint/Actuators/CloudFoundry/CloudFoundryEndpointMiddleware.cs @@ -28,8 +28,8 @@ internal sealed class CloudFoundryEndpointMiddleware( ? headerScheme.ToString() : httpContext.Request.Scheme; - string uri = $"{scheme}://{httpContext.Request.Host}{httpContext.Request.PathBase}{httpContext.Request.Path}"; - return Task.FromResult(uri); + string requestUri = $"{scheme}://{httpContext.Request.Host}{httpContext.Request.Path}"; + return Task.FromResult(requestUri); } protected override async Task InvokeEndpointHandlerAsync(string? uri, CancellationToken cancellationToken) diff --git a/src/Management/src/Endpoint/Actuators/CloudFoundry/EndpointServiceCollectionExtensions.cs b/src/Management/src/Endpoint/Actuators/CloudFoundry/EndpointServiceCollectionExtensions.cs index c376f108af..de556c0037 100644 --- a/src/Management/src/Endpoint/Actuators/CloudFoundry/EndpointServiceCollectionExtensions.cs +++ b/src/Management/src/Endpoint/Actuators/CloudFoundry/EndpointServiceCollectionExtensions.cs @@ -43,6 +43,8 @@ public static IServiceCollection AddCloudFoundryActuator(this IServiceCollection { ArgumentNullException.ThrowIfNull(services); + services.AddHttpContextAccessor(); + services.AddCoreActuatorServices(configureMiddleware); diff --git a/src/Management/src/Endpoint/Actuators/Hypermedia/EndpointServiceCollectionExtensions.cs b/src/Management/src/Endpoint/Actuators/Hypermedia/EndpointServiceCollectionExtensions.cs index 82e10e1898..6bc092f804 100644 --- a/src/Management/src/Endpoint/Actuators/Hypermedia/EndpointServiceCollectionExtensions.cs +++ b/src/Management/src/Endpoint/Actuators/Hypermedia/EndpointServiceCollectionExtensions.cs @@ -39,6 +39,8 @@ public static IServiceCollection AddHypermediaActuator(this IServiceCollection s { ArgumentNullException.ThrowIfNull(services); + services.AddHttpContextAccessor(); + services.AddCoreActuatorServices(configureMiddleware); diff --git a/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointHandler.cs b/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointHandler.cs index 9071e84130..9460d9363e 100644 --- a/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointHandler.cs +++ b/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointHandler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Steeltoe.Common; @@ -17,6 +18,7 @@ internal sealed class HypermediaEndpointHandler : IHypermediaEndpointHandler { private readonly IOptionsMonitor _managementOptionsMonitor; private readonly IOptionsMonitor _endpointOptionsMonitor; + private readonly IHttpContextAccessor _httpContextAccessor; private readonly IEndpointOptionsMonitorProvider[] _endpointOptionsMonitorProviderArray; private readonly ILogger _hypermediaServiceLogger; @@ -24,11 +26,12 @@ internal sealed class HypermediaEndpointHandler : IHypermediaEndpointHandler public HypermediaEndpointHandler(IOptionsMonitor managementOptionsMonitor, IOptionsMonitor endpointOptionsMonitor, IEnumerable endpointOptionsMonitorProviders, - ILoggerFactory loggerFactory) + IHttpContextAccessor httpContextAccessor, ILoggerFactory loggerFactory) { ArgumentNullException.ThrowIfNull(managementOptionsMonitor); ArgumentNullException.ThrowIfNull(endpointOptionsMonitor); ArgumentNullException.ThrowIfNull(endpointOptionsMonitorProviders); + ArgumentNullException.ThrowIfNull(httpContextAccessor); ArgumentNullException.ThrowIfNull(loggerFactory); IEndpointOptionsMonitorProvider[] endpointOptionsMonitorProviderArray = endpointOptionsMonitorProviders.ToArray(); @@ -36,6 +39,7 @@ public HypermediaEndpointHandler(IOptionsMonitor managementOp _managementOptionsMonitor = managementOptionsMonitor; _endpointOptionsMonitor = endpointOptionsMonitor; + _httpContextAccessor = httpContextAccessor; _endpointOptionsMonitorProviderArray = endpointOptionsMonitorProviderArray; _hypermediaServiceLogger = loggerFactory.CreateLogger(); } @@ -44,7 +48,9 @@ public Task InvokeAsync(string baseUrl, CancellationToken cancellationTok { ArgumentException.ThrowIfNullOrWhiteSpace(baseUrl); - var service = new HypermediaService(_managementOptionsMonitor, _endpointOptionsMonitor, _endpointOptionsMonitorProviderArray, _hypermediaServiceLogger); + var service = new HypermediaService(_managementOptionsMonitor, _endpointOptionsMonitor, _endpointOptionsMonitorProviderArray, _httpContextAccessor, + _hypermediaServiceLogger); + Links result = service.Invoke(new Uri(baseUrl)); return Task.FromResult(result); } diff --git a/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointMiddleware.cs b/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointMiddleware.cs index 34a6b425cc..b4f3bd15b9 100644 --- a/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointMiddleware.cs +++ b/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaEndpointMiddleware.cs @@ -23,12 +23,7 @@ internal sealed class HypermediaEndpointMiddleware( ? headerScheme.ToString() : httpContext.Request.Scheme; - // request.Host automatically includes or excludes the port based on whether it is standard for the scheme - // ... except when we manually change the scheme to match the X-Forwarded-Proto - string requestUri = scheme == "https" && httpContext.Request.Host.Port == 443 - ? $"{scheme}://{httpContext.Request.Host.Host}{httpContext.Request.PathBase}{httpContext.Request.Path}" - : $"{scheme}://{httpContext.Request.Host}{httpContext.Request.PathBase}{httpContext.Request.Path}"; - + string requestUri = $"{scheme}://{httpContext.Request.Host}{httpContext.Request.Path}"; return Task.FromResult(requestUri); } diff --git a/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaService.cs b/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaService.cs index 4e667ea69e..ba0b3c7890 100644 --- a/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaService.cs +++ b/src/Management/src/Endpoint/Actuators/Hypermedia/HypermediaService.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Steeltoe.Common; @@ -16,37 +17,44 @@ internal sealed class HypermediaService private readonly IOptionsMonitor _managementOptionsMonitor; private readonly EndpointOptions _endpointOptions; private readonly ICollection _endpointOptionsMonitorProviders; + private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger _logger; public HypermediaService(IOptionsMonitor managementOptionsMonitor, IOptionsMonitor hypermediaEndpointOptionsMonitor, - ICollection endpointOptionsMonitorProviders, ILogger logger) + ICollection endpointOptionsMonitorProviders, IHttpContextAccessor httpContextAccessor, + ILogger logger) { ArgumentNullException.ThrowIfNull(managementOptionsMonitor); ArgumentNullException.ThrowIfNull(hypermediaEndpointOptionsMonitor); ArgumentNullException.ThrowIfNull(endpointOptionsMonitorProviders); + ArgumentNullException.ThrowIfNull(httpContextAccessor); ArgumentGuard.ElementsNotNull(endpointOptionsMonitorProviders); ArgumentNullException.ThrowIfNull(logger); _managementOptionsMonitor = managementOptionsMonitor; _endpointOptions = hypermediaEndpointOptionsMonitor.CurrentValue; _endpointOptionsMonitorProviders = endpointOptionsMonitorProviders; + _httpContextAccessor = httpContextAccessor; _logger = logger; } public HypermediaService(IOptionsMonitor managementOptionsMonitor, IOptionsMonitor cloudFoundryEndpointOptionsMonitor, - ICollection endpointOptionsMonitorProviders, ILogger logger) + ICollection endpointOptionsMonitorProviders, IHttpContextAccessor httpContextAccessor, + ILogger logger) { ArgumentNullException.ThrowIfNull(managementOptionsMonitor); ArgumentNullException.ThrowIfNull(cloudFoundryEndpointOptionsMonitor); ArgumentNullException.ThrowIfNull(endpointOptionsMonitorProviders); + ArgumentNullException.ThrowIfNull(httpContextAccessor); ArgumentGuard.ElementsNotNull(endpointOptionsMonitorProviders); ArgumentNullException.ThrowIfNull(logger); _managementOptionsMonitor = managementOptionsMonitor; _endpointOptions = cloudFoundryEndpointOptionsMonitor.CurrentValue; _endpointOptionsMonitorProviders = endpointOptionsMonitorProviders; + _httpContextAccessor = httpContextAccessor; _logger = logger; } @@ -68,6 +76,11 @@ public Links Invoke(Uri baseUrl) bool skipExposureCheck = PermissionsProvider.IsCloudFoundryRequest(baseUrl.PathAndQuery); string? basePath = managementOptions.GetBasePath(baseUrl.AbsolutePath); + if (_httpContextAccessor.HttpContext?.Request != null) + { + basePath = $"{_httpContextAccessor.HttpContext.Request.PathBase}{basePath}"; + } + foreach (EndpointOptions endpointOptions in _endpointOptionsMonitorProviders.Select(provider => provider.Get()).OrderBy(options => options.Id)) { if (endpointOptions.Id == null || !endpointOptions.IsEnabled(managementOptions)) diff --git a/src/Management/src/Endpoint/ConfigureActuatorsMiddlewareStartupFilter.cs b/src/Management/src/Endpoint/ConfigureActuatorsMiddlewareStartupFilter.cs index 682b636002..961705703e 100644 --- a/src/Management/src/Endpoint/ConfigureActuatorsMiddlewareStartupFilter.cs +++ b/src/Management/src/Endpoint/ConfigureActuatorsMiddlewareStartupFilter.cs @@ -2,15 +2,27 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Steeltoe.Management.Endpoint.Actuators.CloudFoundry; namespace Steeltoe.Management.Endpoint; internal sealed class ConfigureActuatorsMiddlewareStartupFilter : IStartupFilter { + private readonly ILogger _logger; + + public ConfigureActuatorsMiddlewareStartupFilter(ILogger logger) + { + ArgumentNullException.ThrowIfNull(logger); + + _logger = logger; + } + public Action Configure(Action next) { ArgumentNullException.ThrowIfNull(next); @@ -33,9 +45,30 @@ public Action Configure(Action next) app.UseCloudFoundrySecurity(); } + int? beforeMiddlewareCount = GetMiddlewareCount(app); next.Invoke(app); + int? afterMiddlewareCount = GetMiddlewareCount(app); + + if (beforeMiddlewareCount != afterMiddlewareCount) + { + _logger.LogWarning( + "Actuators were registered with automatic middleware setup, and at least one additional middleware was registered afterward. This combination is usually undesired. " + + "To remove this warning, either remove the additional middleware registration or set configureMiddleware to false when registering actuators."); + } app.UseActuatorEndpoints(); }; } + + private static int? GetMiddlewareCount(IApplicationBuilder app) + { + FieldInfo? componentsField = app.GetType().GetField("_components", BindingFlags.NonPublic | BindingFlags.Instance); + return componentsField?.GetValue(app) is List> components ? components.Count(IsMiddleware) : null; + } + + private static bool IsMiddleware(Func component) + { + // This type exists so that ASP.NET Core can identify where to inject UseRouting. It is not a real middleware. + return component.Target == null || component.Target.ToString() != "Microsoft.AspNetCore.Builder.WebApplicationBuilder+WireSourcePipeline"; + } } diff --git a/src/Management/test/Endpoint.Test/Actuators/All/AllActuatorsTest.cs b/src/Management/test/Endpoint.Test/Actuators/All/AllActuatorsTest.cs index 1efdbebb63..b6d59e1afe 100644 --- a/src/Management/test/Endpoint.Test/Actuators/All/AllActuatorsTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/All/AllActuatorsTest.cs @@ -2,10 +2,12 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors.Infrastructure; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Steeltoe.Common.TestResources; using Steeltoe.Management.Endpoint.Actuators.All; @@ -132,4 +134,24 @@ public async Task Does_not_register_duplicate_services(HostBuilderType hostBuild host.Services.GetServices().Should().ContainSingle(); host.Services.GetServices().OfType().Should().ContainSingle(); } + + [Fact] + public async Task Logs_warning_when_custom_middleware_is_registered_without_configureMiddleware_false() + { + using var capturingLoggerProvider = new CapturingLoggerProvider((_, logLevel) => logLevel >= LogLevel.Warning); + + WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); + builder.Logging.AddProvider(capturingLoggerProvider); + builder.Services.AddAllActuators(); + await using WebApplication host = builder.Build(); + + host.UseRouting(); + host.UseActuatorEndpoints(); + + await host.StartAsync(TestContext.Current.CancellationToken); + + capturingLoggerProvider.GetAll().Should().Contain($"WARN {typeof(ConfigureActuatorsMiddlewareStartupFilter)}: " + + "Actuators were registered with automatic middleware setup, and at least one additional middleware was registered afterward. This combination is usually undesired. " + + "To remove this warning, either remove the additional middleware registration or set configureMiddleware to false when registering actuators."); + } } diff --git a/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundryActuatorTest.cs b/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundryActuatorTest.cs index ec3379712f..5484052d8a 100644 --- a/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundryActuatorTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundryActuatorTest.cs @@ -421,6 +421,57 @@ public async Task Hides_disabled_actuators_and_ignores_exposure() """); } + [Fact] + public async Task Ignores_exposure_with_UsePathBase() + { + using var scope = new EnvironmentVariableScope("VCAP_APPLICATION", VcapApplicationForMock); + + var appSettings = new Dictionary + { + ["Management:Endpoints:Actuator:Exposure:Include:0"] = "*", + ["Management:Endpoints:Actuator:Exposure:Exclude:1"] = "loggers" + }; + + WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); + builder.Configuration.AddCloudFoundry(); + builder.Configuration.AddInMemoryCollection(appSettings); + builder.Services.AddCloudFoundryActuator(false); + builder.Services.AddLoggersActuator(false); + + await using WebApplication host = builder.Build(); + + host.UsePathBase("/some/prefix"); + host.UseRouting(); + host.UseCloudFoundrySecurity(); + host.UseActuatorEndpoints(); + + host.Services.GetRequiredService().Using(CloudControllerPermissionsMock.GetHttpMessageHandler()); + await host.StartAsync(TestContext.Current.CancellationToken); + using HttpClient httpClient = host.GetTestClient(); + + HttpResponseMessage response = await AuthenticatedGetAsync(httpClient, new Uri("http://localhost/some/prefix/cloudfoundryapplication")); + + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string responseBody = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); + + responseBody.Should().BeJson(""" + { + "type": "steeltoe", + "_links": { + "loggers": { + "href": "http://localhost/some/prefix/cloudfoundryapplication/loggers", + "templated": false + }, + "self": { + "href": "http://localhost/some/prefix/cloudfoundryapplication", + "templated": false + } + } + } + """); + } + [Theory] [InlineData("http://somehost:1234", "https://somehost:1234", "https")] [InlineData("http://somehost:443", "https://somehost", "https")] diff --git a/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundrySecurityMiddlewareTest.cs b/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundrySecurityMiddlewareTest.cs index c3639b9ac4..99a64e2782 100644 --- a/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundrySecurityMiddlewareTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/CloudFoundry/CloudFoundrySecurityMiddlewareTest.cs @@ -331,7 +331,8 @@ public async Task RedactsHttpHeaders() ["vcap:application:cf_api"] = "https://example.api.com" }; - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("System.Net.Http.HttpClient", StringComparison.Ordinal)); + using var capturingLoggerProvider = + new CapturingLoggerProvider(category => category.StartsWith("System.Net.Http.HttpClient", StringComparison.Ordinal)); WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); builder.Configuration.AddInMemoryCollection(appSettings); diff --git a/src/Management/test/Endpoint.Test/Actuators/DbMigrations/DbMigrationsActuatorTest.cs b/src/Management/test/Endpoint.Test/Actuators/DbMigrations/DbMigrationsActuatorTest.cs index 864d6d45bb..491af47e67 100644 --- a/src/Management/test/Endpoint.Test/Actuators/DbMigrations/DbMigrationsActuatorTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/DbMigrations/DbMigrationsActuatorTest.cs @@ -190,6 +190,6 @@ public async Task Endpoint_returns_all_migrations_when_pending_migrations_are_un """); IList logLines = loggerProvider.GetAll(); - logLines.Should().Contain($"WARN {typeof(DbMigrationsEndpointHandler).FullName}: Failed to load pending/applied migrations, returning all migrations."); + logLines.Should().Contain($"WARN {typeof(DbMigrationsEndpointHandler)}: Failed to load pending/applied migrations, returning all migrations."); } } diff --git a/src/Management/test/Endpoint.Test/Actuators/HeapDump/HeapDumperTest.cs b/src/Management/test/Endpoint.Test/Actuators/HeapDump/HeapDumperTest.cs index bde13d99b7..c1cfe1045c 100644 --- a/src/Management/test/Endpoint.Test/Actuators/HeapDump/HeapDumperTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/HeapDump/HeapDumperTest.cs @@ -50,14 +50,14 @@ public async Task Can_create_heap_dump(HeapDumpType heapDumpType, string fileNam File.Delete(path); IList logLines = loggerProvider.GetAll(); - logLines.Should().Contain($"INFO {typeof(HeapDumper).FullName}: Attempting to create a {description}."); - logLines.Should().Contain($"INFO {typeof(HeapDumper).FullName}: Successfully created a {description}."); + logLines.Should().Contain($"INFO {typeof(HeapDumper)}: Attempting to create a {description}."); + logLines.Should().Contain($"INFO {typeof(HeapDumper)}: Successfully created a {description}."); if (heapDumpType == HeapDumpType.GCDump) { string logText = loggerProvider.GetAsText(); - logText.Should().Contain($"TRCE {typeof(HeapDumper).FullName}: Captured log from gcdump:"); + logText.Should().Contain($"TRCE {typeof(HeapDumper)}: Captured log from gcdump:"); logText.Should().Contain("Done Dumping .NET heap success=True"); } } diff --git a/src/Management/test/Endpoint.Test/Actuators/Hypermedia/HypermediaActuatorTest.cs b/src/Management/test/Endpoint.Test/Actuators/Hypermedia/HypermediaActuatorTest.cs index 1b9e98e5e5..abba10aa7b 100644 --- a/src/Management/test/Endpoint.Test/Actuators/Hypermedia/HypermediaActuatorTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/Hypermedia/HypermediaActuatorTest.cs @@ -327,7 +327,7 @@ public async Task Logs_warning_when_duplicate_endpoint_ID_detected() response.StatusCode.Should().Be(HttpStatusCode.OK); IList logLines = loggerProvider.GetAll(); - logLines.Should().ContainSingle().Which.Should().Be($"WARN {typeof(HypermediaService).FullName}: Duplicate endpoint with ID 'same' detected."); + logLines.Should().ContainSingle().Which.Should().Be($"WARN {typeof(HypermediaService)}: Duplicate endpoint with ID 'same' detected."); } [Fact] @@ -370,6 +370,44 @@ public async Task Can_use_slash_as_management_path() """); } + [Fact] + public async Task Includes_base_path_from_UsePathBase_in_hypermedia_links() + { + WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(); + builder.Services.AddHypermediaActuator(false); + builder.Services.AddInfoActuator(false); + await using WebApplication host = builder.Build(); + + host.UsePathBase("/some/prefix"); + host.UseRouting(); + host.UseActuatorEndpoints(); + + await host.StartAsync(TestContext.Current.CancellationToken); + using HttpClient httpClient = host.GetTestClient(); + + HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://localhost/some/prefix/actuator"), TestContext.Current.CancellationToken); + + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string responseBody = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); + + responseBody.Should().BeJson(""" + { + "type": "steeltoe", + "_links": { + "info": { + "href": "http://localhost/some/prefix/actuator/info", + "templated": false + }, + "self": { + "href": "http://localhost/some/prefix/actuator", + "templated": false + } + } + } + """); + } + [Theory] [InlineData("http://somehost:1234", "https://somehost:1234", "https")] [InlineData("http://somehost:443", "https://somehost", "https")] diff --git a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RouteMappingsActuatorTest.cs b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RouteMappingsActuatorTest.cs index cdbf2d628f..3262df4951 100644 --- a/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RouteMappingsActuatorTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/RouteMappings/RouteMappingsActuatorTest.cs @@ -183,7 +183,7 @@ public async Task Returns_no_endpoints_and_logs_warning_when_conventional_routin """); IList logMessages = loggerProvider.GetAll(); - logMessages.Should().Contain($"WARN {typeof(AspNetEndpointProvider).FullName}: Conventional routing is not supported."); + logMessages.Should().Contain($"WARN {typeof(AspNetEndpointProvider)}: Conventional routing is not supported."); } [Theory] diff --git a/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs b/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs index 0cedf51ef4..29f31200f3 100644 --- a/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/ThreadDump/EventPipeThreadDumperTest.cs @@ -52,11 +52,11 @@ public async Task Can_resolve_source_location_from_pdb() backgroundThread.Join(); IList logLines = loggerProvider.GetAll(); - logLines.Should().Contain($"INFO {typeof(EventPipeThreadDumper).FullName}: Attempting to create a thread dump."); - logLines.Should().Contain($"INFO {typeof(EventPipeThreadDumper).FullName}: Successfully created a thread dump."); + logLines.Should().Contain($"INFO {typeof(EventPipeThreadDumper)}: Attempting to create a thread dump."); + logLines.Should().Contain($"INFO {typeof(EventPipeThreadDumper)}: Successfully created a thread dump."); string logText = loggerProvider.GetAsText(); - logText.Should().Contain($"TRCE {typeof(EventPipeThreadDumper).FullName}: Captured log from thread dump:"); + logText.Should().Contain($"TRCE {typeof(EventPipeThreadDumper)}: Captured log from thread dump:"); logText.Should().Contain("Created SymbolReader with SymbolPath"); } diff --git a/src/Management/test/Tasks.Test/TaskHostExtensionsTest.cs b/src/Management/test/Tasks.Test/TaskHostExtensionsTest.cs index 03a7917f7c..10e6f5db60 100644 --- a/src/Management/test/Tasks.Test/TaskHostExtensionsTest.cs +++ b/src/Management/test/Tasks.Test/TaskHostExtensionsTest.cs @@ -198,7 +198,7 @@ public async Task WebApplication_LogsErrorOnUnknownTask() WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create(args); - var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); + using var capturingLoggerProvider = new CapturingLoggerProvider(category => category.StartsWith("Steeltoe.", StringComparison.Ordinal)); builder.Services.AddLogging(options => options.AddProvider(capturingLoggerProvider)); WebApplication app = builder.Build();