Skip to content

Commit

Permalink
Merge pull request #305 from dnperfors/issue174-configurable-properties
Browse files Browse the repository at this point in the history
Add GetMessageTemplateProperties to options
  • Loading branch information
nblumhardt committed Aug 29, 2022
2 parents 1d99211 + ccd73c3 commit cd2a857
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 8 deletions.
13 changes: 5 additions & 8 deletions src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Serilog.Extensions.Hosting;
using Serilog.Parsing;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -32,6 +33,7 @@ class RequestLoggingMiddleware
readonly MessageTemplate _messageTemplate;
readonly Action<IDiagnosticContext, HttpContext> _enrichDiagnosticContext;
readonly Func<HttpContext, double, Exception, LogEventLevel> _getLevel;
readonly Func<HttpContext, string, double, int, IEnumerable<LogEventProperty>> _getMessageTemplateProperties;
readonly ILogger _logger;
readonly bool _includeQueryInRequestPath;
static readonly LogEventProperty[] NoProperties = new LogEventProperty[0];
Expand All @@ -47,6 +49,7 @@ public RequestLoggingMiddleware(RequestDelegate next, DiagnosticContext diagnost
_messageTemplate = new MessageTemplateParser().Parse(options.MessageTemplate);
_logger = options.Logger?.ForContext<RequestLoggingMiddleware>();
_includeQueryInRequestPath = options.IncludeQueryInRequestPath;
_getMessageTemplateProperties = options.GetMessageTemplateProperties;
}

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

// Last-in (correctly) wins...
var properties = collectedProperties.Concat(new[]
{
new LogEventProperty("RequestMethod", new ScalarValue(httpContext.Request.Method)),
new LogEventProperty("RequestPath", new ScalarValue(GetPath(httpContext, _includeQueryInRequestPath))),
new LogEventProperty("StatusCode", new ScalarValue(statusCode)),
new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
});
var properties = collectedProperties.Concat(_getMessageTemplateProperties(httpContext, GetPath(httpContext, _includeQueryInRequestPath), elapsedMs, statusCode));

var evt = new LogEvent(DateTimeOffset.Now, level, ex ?? collectedException, _messageTemplate, properties);
logger.Write(evt);
Expand All @@ -123,7 +120,7 @@ static string GetPath(HttpContext httpContext, bool includeQueryInRequestPath)
{
requestPath = httpContext.Request.Path.ToString();
}

return requestPath;
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/Serilog.AspNetCore/AspNetCore/RequestLoggingOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.AspNetCore.Http;
using Serilog.Events;
using System;
using System.Collections.Generic;

// ReSharper disable UnusedAutoPropertyAccessor.Global

Expand All @@ -34,6 +35,15 @@ public class RequestLoggingOptions
: ctx.Response.StatusCode > 499
? LogEventLevel.Error
: LogEventLevel.Information;

IEnumerable<LogEventProperty> DefaultGetMessageTemplateProperties(HttpContext httpContext, string requestPath, double elapsedMs, int statusCode) =>
new[]
{
new LogEventProperty("RequestMethod", new ScalarValue(httpContext.Request.Method)),
new LogEventProperty("RequestPath", new ScalarValue(requestPath)),
new LogEventProperty("StatusCode", new ScalarValue(statusCode)),
new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
};

/// <summary>
/// Gets or sets the message template. The default value is
Expand Down Expand Up @@ -74,13 +84,19 @@ public class RequestLoggingOptions
/// </summary>
public bool IncludeQueryInRequestPath { get; set; }

/// <summary>
/// A function to specify the values of the MessageTemplateProperties.
/// </summary>
public Func<HttpContext, string, double, int, IEnumerable<LogEventProperty>> GetMessageTemplateProperties { get; set; }

/// <summary>
/// Constructor
/// </summary>
public RequestLoggingOptions()
{
GetLevel = DefaultGetLevel;
MessageTemplate = DefaultRequestCompletionMessageTemplate;
GetMessageTemplateProperties = DefaultGetMessageTemplateProperties;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using Microsoft.AspNetCore.Http;
using Serilog.Filters;
using Serilog.AspNetCore.Tests.Support;
using Serilog.Events;
using System.Net.Http;

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

[Fact]
public async Task RequestLoggingMiddlewareShouldEnrichWithCustomisedProperties()
{
var (sink, web) = Setup(options =>
{
options.MessageTemplate = "HTTP {RequestMethod} responded {Status} in {ElapsedMilliseconds:0.0000} ms";
options.GetMessageTemplateProperties = (ctx, path, elapsedMs, status) =>
new[]
{
new LogEventProperty("RequestMethod", new ScalarValue(ctx.Request.Method)),
new LogEventProperty("Status", new ScalarValue(status)),
new LogEventProperty("ElapsedMilliseconds", new ScalarValue(elapsedMs))
};
});

await web.CreateClient().GetAsync("/resource");

Assert.NotEmpty(sink.Writes);

var completionEvent = sink.Writes.First(logEvent => Matching.FromSource<RequestLoggingMiddleware>()(logEvent));

Assert.Equal("string", completionEvent.Properties["SomeString"].LiteralValue());
Assert.Equal(200, completionEvent.Properties["Status"].LiteralValue());
Assert.Equal("GET", completionEvent.Properties["RequestMethod"].LiteralValue());
Assert.True(completionEvent.Properties.ContainsKey("ElapsedMilliseconds"));
Assert.False(completionEvent.Properties.ContainsKey("Elapsed"));
}

[Fact]
public async Task RequestLoggingMiddlewareShouldEnrichWithCollectedExceptionIfNoUnhandledException()
{
Expand Down

0 comments on commit cd2a857

Please sign in to comment.