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