Skip to content

Commit 7a7f124

Browse files
authored
Fix IndexOutOfBoundsException in Jetty 9, 10, 11, 12 InstrumentedHandler (#3912)
Fixes #3911 Refs #3133 Refs #3174 Refs #3175
1 parent a964779 commit 7a7f124

File tree

8 files changed

+315
-220
lines changed

8 files changed

+315
-220
lines changed

metrics-jetty10/src/main/java/io/dropwizard/metrics/jetty10/InstrumentedHandler.java

+59-55
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,6 @@ protected void doStart() throws Exception {
169169
this.asyncTimeouts = metricRegistry.meter(name(prefix, NAME_ASYNC_TIMEOUTS));
170170

171171
this.responseCodeMeters = DETAILED_METER_LEVELS.contains(responseMeteredLevel) ? new ConcurrentHashMap<>() : Collections.emptyMap();
172-
this.responses = COARSE_METER_LEVELS.contains(responseMeteredLevel) ?
173-
Collections.unmodifiableList(Arrays.asList(
174-
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
175-
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
176-
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
177-
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
178-
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
179-
)) : Collections.emptyList();
180172

181173
this.getRequests = metricRegistry.timer(name(prefix, NAME_GET_REQUESTS));
182174
this.postRequests = metricRegistry.timer(name(prefix, NAME_POST_REQUESTS));
@@ -189,53 +181,65 @@ protected void doStart() throws Exception {
189181
this.moveRequests = metricRegistry.timer(name(prefix, NAME_MOVE_REQUESTS));
190182
this.otherRequests = metricRegistry.timer(name(prefix, NAME_OTHER_REQUESTS));
191183

192-
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
193-
@Override
194-
protected Ratio getRatio() {
195-
return Ratio.of(responses.get(3).getOneMinuteRate(),
196-
requests.getOneMinuteRate());
197-
}
198-
});
199-
200-
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
201-
@Override
202-
protected Ratio getRatio() {
203-
return Ratio.of(responses.get(3).getFiveMinuteRate(),
204-
requests.getFiveMinuteRate());
205-
}
206-
});
207-
208-
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
209-
@Override
210-
protected Ratio getRatio() {
211-
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
212-
requests.getFifteenMinuteRate());
213-
}
214-
});
215-
216-
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
217-
@Override
218-
protected Ratio getRatio() {
219-
return Ratio.of(responses.get(4).getOneMinuteRate(),
220-
requests.getOneMinuteRate());
221-
}
222-
});
223-
224-
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
225-
@Override
226-
protected Ratio getRatio() {
227-
return Ratio.of(responses.get(4).getFiveMinuteRate(),
228-
requests.getFiveMinuteRate());
229-
}
230-
});
231-
232-
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
233-
@Override
234-
public Ratio getRatio() {
235-
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
236-
requests.getFifteenMinuteRate());
237-
}
238-
});
184+
if (COARSE_METER_LEVELS.contains(responseMeteredLevel)) {
185+
this.responses = Collections.unmodifiableList(Arrays.asList(
186+
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
187+
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
188+
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
189+
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
190+
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
191+
));
192+
193+
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
194+
@Override
195+
protected Ratio getRatio() {
196+
return Ratio.of(responses.get(3).getOneMinuteRate(),
197+
requests.getOneMinuteRate());
198+
}
199+
});
200+
201+
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
202+
@Override
203+
protected Ratio getRatio() {
204+
return Ratio.of(responses.get(3).getFiveMinuteRate(),
205+
requests.getFiveMinuteRate());
206+
}
207+
});
208+
209+
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
210+
@Override
211+
protected Ratio getRatio() {
212+
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
213+
requests.getFifteenMinuteRate());
214+
}
215+
});
216+
217+
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
218+
@Override
219+
protected Ratio getRatio() {
220+
return Ratio.of(responses.get(4).getOneMinuteRate(),
221+
requests.getOneMinuteRate());
222+
}
223+
});
224+
225+
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
226+
@Override
227+
protected Ratio getRatio() {
228+
return Ratio.of(responses.get(4).getFiveMinuteRate(),
229+
requests.getFiveMinuteRate());
230+
}
231+
});
232+
233+
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
234+
@Override
235+
public Ratio getRatio() {
236+
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
237+
requests.getFifteenMinuteRate());
238+
}
239+
});
240+
} else {
241+
this.responses = Collections.emptyList();
242+
}
239243

240244

241245
this.listener = new AsyncAttachingListener();

