Skip to content

Commit cd2a857

Browse files
authored
Merge pull request #305 from dnperfors/issue174-configurable-properties
Add GetMessageTemplateProperties to options
2 parents 1d99211 + ccd73c3 commit cd2a857

File tree

3 files changed

+51
-8
lines changed

3 files changed

+51
-8
lines changed

src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Serilog.Extensions.Hosting;
1919
using Serilog.Parsing;
2020
using System;
21+
using System.Collections.Generic;
2122
using System.Diagnostics;
2223
using System.Linq;
2324
using System.Threading.Tasks;
@@ -32,6 +33,7 @@ class RequestLoggingMiddleware
3233
readonly MessageTemplate _messageTemplate;
3334
readonly Action<IDiagnosticContext, HttpContext> _enrichDiagnosticContext;
3435
readonly Func<HttpContext, double, Exception, LogEventLevel> _getLevel;
36+
readonly Func<HttpContext, string, double, int, IEnumerable<LogEventProperty>> _getMessageTemplateProperties;
3537
readonly ILogger _logger;
3638
readonly bool _includeQueryInRequestPath;
3739
static readonly LogEventProperty[] NoProperties = new LogEventProperty[0];
@@ -47,6 +49,7 @@ public RequestLoggingMiddleware(RequestDelegate next, DiagnosticContext diagnost
4749
_messageTemplate = new MessageTemplateParser().Parse(options.MessageTemplate);
4850
_logger = options.Logger?.ForContext<RequestLoggingMiddleware>();
4951
_includeQueryInRequestPath = options.IncludeQueryInRequestPath;
52+
_getMessageTemplateProperties = options.GetMessageTemplateProperties;
5053
}
5154

5255
// ReSharper disable once UnusedMember.Global
@@ -90,13 +93,7 @@ bool LogCompletion(HttpContext httpContext, DiagnosticContextCollector collector
9093
collectedProperties = NoProperties;
9194

9295
// Last-in (correctly) wins...
93-
var properties = collectedProperties.Concat(new[]
94-
{
95-
new LogEventProperty("RequestMethod", new ScalarValue(httpContext.Request.Method)),
96-
new LogEventProperty("RequestPath", new ScalarValue(GetPath(httpContext, _includeQueryInRequestPath))),
97-
new LogEventProperty("StatusCode", new ScalarValue(statusCode)),
98-
new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
99-
});
96+
var properties = collectedProperties.Concat(_getMessageTemplateProperties(httpContext, GetPath(httpContext, _includeQueryInRequestPath), elapsedMs, statusCode));
10097

10198
var evt = new LogEvent(DateTimeOffset.Now, level, ex ?? collectedException, _messageTemplate, properties);
10299
logger.Write(evt);
@@ -123,7 +120,7 @@ static string GetPath(HttpContext httpContext, bool includeQueryInRequestPath)
123120
{
124121
requestPath = httpContext.Request.Path.ToString();
125122
}
126-
123+
127124
return requestPath;
128125
}
129126
}

src/Serilog.AspNetCore/AspNetCore/RequestLoggingOptions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.AspNetCore.Http;
1616
using Serilog.Events;
1717
using System;
18+
using System.Collections.Generic;
1819

1920
// ReSharper disable UnusedAutoPropertyAccessor.Global
2021

@@ -34,6 +35,15 @@ static LogEventLevel DefaultGetLevel(HttpContext ctx, double _, Exception ex) =>
3435
: ctx.Response.StatusCode > 499
3536
? LogEventLevel.Error
3637
: LogEventLevel.Information;
38+
39+
IEnumerable<LogEventProperty> DefaultGetMessageTemplateProperties(HttpContext httpContext, string requestPath, double elapsedMs, int statusCode) =>
40+
new[]
41+
{
42+
new LogEventProperty("RequestMethod", new ScalarValue(httpContext.Request.Method)),
43+
new LogEventProperty("RequestPath", new ScalarValue(requestPath)),
44+
new LogEventProperty("StatusCode", new ScalarValue(statusCode)),
45+
new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
46+
};
3747

3848
/// <summary>
3949
/// Gets or sets the message template. The default value is
@@ -74,13 +84,19 @@ static LogEventLevel DefaultGetLevel(HttpContext ctx, double _, Exception ex) =>
7484
/// </summary>
7585
public bool IncludeQueryInRequestPath { get; set; }
7686

87+
/// <summary>
88+
/// A function to specify the values of the MessageTemplateProperties.
89+
/// </summary>
90+
public Func<HttpContext, string, double, int, IEnumerable<LogEventProperty>> GetMessageTemplateProperties { get; set; }
91+
7792
/// <summary>
7893
/// Constructor
7994
/// </summary>
8095
public RequestLoggingOptions()
8196
{
8297
GetLevel = DefaultGetLevel;
8398
MessageTemplate = DefaultRequestCompletionMessageTemplate;
99+
GetMessageTemplateProperties = DefaultGetMessageTemplateProperties;
84100
}
85101
}
86102
}

test/Serilog.AspNetCore.Tests/SerilogWebHostBuilderExtensionsTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
using Microsoft.AspNetCore.Http;
1313
using Serilog.Filters;
1414
using Serilog.AspNetCore.Tests.Support;
15+
using Serilog.Events;
16+
using System.Net.Http;
1517

1618
// Newer frameworks provide IHostBuilder
1719
#pragma warning disable CS0618
@@ -66,6 +68,34 @@ public async Task RequestLoggingMiddlewareShouldEnrich()
6668
Assert.True(completionEvent.Properties.ContainsKey("Elapsed"));
6769
}
6870

71+
[Fact]
72+
public async Task RequestLoggingMiddlewareShouldEnrichWithCustomisedProperties()
73+
{
74+
var (sink, web) = Setup(options =>
75+
{
76+
options.MessageTemplate = "HTTP {RequestMethod} responded {Status} in {ElapsedMilliseconds:0.0000} ms";
77+
options.GetMessageTemplateProperties = (ctx, path, elapsedMs, status) =>
78+
new[]
79+
{
80+
new LogEventProperty("RequestMethod", new ScalarValue(ctx.Request.Method)),
81+
new LogEventProperty("Status", new ScalarValue(status)),
82+
new LogEventProperty("ElapsedMilliseconds", new ScalarValue(elapsedMs))
83+
};
84+
});
85+
86+
await web.CreateClient().GetAsync("/resource");
87+
88+
Assert.NotEmpty(sink.Writes);
89+
90+
var completionEvent = sink.Writes.First(logEvent => Matching.FromSource<RequestLoggingMiddleware>()(logEvent));
91+
92+
Assert.Equal("string", completionEvent.Properties["SomeString"].LiteralValue());
93+
Assert.Equal(200, completionEvent.Properties["Status"].LiteralValue());
94+
Assert.Equal("GET", completionEvent.Properties["RequestMethod"].LiteralValue());
95+
Assert.True(completionEvent.Properties.ContainsKey("ElapsedMilliseconds"));
96+
Assert.False(completionEvent.Properties.ContainsKey("Elapsed"));
97+
}
98+
6999
[Fact]
70100
public async Task RequestLoggingMiddlewareShouldEnrichWithCollectedExceptionIfNoUnhandledException()
71101
{

0 commit comments

Comments
 (0)