mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 22:30:41 +01:00
Add request / response logging (#151)
Add request / response logging (#151)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
@@ -28,7 +29,8 @@ namespace WireMock.Net.ConsoleApplication
|
||||
// SaveMapping = true
|
||||
//},
|
||||
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
|
||||
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); }
|
||||
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
|
||||
Logger = new WireMockConsoleLogger()
|
||||
});
|
||||
System.Console.WriteLine("FluentMockServer listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using log4net;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock.Net.StandAlone.NETCoreApp
|
||||
@@ -26,5 +28,11 @@ namespace WireMock.Net.StandAlone.NETCoreApp
|
||||
{
|
||||
Log.ErrorFormat(formatString, args);
|
||||
}
|
||||
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
Log.DebugFormat("Admin[{0}] {1}", isAdminRequest, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Net.StandAlone;
|
||||
using WireMock.Settings;
|
||||
@@ -42,6 +43,12 @@ namespace WireMock.Net.WebApplication
|
||||
{
|
||||
_logger.LogError(formatString, args);
|
||||
}
|
||||
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminrequest)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
_logger.LogDebug("Admin[{0}] {1}", isAdminrequest, message);
|
||||
}
|
||||
}
|
||||
|
||||
public WireMockService(ILogger logger, IFluentMockServerSettings settings)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Lightweight StandAlone Http Mocking Server for .Net.</Description>
|
||||
<AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle>
|
||||
<Version>1.0.3.20</Version>
|
||||
<Version>1.0.4.0</Version>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Admin.Requests;
|
||||
|
||||
namespace WireMock.Logging
|
||||
{
|
||||
@@ -43,5 +44,13 @@ namespace WireMock.Logging
|
||||
[PublicAPI]
|
||||
[StringFormatMethod("formatString")]
|
||||
void Error([NotNull] string formatString, [NotNull] params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the LogEntryModel (LogRequestModel, LogResponseModel and more).
|
||||
/// </summary>
|
||||
/// <param name="logEntryModel">The Request Log Model.</param>
|
||||
/// <param name="isAdminrequest">Defines if this request is an admin request.</param>
|
||||
[PublicAPI]
|
||||
void DebugRequestResponse([NotNull] LogEntryModel logEntryModel, bool isAdminrequest);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Requests;
|
||||
|
||||
namespace WireMock.Logging
|
||||
{
|
||||
@@ -8,6 +10,14 @@ namespace WireMock.Logging
|
||||
/// <seealso cref="IWireMockLogger" />
|
||||
public class WireMockConsoleLogger : IWireMockLogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockConsoleLogger"/> class.
|
||||
/// </summary>
|
||||
public WireMockConsoleLogger()
|
||||
{
|
||||
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||
}
|
||||
|
||||
/// <see cref="IWireMockLogger.Debug"/>
|
||||
public void Debug(string formatString, params object[] args)
|
||||
{
|
||||
@@ -32,9 +42,16 @@ namespace WireMock.Logging
|
||||
Console.WriteLine(Format("Error", formatString, args));
|
||||
}
|
||||
|
||||
/// <see cref="IWireMockLogger.DebugRequestResponse"/>
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
Console.WriteLine(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
|
||||
}
|
||||
|
||||
private static string Format(string level, string formatString, params object[] args)
|
||||
{
|
||||
string message = string.Format(formatString, args);
|
||||
var message = args.Length > 0 ? string.Format(formatString, args) : formatString;
|
||||
|
||||
return $"{DateTime.UtcNow} [{level}] : {message}";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace WireMock.Logging
|
||||
using WireMock.Admin.Requests;
|
||||
|
||||
namespace WireMock.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// WireMockNullLogger which does not log.
|
||||
@@ -25,5 +27,10 @@
|
||||
public void Error(string formatString, params object[] args)
|
||||
{
|
||||
}
|
||||
|
||||
/// <see cref="IWireMockLogger.DebugRequestResponse"/>
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Http;
|
||||
using WireMock.Serialization;
|
||||
#if !NETSTANDARD
|
||||
using Microsoft.Owin;
|
||||
#else
|
||||
@@ -153,6 +154,8 @@ namespace WireMock.Owin
|
||||
|
||||
private void LogRequest(LogEntry entry, bool addRequest)
|
||||
{
|
||||
_options.Logger.DebugRequestResponse(LogEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||
|
||||
if (addRequest)
|
||||
{
|
||||
_options.LogEntries.Add(entry);
|
||||
|
||||
70
src/WireMock.Net/Serialization/LogEntryMapper.cs
Normal file
70
src/WireMock.Net/Serialization/LogEntryMapper.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Linq;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
{
|
||||
internal static class LogEntryMapper
|
||||
{
|
||||
public static LogEntryModel Map(LogEntry logEntry)
|
||||
{
|
||||
return new LogEntryModel
|
||||
{
|
||||
Guid = logEntry.Guid,
|
||||
Request = new LogRequestModel
|
||||
{
|
||||
DateTime = logEntry.RequestMessage.DateTime,
|
||||
ClientIP = logEntry.RequestMessage.ClientIP,
|
||||
Path = logEntry.RequestMessage.Path,
|
||||
AbsoluteUrl = logEntry.RequestMessage.Url,
|
||||
Query = logEntry.RequestMessage.Query,
|
||||
Method = logEntry.RequestMessage.Method,
|
||||
Body = logEntry.RequestMessage.Body,
|
||||
BodyAsJson = logEntry.RequestMessage.BodyAsJson,
|
||||
BodyAsBytes = logEntry.RequestMessage.BodyAsBytes,
|
||||
Headers = logEntry.RequestMessage.Headers,
|
||||
Cookies = logEntry.RequestMessage.Cookies,
|
||||
BodyEncoding = logEntry.RequestMessage.BodyEncoding != null ? new EncodingModel
|
||||
{
|
||||
EncodingName = logEntry.RequestMessage.BodyEncoding.EncodingName,
|
||||
CodePage = logEntry.RequestMessage.BodyEncoding.CodePage,
|
||||
WebName = logEntry.RequestMessage.BodyEncoding.WebName
|
||||
} : null
|
||||
},
|
||||
Response = new LogResponseModel
|
||||
{
|
||||
StatusCode = logEntry.ResponseMessage.StatusCode,
|
||||
BodyDestination = logEntry.ResponseMessage.BodyDestination,
|
||||
Body = logEntry.ResponseMessage.Body,
|
||||
BodyAsJson = logEntry.ResponseMessage.BodyAsJson,
|
||||
BodyAsBytes = logEntry.ResponseMessage.BodyAsBytes,
|
||||
BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
|
||||
BodyAsFile = logEntry.ResponseMessage.BodyAsFile,
|
||||
BodyAsFileIsCached = logEntry.ResponseMessage.BodyAsFileIsCached,
|
||||
Headers = logEntry.ResponseMessage.Headers,
|
||||
BodyEncoding = logEntry.ResponseMessage.BodyEncoding != null ? new EncodingModel
|
||||
{
|
||||
EncodingName = logEntry.ResponseMessage.BodyEncoding.EncodingName,
|
||||
CodePage = logEntry.ResponseMessage.BodyEncoding.CodePage,
|
||||
WebName = logEntry.ResponseMessage.BodyEncoding.WebName
|
||||
} : null
|
||||
},
|
||||
MappingGuid = logEntry.MappingGuid,
|
||||
MappingTitle = logEntry.MappingTitle,
|
||||
RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel
|
||||
{
|
||||
TotalScore = logEntry.RequestMatchResult.TotalScore,
|
||||
TotalNumber = logEntry.RequestMatchResult.TotalNumber,
|
||||
IsPerfectMatch = logEntry.RequestMatchResult.IsPerfectMatch,
|
||||
AverageTotalScore = logEntry.RequestMatchResult.AverageTotalScore,
|
||||
MatchDetails = logEntry.RequestMatchResult.MatchDetails.Select(x => new
|
||||
{
|
||||
Name = x.Key.Name.Replace("RequestMessage", string.Empty),
|
||||
Score = x.Value
|
||||
} as object).ToList()
|
||||
} : null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -457,7 +457,7 @@ namespace WireMock.Server
|
||||
return new ResponseMessage { StatusCode = 404, Body = "Request not found" };
|
||||
}
|
||||
|
||||
var model = ToLogEntryModel(entry);
|
||||
var model = LogEntryMapper.Map(entry);
|
||||
|
||||
return ToJson(model);
|
||||
}
|
||||
@@ -478,71 +478,11 @@ namespace WireMock.Server
|
||||
{
|
||||
var result = LogEntries
|
||||
.Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
|
||||
.Select(ToLogEntryModel);
|
||||
.Select(LogEntryMapper.Map);
|
||||
|
||||
return ToJson(result);
|
||||
}
|
||||
|
||||
private LogEntryModel ToLogEntryModel(LogEntry logEntry)
|
||||
{
|
||||
return new LogEntryModel
|
||||
{
|
||||
Guid = logEntry.Guid,
|
||||
Request = new LogRequestModel
|
||||
{
|
||||
DateTime = logEntry.RequestMessage.DateTime,
|
||||
ClientIP = logEntry.RequestMessage.ClientIP,
|
||||
Path = logEntry.RequestMessage.Path,
|
||||
AbsoluteUrl = logEntry.RequestMessage.Url,
|
||||
Query = logEntry.RequestMessage.Query,
|
||||
Method = logEntry.RequestMessage.Method,
|
||||
Body = logEntry.RequestMessage.Body,
|
||||
BodyAsJson = logEntry.RequestMessage.BodyAsJson,
|
||||
BodyAsBytes = logEntry.RequestMessage.BodyAsBytes,
|
||||
Headers = logEntry.RequestMessage.Headers,
|
||||
Cookies = logEntry.RequestMessage.Cookies,
|
||||
BodyEncoding = logEntry.RequestMessage.BodyEncoding != null ? new EncodingModel
|
||||
{
|
||||
EncodingName = logEntry.RequestMessage.BodyEncoding.EncodingName,
|
||||
CodePage = logEntry.RequestMessage.BodyEncoding.CodePage,
|
||||
WebName = logEntry.RequestMessage.BodyEncoding.WebName
|
||||
} : null
|
||||
},
|
||||
Response = new LogResponseModel
|
||||
{
|
||||
StatusCode = logEntry.ResponseMessage.StatusCode,
|
||||
BodyDestination = logEntry.ResponseMessage.BodyDestination,
|
||||
Body = logEntry.ResponseMessage.Body,
|
||||
BodyAsJson = logEntry.ResponseMessage.BodyAsJson,
|
||||
BodyAsBytes = logEntry.ResponseMessage.BodyAsBytes,
|
||||
BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
|
||||
BodyAsFile = logEntry.ResponseMessage.BodyAsFile,
|
||||
BodyAsFileIsCached = logEntry.ResponseMessage.BodyAsFileIsCached,
|
||||
Headers = logEntry.ResponseMessage.Headers,
|
||||
BodyEncoding = logEntry.ResponseMessage.BodyEncoding != null ? new EncodingModel
|
||||
{
|
||||
EncodingName = logEntry.ResponseMessage.BodyEncoding.EncodingName,
|
||||
CodePage = logEntry.ResponseMessage.BodyEncoding.CodePage,
|
||||
WebName = logEntry.ResponseMessage.BodyEncoding.WebName
|
||||
} : null
|
||||
},
|
||||
MappingGuid = logEntry.MappingGuid,
|
||||
MappingTitle = logEntry.MappingTitle,
|
||||
RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel
|
||||
{
|
||||
TotalScore = logEntry.RequestMatchResult.TotalScore,
|
||||
TotalNumber = logEntry.RequestMatchResult.TotalNumber,
|
||||
IsPerfectMatch = logEntry.RequestMatchResult.IsPerfectMatch,
|
||||
AverageTotalScore = logEntry.RequestMatchResult.AverageTotalScore,
|
||||
MatchDetails = logEntry.RequestMatchResult.MatchDetails.Select(x => new
|
||||
{
|
||||
Name = x.Key.Name.Replace("RequestMessage", string.Empty),
|
||||
Score = x.Value
|
||||
} as object).ToList()
|
||||
} : null
|
||||
};
|
||||
}
|
||||
|
||||
private ResponseMessage RequestsDelete(RequestMessage requestMessage)
|
||||
{
|
||||
ResetLogEntries();
|
||||
@@ -568,7 +508,7 @@ namespace WireMock.Server
|
||||
}
|
||||
}
|
||||
|
||||
var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(ToLogEntryModel);
|
||||
var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(LogEntryMapper.Map);
|
||||
|
||||
return ToJson(result);
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ namespace WireMock.Server
|
||||
settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
|
||||
_logger = settings.Logger;
|
||||
|
||||
_logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
|
||||
_logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
|
||||
if (settings.Urls != null)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
|
||||
<AssemblyTitle>WireMock.Net</AssemblyTitle>
|
||||
<Version>1.0.3.20</Version>
|
||||
<Version>1.0.4.0</Version>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
||||
Reference in New Issue
Block a user