metrics-jetty10/src/test/java/io/dropwizard/metrics/jetty10/InstrumentedHandlerTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.concurrent.TimeUnit;
2424

2525
import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
26+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE;
27+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.DETAILED;
2628
import static org.assertj.core.api.Assertions.assertThat;
2729
import static org.assertj.core.api.Assertions.assertThatCode;
2830

@@ -120,6 +122,24 @@ public void doStopDoesNotThrowNPE() throws Exception {
120122
assertThatCode(handler::doStop).doesNotThrowAnyException();
121123
}
122124

125+
@Test
126+
public void gaugesAreRegisteredWithResponseMeteredLevelCoarse() throws Exception {
127+
InstrumentedHandler handler = new InstrumentedHandler(registry, "coarse", COARSE);
128+
handler.setHandler(new TestHandler());
129+
handler.setName("handler");
130+
handler.doStart();
131+
assertThat(registry.getGauges()).containsKey("coarse.handler.percent-4xx-1m");
132+
}
133+
134+
@Test
135+
public void gaugesAreNotRegisteredWithResponseMeteredLevelDetailed() throws Exception {
136+
InstrumentedHandler handler = new InstrumentedHandler(registry, "detailed", DETAILED);
137+
handler.setHandler(new TestHandler());
138+
handler.setName("handler");
139+
handler.doStart();
140+
assertThat(registry.getGauges()).doesNotContainKey("coarse.handler.percent-4xx-1m");
141+
}
142+
123143
@Test
124144
@Ignore("flaky on virtual machines")
125145
public void responseTimesAreRecordedForAsyncResponses() throws Exception {

metrics-jetty11/src/main/java/io/dropwizard/metrics/jetty11/InstrumentedHandler.java

+58-55
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,6 @@ protected void doStart() throws Exception {
169169
this.asyncTimeouts = metricRegistry.meter(name(prefix, NAME_ASYNC_TIMEOUTS));
170170

171171
this.responseCodeMeters = DETAILED_METER_LEVELS.contains(responseMeteredLevel) ? new ConcurrentHashMap<>() : Collections.emptyMap();
172-
this.responses = COARSE_METER_LEVELS.contains(responseMeteredLevel) ?
173-
Collections.unmodifiableList(Arrays.asList(
174-
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
175-
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
176-
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
177-
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
178-
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
179-
)) : Collections.emptyList();
180172

181173
this.getRequests = metricRegistry.timer(name(prefix, NAME_GET_REQUESTS));
182174
this.postRequests = metricRegistry.timer(name(prefix, NAME_POST_REQUESTS));
@@ -189,53 +181,64 @@ protected void doStart() throws Exception {
189181
this.moveRequests = metricRegistry.timer(name(prefix, NAME_MOVE_REQUESTS));
190182
this.otherRequests = metricRegistry.timer(name(prefix, NAME_OTHER_REQUESTS));
191183

192-
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
193-
@Override
194-
protected Ratio getRatio() {
195-
return Ratio.of(responses.get(3).getOneMinuteRate(),
196-
requests.getOneMinuteRate());
197-
}
198-
});
199-
200-
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
201-
@Override
202-
protected Ratio getRatio() {
203-
return Ratio.of(responses.get(3).getFiveMinuteRate(),
204-
requests.getFiveMinuteRate());
205-
}
206-
});
207-
208-
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
209-
@Override
210-
protected Ratio getRatio() {
211-
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
212-
requests.getFifteenMinuteRate());
213-
}
214-
});
215-
216-
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
217-
@Override
218-
protected Ratio getRatio() {
219-
return Ratio.of(responses.get(4).getOneMinuteRate(),
220-
requests.getOneMinuteRate());
221-
}
222-
});
223-
224-
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
225-
@Override
226-
protected Ratio getRatio() {
227-
return Ratio.of(responses.get(4).getFiveMinuteRate(),
228-
requests.getFiveMinuteRate());
229-
}
230-
});
231-
232-
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
233-
@Override
234-
public Ratio getRatio() {
235-
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
236-
requests.getFifteenMinuteRate());
237-
}
238-
});
184+
if (COARSE_METER_LEVELS.contains(responseMeteredLevel)) {
185+
this.responses = Collections.unmodifiableList(Arrays.asList(
186+
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
187+
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
188+
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
189+
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
190+
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
191+
));
192+
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
193+
@Override
194+
protected Ratio getRatio() {
195+
return Ratio.of(responses.get(3).getOneMinuteRate(),
196+
requests.getOneMinuteRate());
197+
}
198+
});
199+
200+
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
201+
@Override
202+
protected Ratio getRatio() {
203+
return Ratio.of(responses.get(3).getFiveMinuteRate(),
204+
requests.getFiveMinuteRate());
205+
}
206+
});
207+
208+
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
209+
@Override
210+
protected Ratio getRatio() {
211+
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
212+
requests.getFifteenMinuteRate());
213+
}
214+
});
215+
216+
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
217+
@Override
218+
protected Ratio getRatio() {
219+
return Ratio.of(responses.get(4).getOneMinuteRate(),
220+
requests.getOneMinuteRate());
221+
}
222+
});
223+
224+
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
225+
@Override
226+
protected Ratio getRatio() {
227+
return Ratio.of(responses.get(4).getFiveMinuteRate(),
228+
requests.getFiveMinuteRate());
229+
}
230+
});
231+
232+
metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
233+
@Override
234+
public Ratio getRatio() {
235+
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
236+
requests.getFifteenMinuteRate());
237+
}
238+
});
239+
} else {
240+
this.responses = Collections.emptyList();
241+
}
239242

