99using Microsoft . AspNetCore . Hosting ;
1010using Microsoft . AspNetCore . Mvc . Testing ;
1111using Microsoft . AspNetCore . Builder ;
12+ using Microsoft . AspNetCore . Http ;
1213using Serilog . Filters ;
1314using 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