38
38
import io .micrometer .core .annotation .Timed ;
39
39
import io .micrometer .core .instrument .Clock ;
40
40
import io .micrometer .core .instrument .Meter ;
41
+ import io .micrometer .core .instrument .Meter .Id ;
41
42
import io .micrometer .core .instrument .MeterRegistry ;
42
43
import io .micrometer .core .instrument .MockClock ;
43
44
import io .micrometer .core .instrument .Tag ;
@@ -127,8 +128,8 @@ class WebMvcMetricsFilterTests {
127
128
128
129
@ BeforeEach
129
130
void setupMockMvc () {
130
- this .mvc = MockMvcBuilders .webAppContextSetup (this .context )
131
- .addFilters ( this . filter , new RedirectAndNotFoundFilter ()). build ();
131
+ this .mvc = MockMvcBuilders .webAppContextSetup (this .context ). addFilters ( this . filter , new CustomBehaviorFilter ())
132
+ .build ();
132
133
}
133
134
134
135
@ Test
@@ -165,15 +166,15 @@ void badClientRequest() throws Exception {
165
166
166
167
@ Test
167
168
void redirectRequest () throws Exception {
168
- this .mvc .perform (get ("/api/redirect" ).header (RedirectAndNotFoundFilter . TEST_MISBEHAVE_HEADER , "302" ))
169
+ this .mvc .perform (get ("/api/redirect" ).header (CustomBehaviorFilter . TEST_STATUS_HEADER , "302" ))
169
170
.andExpect (status ().is3xxRedirection ());
170
171
assertThat (this .registry .get ("http.server.requests" ).tags ("uri" , "REDIRECTION" ).tags ("status" , "302" ).timer ())
171
172
.isNotNull ();
172
173
}
173
174
174
175
@ Test
175
176
void notFoundRequest () throws Exception {
176
- this .mvc .perform (get ("/api/not/found" ).header (RedirectAndNotFoundFilter . TEST_MISBEHAVE_HEADER , "404" ))
177
+ this .mvc .perform (get ("/api/not/found" ).header (CustomBehaviorFilter . TEST_STATUS_HEADER , "404" ))
177
178
.andExpect (status ().is4xxClientError ());
178
179
assertThat (this .registry .get ("http.server.requests" ).tags ("uri" , "NOT_FOUND" ).tags ("status" , "404" ).timer ())
179
180
.isNotNull ();
@@ -187,13 +188,23 @@ void unhandledError() {
187
188
.isEqualTo (1L );
188
189
}
189
190
191
+ @ Test
192
+ void unhandledServletException () {
193
+ assertThatCode (() -> this .mvc
194
+ .perform (get ("/api/filterError" ).header (CustomBehaviorFilter .TEST_SERVLET_EXCEPTION_HEADER , "throw" ))
195
+ .andExpect (status ().isOk ())).isInstanceOf (ServletException .class );
196
+ Id meterId = this .registry .get ("http.server.requests" ).tags ("exception" , "ServletException" ).timer ().getId ();
197
+ assertThat (meterId .getTag ("status" )).isEqualTo ("500" );
198
+ }
199
+
190
200
@ Test
191
201
void streamingError () throws Exception {
192
202
MvcResult result = this .mvc .perform (get ("/api/c1/streamingError" )).andExpect (request ().asyncStarted ())
193
203
.andReturn ();
194
204
assertThatIOException ().isThrownBy (() -> this .mvc .perform (asyncDispatch (result )).andReturn ());
195
- assertThat (this .registry .get ("http.server.requests" ).tags ("exception" , "IOException" ).timer ().count ())
196
- .isEqualTo (1L );
205
+ Id meterId = this .registry .get ("http.server.requests" ).tags ("exception" , "IOException" ).timer ().getId ();
206
+ // Response is committed before error occurs so status is 200 (OK)
207
+ assertThat (meterId .getTag ("status" )).isEqualTo ("200" );
197
208
}
198
209
199
210
@ Test
@@ -209,8 +220,10 @@ void anonymousError() {
209
220
}
210
221
catch (Throwable ignore ) {
211
222
}
212
- assertThat (this .registry .get ("http.server.requests" ).tag ("uri" , "/api/c1/anonymousError/{id}" ).timer ().getId ()
213
- .getTag ("exception" )).endsWith ("$1" );
223
+ Id meterId = this .registry .get ("http.server.requests" ).tag ("uri" , "/api/c1/anonymousError/{id}" ).timer ()
224
+ .getId ();
225
+ assertThat (meterId .getTag ("exception" )).endsWith ("$1" );
226
+ assertThat (meterId .getTag ("status" )).isEqualTo ("500" );
214
227
}
215
228
216
229
@ Test
@@ -359,8 +372,8 @@ public MeterFilterReply accept(@NonNull Meter.Id id) {
359
372
}
360
373
361
374
@ Bean
362
- RedirectAndNotFoundFilter redirectAndNotFoundFilter () {
363
- return new RedirectAndNotFoundFilter ();
375
+ CustomBehaviorFilter redirectAndNotFoundFilter () {
376
+ return new CustomBehaviorFilter ();
364
377
}
365
378
366
379
@ Bean (name = "callableBarrier" )
@@ -474,8 +487,10 @@ String alwaysThrowsUnhandledException(@PathVariable Long id) {
474
487
}
475
488
476
489
@ GetMapping ("/streamingError" )
477
- ResponseBodyEmitter streamingError () {
490
+ ResponseBodyEmitter streamingError () throws IOException {
478
491
ResponseBodyEmitter emitter = new ResponseBodyEmitter ();
492
+ emitter .send ("some data" );
493
+ emitter .send ("some more data" );
479
494
emitter .completeWithError (new IOException ("error while writing to the response" ));
480
495
return emitter ;
481
496
}
@@ -526,20 +541,24 @@ String successful(@PathVariable Long id) {
526
541
527
542
}
528
543
529
- static class RedirectAndNotFoundFilter extends OncePerRequestFilter {
544
+ static class CustomBehaviorFilter extends OncePerRequestFilter {
545
+
546
+ static final String TEST_STATUS_HEADER = "x-test-status" ;
530
547
531
- static final String TEST_MISBEHAVE_HEADER = "x-test-misbehave-status " ;
548
+ static final String TEST_SERVLET_EXCEPTION_HEADER = "x-test-servlet-exception " ;
532
549
533
550
@ Override
534
551
protected void doFilterInternal (HttpServletRequest request , HttpServletResponse response ,
535
552
FilterChain filterChain ) throws ServletException , IOException {
536
- String misbehave = request .getHeader (TEST_MISBEHAVE_HEADER );
537
- if (misbehave != null ) {
538
- response .setStatus (Integer .parseInt (misbehave ));
553
+ String misbehaveStatus = request .getHeader (TEST_STATUS_HEADER );
554
+ if (misbehaveStatus != null ) {
555
+ response .setStatus (Integer .parseInt (misbehaveStatus ));
556
+ return ;
539
557
}
540
- else {
541
- filterChain . doFilter ( request , response );
558
+ if ( request . getHeader ( TEST_SERVLET_EXCEPTION_HEADER ) != null ) {
559
+ throw new ServletException ( );
542
560
}
561
+ filterChain .doFilter (request , response );
543
562
}
544
563
545
564
}
0 commit comments