Add WireMockAspNetCoreLogger to log Kestrel warnings/errors (#1432)

* Add WireMockAspNetCoreLogger

* fix tests

* x

* .
This commit is contained in:
Stef Heyenrath
2026-03-14 10:30:56 +01:00
committed by GitHub
parent d08ce944b6
commit ca788cb9b0
9 changed files with 159 additions and 37 deletions

View File

@@ -0,0 +1,38 @@
// Copyright © WireMock.Net
using Microsoft.Extensions.Logging;
namespace WireMock.Logging;
internal sealed class WireMockAspNetCoreLogger(IWireMockLogger logger, string categoryName) : ILogger
{
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Warning;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
var message = formatter(state, exception);
if (exception != null)
{
message = $"{message} | Exception: {exception}";
}
switch (logLevel)
{
case LogLevel.Warning:
logger.Warn("[{0}] {1}", categoryName, message);
break;
default:
logger.Error("[{0}] {1}", categoryName, message);
break;
}
}
}

View File

@@ -0,0 +1,19 @@
// Copyright © WireMock.Net
using Microsoft.Extensions.Logging;
namespace WireMock.Logging;
internal sealed class WireMockAspNetCoreLoggerProvider : ILoggerProvider
{
private readonly IWireMockLogger _logger;
public WireMockAspNetCoreLoggerProvider(IWireMockLogger logger)
{
_logger = logger;
}
public ILogger CreateLogger(string categoryName) => new WireMockAspNetCoreLogger(_logger, categoryName);
public void Dispose() { }
}

View File

@@ -1,9 +1,9 @@
// Copyright © WireMock.Net
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Stef.Validation;
using WireMock.Logging;
using WireMock.Owin.Mappers;
@@ -57,6 +57,12 @@ internal partial class AspNetCoreSelfHost
_host = builder
.UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
.ConfigureAppConfigurationUsingEnvironmentVariables()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddProvider(new WireMockAspNetCoreLoggerProvider(_logger));
logging.SetMinimumLevel(LogLevel.Warning);
})
.ConfigureServices(services =>
{
services.AddSingleton(_wireMockMiddlewareOptions);
@@ -169,10 +175,10 @@ internal partial class AspNetCoreSelfHost
return _host.RunAsync(token);
}
catch (Exception e)
catch (Exception ex)
{
RunningException = e;
_logger.Error(e.ToString());
RunningException = ex;
_logger.Error("Error while RunAsync", ex);
IsStarted = false;

View File

@@ -1,9 +1,7 @@
// Copyright © WireMock.Net
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
@@ -88,19 +86,15 @@ namespace WireMock.Owin.Mappers
break;
}
var statusCodeType = responseMessage.StatusCode?.GetType();
if (statusCodeType != null)
if (responseMessage.StatusCode is HttpStatusCode or int)
{
if (statusCodeType == typeof(int) || statusCodeType == typeof(int?) || statusCodeType.GetTypeInfo().IsEnum)
{
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
}
else if (statusCodeType == typeof(string))
{
// Note: this case will also match on null
int.TryParse(responseMessage.StatusCode as string, out var statusCodeTypeAsInt);
response.StatusCode = MapStatusCode(statusCodeTypeAsInt);
}
response.StatusCode = MapStatusCode((int) responseMessage.StatusCode);
}
else if (responseMessage.StatusCode is string statusCodeAsString)
{
// Note: this case will also match on null
_ = int.TryParse(statusCodeAsString, out var statusCodeTypeAsInt);
response.StatusCode = MapStatusCode(statusCodeTypeAsInt);
}
SetResponseHeaders(responseMessage, bytes != null, response);

View File

@@ -3,9 +3,7 @@
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Http;
using AnyOfTypes;
using JetBrains.Annotations;
using JsonConverter.Newtonsoft.Json;