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
@@ -62,7 +63,51 @@ public async Task RequestLoggingMiddlewareShouldEnrich()
6263 Assert . True ( completionEvent . Properties . ContainsKey ( "Elapsed" ) ) ;
6364 }
6465
65- WebApplicationFactory < TestStartup > Setup ( ILogger logger , bool dispose , Action < RequestLoggingOptions > configureOptions = null )
66+ [ Fact ]
67+ public async Task RequestLoggingMiddlewareShouldEnrichWithCollectedExceptionIfNoUnhandledException ( )
68+ {
69+ var diagnosticContextException = new Exception ( "Exception set in diagnostic context" ) ;
70+ var ( sink , web ) = Setup ( options =>
71+ {
72+ options . EnrichDiagnosticContext += ( diagnosticContext , _ ) =>
73+ {
74+ diagnosticContext . SetException ( diagnosticContextException ) ;
75+ } ;
76+ } ) ;
77+
78+ await web . CreateClient ( ) . GetAsync ( "/resource" ) ;
79+
80+ var completionEvent = sink . Writes . First ( logEvent => Matching . FromSource < RequestLoggingMiddleware > ( ) ( logEvent ) ) ;
81+
82+ Assert . Same ( diagnosticContextException , completionEvent . Exception ) ;
83+ }
84+
85+ [ Theory ]
86+ [ InlineData ( false ) ]
87+ [ InlineData ( true ) ]
88+ public async Task RequestLoggingMiddlewareShouldEnrichWithUnhandledExceptionEvenIfExceptionIsSetInDiagnosticContext ( bool setExceptionInDiagnosticContext )
89+ {
90+ var diagnosticContextException = new Exception ( "Exception set in diagnostic context" ) ;
91+ var unhandledException = new Exception ( "Unhandled exception thrown in API action" ) ;
92+ var ( sink , web ) = Setup ( options =>
93+ {
94+ options . EnrichDiagnosticContext += ( diagnosticContext , _ ) =>
95+ {
96+ if ( setExceptionInDiagnosticContext )
97+ diagnosticContext . SetException ( diagnosticContextException ) ;
98+ } ;
99+ } , actionCallback : _ => throw unhandledException ) ;
100+
101+ Func < Task > act = ( ) => web . CreateClient ( ) . GetAsync ( "/resource" ) ;
102+
103+ Exception thrownException = await Assert . ThrowsAsync < Exception > ( act ) ;
104+ var completionEvent = sink . Writes . First ( logEvent => Matching . FromSource < RequestLoggingMiddleware > ( ) ( logEvent ) ) ;
105+ Assert . Same ( unhandledException , completionEvent . Exception ) ;
106+ Assert . Same ( unhandledException , thrownException ) ;
107+ }
108+
109+ WebApplicationFactory < TestStartup > Setup ( ILogger logger , bool dispose , Action < RequestLoggingOptions > configureOptions = null ,
110+ Action < HttpContext > actionCallback = null )
66111 {
67112 var web = _web . WithWebHostBuilder (
68113 builder => builder
@@ -77,24 +122,29 @@ WebApplicationFactory<TestStartup> Setup(ILogger logger, bool dispose, Action<Re
77122 . Configure ( app =>
78123 {
79124 app . UseSerilogRequestLogging ( configureOptions ) ;
80- app . Run ( _ => Task . CompletedTask ) ; // 200 OK
125+ app . Run ( ctx =>
126+ {
127+ actionCallback ? . Invoke ( ctx ) ;
128+ return Task . CompletedTask ;
129+ } ) ; // 200 OK
81130 } )
82131 . UseSerilog ( logger , dispose ) ) ;
83132
84133 return web ;
85134 }
86135
87- ( SerilogSink , WebApplicationFactory < TestStartup > ) Setup ( Action < RequestLoggingOptions > configureOptions = null )
136+ ( SerilogSink , WebApplicationFactory < TestStartup > ) Setup ( Action < RequestLoggingOptions > configureOptions = null ,
137+ Action < HttpContext > actionCallback = null )
88138 {
89139 var sink = new SerilogSink ( ) ;
90140 var logger = new LoggerConfiguration ( )
91141 . Enrich . FromLogContext ( )
92142 . WriteTo . Sink ( sink )
93143 . CreateLogger ( ) ;
94144
95- var web = Setup ( logger , true , configureOptions ) ;
145+ var web = Setup ( logger , true , configureOptions , actionCallback ) ;
96146
97147 return ( sink , web ) ;
98148 }
99149 }
100- }
150+ }
0 commit comments