240243

241244
this.listener = new AsyncAttachingListener();

metrics-jetty11/src/test/java/io/dropwizard/metrics/jetty11/InstrumentedHandlerTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.concurrent.TimeUnit;
2424

2525
import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
26+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE;
27+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.DETAILED;
2628
import static org.assertj.core.api.Assertions.assertThat;
2729
import static org.assertj.core.api.Assertions.assertThatCode;
2830

@@ -120,6 +122,24 @@ public void doStopDoesNotThrowNPE() throws Exception {
120122
assertThatCode(handler::doStop).doesNotThrowAnyException();
121123
}
122124

125+
@Test
126+
public void gaugesAreRegisteredWithResponseMeteredLevelCoarse() throws Exception {
127+
InstrumentedHandler handler = new InstrumentedHandler(registry, "coarse", COARSE);
128+
handler.setHandler(new TestHandler());
129+
handler.setName("handler");
130+
handler.doStart();
131+
assertThat(registry.getGauges()).containsKey("coarse.handler.percent-4xx-1m");
132+
}
133+
134+
@Test
135+
public void gaugesAreNotRegisteredWithResponseMeteredLevelDetailed() throws Exception {
136+
InstrumentedHandler handler = new InstrumentedHandler(registry, "detailed", DETAILED);
137+
handler.setHandler(new TestHandler());
138+
handler.setName("handler");
139+
handler.doStart();
140+
assertThat(registry.getGauges()).doesNotContainKey("coarse.handler.percent-4xx-1m");
141+
}
142+
123143
@Test
124144
@Ignore("flaky on virtual machines")
125145
public void responseTimesAreRecordedForAsyncResponses() throws Exception {

metrics-jetty12-ee10/src/test/java/io/dropwizard/metrics/jetty12/ee10/InstrumentedEE10HandlerTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import java.util.concurrent.TimeUnit;
2828

2929
import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
30+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE;
31+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.DETAILED;
3032
import static org.assertj.core.api.Assertions.assertThat;
3133
import static org.assertj.core.api.Assertions.assertThatCode;
3234

@@ -137,6 +139,24 @@ public void doStopDoesNotThrowNPE() throws Exception {
137139
assertThatCode(handler::doStop).doesNotThrowAnyException();
138140
}
139141

142+
@Test
143+
public void gaugesAreRegisteredWithResponseMeteredLevelCoarse() throws Exception {
144+
InstrumentedEE10Handler handler = new InstrumentedEE10Handler(registry, "coarse", COARSE);
145+
handler.setHandler(new TestHandler());
146+
handler.setName("handler");
147+
handler.doStart();
148+
assertThat(registry.getGauges()).containsKey("coarse.handler.percent-4xx-1m");
149+
}
150+
151+
@Test
152+
public void gaugesAreNotRegisteredWithResponseMeteredLevelDetailed() throws Exception {
153+
InstrumentedEE10Handler handler = new InstrumentedEE10Handler(registry, "detailed", DETAILED);
154+
handler.setHandler(new TestHandler());
155+
handler.setName("handler");
156+
handler.doStart();
157+
assertThat(registry.getGauges()).doesNotContainKey("coarse.handler.percent-4xx-1m");
158+
}
159+
140160
@Test
141161
@Ignore("flaky on virtual machines")
142162
public void responseTimesAreRecordedForAsyncResponses() throws Exception {

0 commit comments

Comments
 (0)