Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only capture first line of stacktrace for unexpected RequestAttempt exceptions #1736

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Throwables;
import com.netflix.appinfo.AmazonInfo;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.IClientConfig;
Expand Down Expand Up @@ -340,7 +339,13 @@ public void setException(Throwable t) {
} else {
error = t.getMessage();
exceptionType = t.getClass().getSimpleName();
cause = Throwables.getStackTraceAsString(t);

// for unexpected exceptions, just capture the first line of the stacktrace
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're suppressing the trace, doesn't cause.getCause() != null ? cause.getCause().toString() : cause.toString()) give you the hint?
When we do suppress, consider making it conditional instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite - these are more "rare case" exceptions (like the test does for a h2stream exception), which don't have a cause attached as it's thrown from within netty handlers, and thus bubbled up from the Promises in ProxyEndpoint, so need to get more info from the stacktrace itself.

// otherwise we risk large stacktraces in memory and metrics systems
StackTraceElement[] stackTraceElements = t.getStackTrace();
if (stackTraceElements.length > 0) {
cause = stackTraceElements[0].toString();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import com.netflix.zuul.exception.OutboundErrorType;
import com.netflix.zuul.netty.connectionpool.OriginConnectException;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.Http2Error;
import io.netty.handler.codec.http2.Http2Exception;
import org.junit.jupiter.api.Test;

import javax.net.ssl.SSLHandshakeException;
Expand All @@ -26,6 +29,7 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

public class RequestAttemptTest {
Expand Down Expand Up @@ -77,4 +81,38 @@ void originConnectExceptionWithCauseNotUnwrapped() {
assertEquals("ORIGIN_CONNECT_ERROR", attempt.getError());
assertEquals("java.lang.RuntimeException: socket failure", attempt.getCause());
}

@Test
void h2ExceptionCauseHandled() {
// mock out a real-ish h2 stream exception
Exception h2Exception = spy(Http2Exception.streamError(
100,
Http2Error.REFUSED_STREAM,
"Cannot create stream 100 greater than Last-Stream-ID 99 from GOAWAY.",
new Object[] {100, 99}));

// mock a stacktrace to ensure we don't actually capture it completely
when(h2Exception.getStackTrace()).thenReturn(new StackTraceElement[] {
new StackTraceElement(
DefaultHttp2Connection.class.getCanonicalName(),
"createStream",
"DefaultHttp2Connection.java",
772),
new StackTraceElement(
DefaultHttp2Connection.class.getCanonicalName(),
"checkNewStreamAllowed",
"DefaultHttp2Connection.java",
902)
});

RequestAttempt attempt = new RequestAttempt(1, null, null, "target", "chosen", 200, null, null, 0, 0, 0);
attempt.setException(h2Exception);

assertEquals("Cannot create stream 100 greater than Last-Stream-ID 99 from GOAWAY.", attempt.getError());
assertEquals("StreamException", attempt.getExceptionType());

assertEquals(
"io.netty.handler.codec.http2.DefaultHttp2Connection.createStream(DefaultHttp2Connection.java:772)",
attempt.getCause());
}
}
Loading