Skip to content

Commit c15ab6d

Browse files
authored
Merge pull request #271 from angularsen/agl/diagnostic-exception
Log exception set in IDiagnosticContext
2 parents f1cdcd7 + b8081d8 commit c15ab6d

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

src/Serilog.AspNetCore/AspNetCore/RequestLoggingMiddleware.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ bool LogCompletion(HttpContext httpContext, DiagnosticContextCollector collector
8686
// Enrich diagnostic context
8787
_enrichDiagnosticContext?.Invoke(_diagnosticContext, httpContext);
8888

89-
if (!collector.TryComplete(out var collectedProperties))
89+
if (!collector.TryComplete(out var collectedProperties, out var collectedException))
9090
collectedProperties = NoProperties;
9191

9292
// Last-in (correctly) wins...
@@ -98,7 +98,7 @@ bool LogCompletion(HttpContext httpContext, DiagnosticContextCollector collector
9898
new LogEventProperty("Elapsed", new ScalarValue(elapsedMs))
9999
});
100100

101-
var evt = new LogEvent(DateTimeOffset.Now, level, ex, _messageTemplate, properties);
101+
var evt = new LogEvent(DateTimeOffset.Now, level, ex ?? collectedException, _messageTemplate, properties);
102102
logger.Write(evt);
103103

104104
return false;

src/Serilog.AspNetCore/Serilog.AspNetCore.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
<ItemGroup>
3232
<PackageReference Include="Serilog" Version="2.10.0" />
33-
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.2.0" />
33+
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.2.1-dev-00092" />
3434
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
3535
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
3636
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />

test/Serilog.AspNetCore.Tests/SerilogWebHostBuilderExtensionsTests.cs

+55-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.AspNetCore.Hosting;
1010
using Microsoft.AspNetCore.Mvc.Testing;
1111
using Microsoft.AspNetCore.Builder;
12+
using Microsoft.AspNetCore.Http;
1213
using Serilog.Filters;
1314
using Serilog.AspNetCore.Tests.Support;
1415

@@ -65,7 +66,51 @@ public async Task RequestLoggingMiddlewareShouldEnrich()
6566
Assert.True(completionEvent.Properties.ContainsKey("Elapsed"));
6667
}
6768

68-
WebApplicationFactory<TestStartup> Setup(ILogger logger, bool dispose, Action<RequestLoggingOptions> configureOptions = null)
69+
[Fact]
70+
public async Task RequestLoggingMiddlewareShouldEnrichWithCollectedExceptionIfNoUnhandledException()
71+
{
72+
var diagnosticContextException = new Exception("Exception set in diagnostic context");
73+
var (sink, web) = Setup(options =>
74+
{
75+
options.EnrichDiagnosticContext += (diagnosticContext, _) =>
76+
{
77+
diagnosticContext.SetException(diagnosticContextException);
78+
};
79+
});
80+
81+
await web.CreateClient().GetAsync("/resource");
82+
83+
var completionEvent = sink.Writes.First(logEvent => Matching.FromSource<RequestLoggingMiddleware>()(logEvent));
84+
85+
Assert.Same(diagnosticContextException, completionEvent.Exception);
86+
}
87+
88+
[Theory]
89+
[InlineData(false)]
90+
[InlineData(true)]
91+
public async Task RequestLoggingMiddlewareShouldEnrichWithUnhandledExceptionEvenIfExceptionIsSetInDiagnosticContext(bool setExceptionInDiagnosticContext)
92+
{
93+
var diagnosticContextException = new Exception("Exception set in diagnostic context");
94+
var unhandledException = new Exception("Unhandled exception thrown in API action");
95+
var (sink, web) = Setup(options =>
96+
{
97+
options.EnrichDiagnosticContext += (diagnosticContext, _) =>
98+
{
99+
if (setExceptionInDiagnosticContext)
100+
diagnosticContext.SetException(diagnosticContextException);
101+
};
102+
}, actionCallback: _ => throw unhandledException);
103+
104+
Func<Task> act = () => web.CreateClient().GetAsync("/resource");
105+
106+
Exception thrownException = await Assert.ThrowsAsync<Exception>(act);
107+
var completionEvent = sink.Writes.First(logEvent => Matching.FromSource<RequestLoggingMiddleware>()(logEvent));
108+
Assert.Same(unhandledException, completionEvent.Exception);
109+
Assert.Same(unhandledException, thrownException);
110+
}
111+
112+
WebApplicationFactory<TestStartup> Setup(ILogger logger, bool dispose, Action<RequestLoggingOptions> configureOptions = null,
113+
Action<HttpContext> actionCallback = null)
69114
{
70115
var web = _web.WithWebHostBuilder(
71116
builder => builder
@@ -80,24 +125,29 @@ WebApplicationFactory<TestStartup> Setup(ILogger logger, bool dispose, Action<Re
80125
.Configure(app =>
81126
{
82127
app.UseSerilogRequestLogging(configureOptions);
83-
app.Run(_ => Task.CompletedTask); // 200 OK
128+
app.Run(ctx =>
129+
{
130+
actionCallback?.Invoke(ctx);
131+
return Task.CompletedTask;
132+
}); // 200 OK
84133
})
85134
.UseSerilog(logger, dispose));
86135

87136
return web;
88137
}
89138

90-
(SerilogSink, WebApplicationFactory<TestStartup>) Setup(Action<RequestLoggingOptions> configureOptions = null)
139+
(SerilogSink, WebApplicationFactory<TestStartup>) Setup(Action<RequestLoggingOptions> configureOptions = null,
140+
Action<HttpContext> actionCallback = null)
91141
{
92142
var sink = new SerilogSink();
93143
var logger = new LoggerConfiguration()
94144
.Enrich.FromLogContext()
95145
.WriteTo.Sink(sink)
96146
.CreateLogger();
97147

98-
var web = Setup(logger, true, configureOptions);
148+
var web = Setup(logger, true, configureOptions, actionCallback);
99149

100150
return (sink, web);
101151
}
102152
}
103-
}
153+
}

0 commit comments

Comments
 (0)