Skip to content

Commit bf9ac3a

Browse files
eperottzegelin
authored andcommitted
Mute 'Broken pipe' IOExceptions
Closes #38
1 parent aa586b5 commit bf9ac3a

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

common/src/main/java/com/zegelin/cassandra/exporter/netty/Server.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ public void initChannel(final SocketChannel ch) {
5454
.addLast(new HttpObjectAggregator(1048576))
5555
.addLast(new HttpContentCompressor())
5656
.addLast(new ChunkedWriteHandler())
57-
.addLast(new HttpHandler(harvester, helpExposition));
57+
.addLast(new HttpHandler(harvester, helpExposition))
58+
.addLast(new SuppressingExceptionHandler());
5859
}
5960
}
6061

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.zegelin.cassandra.exporter.netty;
2+
3+
import io.netty.channel.ChannelHandlerAdapter;
4+
import io.netty.channel.ChannelHandlerContext;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
8+
import java.io.IOException;
9+
10+
public class SuppressingExceptionHandler extends ChannelHandlerAdapter {
11+
private static final Logger logger = LoggerFactory.getLogger(SuppressingExceptionHandler.class);
12+
13+
@Override
14+
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
15+
if (brokenPipeException(cause)) {
16+
logger.debug("Exception while processing scrape request: {}", cause.getMessage());
17+
} else {
18+
ctx.fireExceptionCaught(cause);
19+
}
20+
}
21+
22+
private boolean brokenPipeException(Throwable cause) {
23+
return cause instanceof IOException
24+
&& "Broken pipe".equals(cause.getMessage());
25+
}
26+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.zegelin.cassandra.exporter.netty;
2+
3+
import io.netty.channel.ChannelHandlerContext;
4+
import org.mockito.Mock;
5+
import org.mockito.MockitoAnnotations;
6+
import org.testng.annotations.BeforeMethod;
7+
import org.testng.annotations.Test;
8+
9+
import java.io.IOException;
10+
11+
import static org.mockito.ArgumentMatchers.any;
12+
import static org.mockito.Mockito.times;
13+
import static org.mockito.Mockito.verify;
14+
15+
public class TestSuppressingExceptionHandler {
16+
@Mock
17+
private ChannelHandlerContext context;
18+
19+
private SuppressingExceptionHandler handler;
20+
21+
@BeforeMethod
22+
public void before() {
23+
MockitoAnnotations.initMocks(this);
24+
handler = new SuppressingExceptionHandler();
25+
}
26+
27+
@Test
28+
public void testBrokenPipeIoExceptionIsMuted() throws Exception {
29+
handler.exceptionCaught(context, new IOException("Broken pipe"));
30+
verify(context, times(0)).fireExceptionCaught(any());
31+
}
32+
33+
@Test
34+
public void testOtherIoExceptionIsPropagated() throws Exception {
35+
handler.exceptionCaught(context, new IOException("Other"));
36+
verify(context, times(1)).fireExceptionCaught(any());
37+
}
38+
39+
@Test
40+
public void testOtherExceptionIsPropagated() throws Exception {
41+
handler.exceptionCaught(context, new NullPointerException());
42+
verify(context, times(1)).fireExceptionCaught(any());
43+
}
44+
}

0 commit comments

Comments
 (0)