9
9
using Microsoft . AspNetCore . Hosting ;
10
10
using Microsoft . AspNetCore . Mvc . Testing ;
11
11
using Microsoft . AspNetCore . Builder ;
12
+ using Microsoft . AspNetCore . Http ;
12
13
using Serilog . Filters ;
13
14
using Serilog . AspNetCore . Tests . Support ;
14
15
@@ -62,7 +63,51 @@ public async Task RequestLoggingMiddlewareShouldEnrich()
62
63
Assert . True ( completionEvent . Properties . ContainsKey ( "Elapsed" ) ) ;
63
64
}
64
65
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 )
66
111
{
67
112
var web = _web . WithWebHostBuilder (
68
113
builder => builder
@@ -77,24 +122,29 @@ WebApplicationFactory<TestStartup> Setup(ILogger logger, bool dispose, Action<Re
77
122
. Configure ( app =>
78
123
{
79
124
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
81
130
} )
82
131
. UseSerilog ( logger , dispose ) ) ;
83
132
84
133
return web ;
85
134
}
86
135
87
- ( SerilogSink , WebApplicationFactory < TestStartup > ) Setup ( Action < RequestLoggingOptions > configureOptions = null )
136
+ ( SerilogSink , WebApplicationFactory < TestStartup > ) Setup ( Action < RequestLoggingOptions > configureOptions = null ,
137
+ Action < HttpContext > actionCallback = null )
88
138
{
89
139
var sink = new SerilogSink ( ) ;
90
140
var logger = new LoggerConfiguration ( )
91
141
. Enrich . FromLogContext ( )
92
142
. WriteTo . Sink ( sink )
93
143
. CreateLogger ( ) ;
94
144
95
- var web = Setup ( logger , true , configureOptions ) ;
145
+ var web = Setup ( logger , true , configureOptions , actionCallback ) ;
96
146
97
147
return ( sink , web ) ;
98
148
}
99
149
}
100
- }
150
+ }
0 commit comments