Skip to content

Commit

Permalink
Fix IndexOutOfBoundsException in Jetty 9, 10, 11, 12 InstrumentedHandler
Browse files Browse the repository at this point in the history
Fixes #3911
Refs #3133
Refs #3174
Refs #3175
  • Loading branch information
joschi committed Jan 19, 2024
1 parent a964779 commit 9a96ab3
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 220 deletions.
Expand Up @@ -169,14 +169,6 @@ protected void doStart() throws Exception {
this.asyncTimeouts = metricRegistry.meter(name(prefix, NAME_ASYNC_TIMEOUTS));

this.responseCodeMeters = DETAILED_METER_LEVELS.contains(responseMeteredLevel) ? new ConcurrentHashMap<>() : Collections.emptyMap();
this.responses = COARSE_METER_LEVELS.contains(responseMeteredLevel) ?
Collections.unmodifiableList(Arrays.asList(
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
)) : Collections.emptyList();

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

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
@Override
public Ratio getRatio() {
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});
if (COARSE_METER_LEVELS.contains(responseMeteredLevel)) {
this.responses = Collections.unmodifiableList(Arrays.asList(
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
));

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
@Override
public Ratio getRatio() {
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});
} else {
this.responses = Collections.emptyList();
}


this.listener = new AsyncAttachingListener();
Expand Down
Expand Up @@ -23,6 +23,8 @@
import java.util.concurrent.TimeUnit;

import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE;
import static com.codahale.metrics.annotation.ResponseMeteredLevel.DETAILED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;

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

@Test
public void gaugesAreRegisteredWithResponseMeteredLevelCoarse() throws Exception {
InstrumentedHandler handler = new InstrumentedHandler(registry, "coarse", COARSE);
handler.setHandler(new TestHandler());
handler.setName("handler");
handler.doStart();
assertThat(registry.getGauges()).containsKey("coarse.handler.percent-4xx-1m");
}

@Test
public void gaugesAreNotRegisteredWithResponseMeteredLevelDetailed() throws Exception {
InstrumentedHandler handler = new InstrumentedHandler(registry, "detailed", DETAILED);
handler.setHandler(new TestHandler());
handler.setName("handler");
handler.doStart();
assertThat(registry.getGauges()).doesNotContainKey("coarse.handler.percent-4xx-1m");
}

@Test
@Ignore("flaky on virtual machines")
public void responseTimesAreRecordedForAsyncResponses() throws Exception {
Expand Down
Expand Up @@ -169,14 +169,6 @@ protected void doStart() throws Exception {
this.asyncTimeouts = metricRegistry.meter(name(prefix, NAME_ASYNC_TIMEOUTS));

this.responseCodeMeters = DETAILED_METER_LEVELS.contains(responseMeteredLevel) ? new ConcurrentHashMap<>() : Collections.emptyMap();
this.responses = COARSE_METER_LEVELS.contains(responseMeteredLevel) ?
Collections.unmodifiableList(Arrays.asList(
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
)) : Collections.emptyList();

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

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
@Override
public Ratio getRatio() {
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});
if (COARSE_METER_LEVELS.contains(responseMeteredLevel)) {
this.responses = Collections.unmodifiableList(Arrays.asList(
metricRegistry.meter(name(prefix, NAME_1XX_RESPONSES)), // 1xx
metricRegistry.meter(name(prefix, NAME_2XX_RESPONSES)), // 2xx
metricRegistry.meter(name(prefix, NAME_3XX_RESPONSES)), // 3xx
metricRegistry.meter(name(prefix, NAME_4XX_RESPONSES)), // 4xx
metricRegistry.meter(name(prefix, NAME_5XX_RESPONSES)) // 5xx
));
metricRegistry.register(name(prefix, NAME_PERCENT_4XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_4XX_15M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(3).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_1M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getOneMinuteRate(),
requests.getOneMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_5M), new RatioGauge() {
@Override
protected Ratio getRatio() {
return Ratio.of(responses.get(4).getFiveMinuteRate(),
requests.getFiveMinuteRate());
}
});

metricRegistry.register(name(prefix, NAME_PERCENT_5XX_15M), new RatioGauge() {
@Override
public Ratio getRatio() {
return Ratio.of(responses.get(4).getFifteenMinuteRate(),
requests.getFifteenMinuteRate());
}
});
} else {
this.responses = Collections.emptyList();
}


this.listener = new AsyncAttachingListener();
Expand Down
Expand Up @@ -23,6 +23,8 @@
import java.util.concurrent.TimeUnit;

import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE;
import static com.codahale.metrics.annotation.ResponseMeteredLevel.DETAILED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;

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

@Test
public void gaugesAreRegisteredWithResponseMeteredLevelCoarse() throws Exception {
InstrumentedHandler handler = new InstrumentedHandler(registry, "coarse", COARSE);
handler.setHandler(new TestHandler());
handler.setName("handler");
handler.doStart();
assertThat(registry.getGauges()).containsKey("coarse.handler.percent-4xx-1m");
}

@Test
public void gaugesAreNotRegisteredWithResponseMeteredLevelDetailed() throws Exception {
InstrumentedHandler handler = new InstrumentedHandler(registry, "detailed", DETAILED);
handler.setHandler(new TestHandler());
handler.setName("handler");
handler.doStart();
assertThat(registry.getGauges()).doesNotContainKey("coarse.handler.percent-4xx-1m");
}

@Test
@Ignore("flaky on virtual machines")
public void responseTimesAreRecordedForAsyncResponses() throws Exception {
Expand Down
Expand Up @@ -27,6 +27,8 @@
import java.util.concurrent.TimeUnit;

import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE;
import static com.codahale.metrics.annotation.ResponseMeteredLevel.DETAILED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;

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

@Test
public void gaugesAreRegisteredWithResponseMeteredLevelCoarse() throws Exception {
InstrumentedEE10Handler handler = new InstrumentedEE10Handler(registry, "coarse", COARSE);
handler.setHandler(new TestHandler());
handler.setName("handler");
handler.doStart();
assertThat(registry.getGauges()).containsKey("coarse.handler.percent-4xx-1m");
}

@Test
public void gaugesAreNotRegisteredWithResponseMeteredLevelDetailed() throws Exception {
InstrumentedEE10Handler handler = new InstrumentedEE10Handler(registry, "detailed", DETAILED);
handler.setHandler(new TestHandler());
handler.setName("handler");
handler.doStart();
assertThat(registry.getGauges()).doesNotContainKey("coarse.handler.percent-4xx-1m");
}

@Test
@Ignore("flaky on virtual machines")
public void responseTimesAreRecordedForAsyncResponses() throws Exception {
Expand Down

0 comments on commit 9a96ab3

Please sign in to comment.