diff --git a/sentry-core/src/main/java/io/sentry/core/transport/HttpTransport.java b/sentry-core/src/main/java/io/sentry/core/transport/HttpTransport.java index fb8062eef..38eb1d462 100644 --- a/sentry-core/src/main/java/io/sentry/core/transport/HttpTransport.java +++ b/sentry-core/src/main/java/io/sentry/core/transport/HttpTransport.java @@ -3,7 +3,7 @@ import static io.sentry.core.SentryLevel.DEBUG; import static io.sentry.core.SentryLevel.ERROR; import static io.sentry.core.SentryLevel.INFO; -import static io.sentry.core.SentryLevel.WARNING; +import static java.net.HttpURLConnection.HTTP_OK; import com.jakewharton.nopen.annotation.Open; import io.sentry.core.ILogger; @@ -160,25 +160,20 @@ public HttpTransport( @Override public @NotNull TransportResult send(final @NotNull SentryEvent event) throws IOException { final HttpURLConnection connection = createConnection(false); - - int responseCode = -1; + TransportResult result; try (final OutputStream outputStream = connection.getOutputStream(); final GZIPOutputStream gzip = new GZIPOutputStream(outputStream); final Writer writer = new BufferedWriter(new OutputStreamWriter(gzip, UTF_8))) { serializer.serialize(event, writer); - - logger.log(DEBUG, "Event sent %s successfully.", event.getEventId()); - return TransportResult.success(); } catch (IOException e) { - final TransportResult errorResult = getResultFromErrorCode(connection, e); - responseCode = errorResult.getResponseCode(); - return errorResult; + logger.log( + ERROR, e, "An exception occurred while submitting the event to the Sentry server."); } finally { - updateRetryAfterLimits(connection, responseCode); - - closeAndDisconnect(connection); + result = + readAndLog(connection, String.format("Event sent %s successfully.", event.getEventId())); } + return result; } /** @@ -256,6 +251,7 @@ public boolean isRetryAfter(final @NotNull String itemType) { connection.setRequestMethod("POST"); connection.setDoOutput(true); + connection.setChunkedStreamingMode(0); connection.setRequestProperty("Content-Encoding", "gzip"); connection.setRequestProperty("Content-Type", contentType); @@ -278,78 +274,72 @@ public boolean isRetryAfter(final @NotNull String itemType) { @Override public @NotNull TransportResult send(final @NotNull SentryEnvelope envelope) throws IOException { final HttpURLConnection connection = createConnection(true); - - int responseCode = -1; + TransportResult result; try (final OutputStream outputStream = connection.getOutputStream(); final GZIPOutputStream gzip = new GZIPOutputStream(outputStream); final Writer writer = new BufferedWriter(new OutputStreamWriter(gzip, UTF_8))) { serializer.serialize(envelope, writer); - - logger.log(DEBUG, "Envelope sent successfully."); - return TransportResult.success(); - } catch (IOException e) { - final TransportResult errorResult = getResultFromErrorCode(connection, e); - responseCode = errorResult.getResponseCode(); - return errorResult; } catch (Exception e) { - return getDefaultErrorResult(e); + logger.log( + ERROR, e, "An exception occurred while submitting the envelope to the Sentry server."); } finally { - updateRetryAfterLimits(connection, responseCode); - - closeAndDisconnect(connection); + result = readAndLog(connection, "Envelope sent successfully."); } + return result; } /** - * Closes the Response stream and disconnect the connection + * Read responde code, retry after header and its error stream if there are errors and log it * * @param connection the HttpURLConnection + * @param message the message, if custom message if its an event or envelope + * @return TransportResult.success if responseCode is 200 or TransportResult.error otherwise */ - private void closeAndDisconnect(final @NotNull HttpURLConnection connection) { + private @NotNull TransportResult readAndLog( + final @NotNull HttpURLConnection connection, final @NotNull String message) { try { - connection.getInputStream().close(); + final int responseCode = connection.getResponseCode(); + + updateRetryAfterLimits(connection, responseCode); + + if (!isSuccessfulResponseCode(responseCode)) { + logger.log(ERROR, "Request failed, API returned %s", responseCode); + // double check because call is expensive + if (options.isDebug()) { + String errorMessage = getErrorMessageFromStream(connection); + logger.log(ERROR, errorMessage); + } + + return TransportResult.error(responseCode); + } + + logger.log(DEBUG, message); + + return TransportResult.success(); } catch (IOException e) { - logger.log(ERROR, e, "Error while closing the connection."); + logger.log(ERROR, e, "Error reading and logging the response stream"); } finally { - connection.disconnect(); + closeAndDisconnect(connection); } + return TransportResult.error(); } /** - * Returns a TransportResult error with the given responseCode + * Closes the Response stream and disconnect the connection * * @param connection the HttpURLConnection - * @param ioException the IOException - * @return the TransportResult error */ - private @NotNull TransportResult getResultFromErrorCode( - final @NotNull HttpURLConnection connection, final @NotNull IOException ioException) { + private void closeAndDisconnect(final @NotNull HttpURLConnection connection) { try { - final int responseCode = connection.getResponseCode(); - - logErrorInPayload(connection); - return TransportResult.error(responseCode); - } catch (IOException responseCodeException) { - logger.log(ERROR, responseCodeException, "Error getting responseCode"); - - // this should not stop us from continuing. - return getDefaultErrorResult(ioException); + connection.getInputStream().close(); + } catch (IOException ignored) { + // connection is already closed + } finally { + connection.disconnect(); } } - /** - * Logs a default error message and return the TransportResult error with -1 responseCode - * - * @param exception the Exception - * @return the TransportResult error - */ - private @NotNull TransportResult getDefaultErrorResult(final @NotNull Exception exception) { - logger.log( - WARNING, "Failed to obtain error message while analyzing event send failure.", exception); - return TransportResult.error(); - } - /** * Read retry after headers and update the rate limit Dictionary * @@ -470,31 +460,13 @@ private long parseRetryAfterOrDefault(final @Nullable String retryAfterHeader) { return retryAfterMillis; } - /** - * Logs the error message from the ErrorStream - * - * @param connection the HttpURLConnection - */ - private void logErrorInPayload(final @NotNull HttpURLConnection connection) { - // just because its expensive, but internally isDebug is already checked when - // .log() is called - if (options.isDebug()) { - String errorMessage = getErrorMessageFromStream(connection); - if (null == errorMessage || errorMessage.isEmpty()) { - errorMessage = "An exception occurred while submitting the event to the Sentry server."; - } - - logger.log(DEBUG, errorMessage); - } - } - /** * Reads the error message from the error stream * * @param connection the HttpURLConnection * @return the error message or null if none */ - private @Nullable String getErrorMessageFromStream(final @NotNull HttpURLConnection connection) { + private @NotNull String getErrorMessageFromStream(final @NotNull HttpURLConnection connection) { try (final InputStream errorStream = connection.getErrorStream(); final BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream, UTF_8))) { @@ -511,9 +483,18 @@ private void logErrorInPayload(final @NotNull HttpURLConnection connection) { } return sb.toString(); } catch (IOException e) { - logger.log(ERROR, e, "Exception while reading the error message from the connection"); + return "Failed to obtain error message while analyzing send failure."; } - return null; + } + + /** + * Returns if response code is OK=200 + * + * @param responseCode the response code + * @return true if it is OK=200 or false otherwise + */ + private boolean isSuccessfulResponseCode(final int responseCode) { + return responseCode == HTTP_OK; } @Override diff --git a/sentry-core/src/test/java/io/sentry/core/transport/HttpTransportTest.kt b/sentry-core/src/test/java/io/sentry/core/transport/HttpTransportTest.kt index 3170befdc..ffef088f8 100644 --- a/sentry-core/src/test/java/io/sentry/core/transport/HttpTransportTest.kt +++ b/sentry-core/src/test/java/io/sentry/core/transport/HttpTransportTest.kt @@ -61,6 +61,7 @@ class HttpTransportTest { @Test fun `test serializes event`() { val transport = fixture.getSUT() + whenever(fixture.connection.responseCode).thenReturn(200) val event = SentryEvent() @@ -73,6 +74,7 @@ class HttpTransportTest { @Test fun `test serializes envelope`() { val transport = fixture.getSUT() + whenever(fixture.connection.responseCode).thenReturn(200) val envelope = SentryEnvelope.fromSession(fixture.serializer, createSession())