Skip to content
This repository was archived by the owner on Aug 30, 2023. It is now read-only.
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
12 changes: 12 additions & 0 deletions sentry-core/src/main/java/io/sentry/core/SentryEnvelope.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,16 @@ public SentryEnvelope(
return new SentryEnvelope(
null, sdkVersion, SentryEnvelopeItem.fromSession(serializer, session));
}

public static @NotNull SentryEnvelope fromEvent(
final @NotNull ISerializer serializer,
final @NotNull SentryEvent event,
final @Nullable SdkVersion sdkVersion)
throws IOException {
Objects.requireNonNull(serializer, "Serializer is required.");
Objects.requireNonNull(event, "Event is required.");

return new SentryEnvelope(
event.getEventId(), sdkVersion, SentryEnvelopeItem.fromEvent(serializer, event));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ private final class EventSender implements Runnable {
private final SentryEvent event;
private final Object hint;
private final IEventCache eventCache;
private final TransportResult failedResult = TransportResult.error(-1);
private final TransportResult failedResult = TransportResult.error();

EventSender(
final @NotNull SentryEvent event,
Expand Down Expand Up @@ -288,7 +288,10 @@ public void run() {

if (transportGate.isConnected()) {
try {
result = transport.send(event);
result =
transport.send(
SentryEnvelope.fromEvent(
options.getSerializer(), event, options.getSdkVersion()));
if (result.isSuccess()) {
eventCache.discard(event);
} else {
Expand Down Expand Up @@ -325,7 +328,7 @@ private final class SessionSender implements Runnable {
private final @NotNull SentryEnvelope envelope;
private final @Nullable Object hint;
private final @NotNull IEnvelopeCache sessionCache;
private final TransportResult failedResult = TransportResult.error(-1);
private final TransportResult failedResult = TransportResult.error();

SessionSender(
final @NotNull SentryEnvelope envelope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import io.sentry.core.ILogger;
import io.sentry.core.ISerializer;
import io.sentry.core.SentryEnvelope;
import io.sentry.core.SentryEvent;
import io.sentry.core.SentryOptions;
import io.sentry.core.util.Objects;
import io.sentry.core.util.StringUtils;
Expand Down Expand Up @@ -76,7 +75,6 @@ public String getCategory() {
private final int connectionTimeout;
private final int readTimeout;
private final boolean bypassSecurity;
private final @NotNull URL storeUrl;
private final @NotNull URL envelopeUrl;
private final @NotNull SentryOptions options;

Expand Down Expand Up @@ -139,42 +137,15 @@ public HttpTransport(

try {
final URI uri = sentryUrl.toURI();
storeUrl = uri.resolve(uri.getPath() + "/store/").toURL();
envelopeUrl = uri.resolve(uri.getPath() + "/envelope/").toURL();
} catch (URISyntaxException | MalformedURLException e) {
throw new IllegalArgumentException("Failed to compose the Sentry's server URL.", e);
}
}

// giving up on testing this method is probably the simplest way of having the rest of the class
// testable...
protected @NotNull HttpURLConnection open(final @Nullable Proxy proxy) throws IOException {
return open(storeUrl, proxy);
}

protected @NotNull HttpURLConnection open(final @NotNull URL url, final @Nullable Proxy proxy)
throws IOException {
return (HttpURLConnection) (proxy == null ? url.openConnection() : url.openConnection(proxy));
}

@Override
public @NotNull TransportResult send(final @NotNull SentryEvent event) throws IOException {
final HttpURLConnection connection = createConnection(false);
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);
} catch (IOException e) {
logger.log(
ERROR, e, "An exception occurred while submitting the event to the Sentry server.");
} finally {
result =
readAndLog(connection, String.format("Event sent %s successfully.", event.getEventId()));
}
return result;
protected @NotNull HttpURLConnection open() throws IOException {
return (HttpURLConnection)
(proxy == null ? envelopeUrl.openConnection() : envelopeUrl.openConnection(proxy));
}

/**
Expand Down Expand Up @@ -235,27 +206,19 @@ public boolean isRetryAfter(final @NotNull String itemType) {
/**
* Create a HttpURLConnection connection Sets specific content-type if its an envelope or not
*
* @param asEnvelope if its an envelope or not
* @return the HttpURLConnection
* @throws IOException if connection has a problem
*/
private @NotNull HttpURLConnection createConnection(boolean asEnvelope) throws IOException {
String contentType = "application/json";
HttpURLConnection connection;
if (asEnvelope) {
connection = open(envelopeUrl, proxy);
contentType = "application/x-sentry-envelope";
} else {
connection = open(proxy);
}
private @NotNull HttpURLConnection createConnection() throws IOException {
HttpURLConnection connection = open();
connectionConfigurator.configure(connection);

connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setChunkedStreamingMode(0);

connection.setRequestProperty("Content-Encoding", "gzip");
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("Content-Type", "application/x-sentry-envelope");
connection.setRequestProperty("Accept", "application/json");

// https://stackoverflow.com/questions/52726909/java-io-ioexception-unexpected-end-of-stream-on-connection/53089882
Expand All @@ -274,7 +237,7 @@ public boolean isRetryAfter(final @NotNull String itemType) {

@Override
public @NotNull TransportResult send(final @NotNull SentryEnvelope envelope) throws IOException {
final HttpURLConnection connection = createConnection(true);
final HttpURLConnection connection = createConnection();
TransportResult result;

try (final OutputStream outputStream = connection.getOutputStream();
Expand All @@ -286,7 +249,7 @@ public boolean isRetryAfter(final @NotNull String itemType) {
logger.log(
ERROR, e, "An exception occurred while submitting the envelope to the Sentry server.");
} finally {
result = readAndLog(connection, "Envelope sent successfully.");
result = readAndLog(connection);
}
return result;
}
Expand All @@ -295,11 +258,9 @@ public boolean isRetryAfter(final @NotNull String itemType) {
* 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 @NotNull TransportResult readAndLog(
final @NotNull HttpURLConnection connection, final @NotNull String message) {
private @NotNull TransportResult readAndLog(final @NotNull HttpURLConnection connection) {
try {
final int responseCode = connection.getResponseCode();

Expand All @@ -316,7 +277,7 @@ public boolean isRetryAfter(final @NotNull String itemType) {
return TransportResult.error(responseCode);
}

logger.log(DEBUG, message);
logger.log(DEBUG, "Envelope sent successfully.");

return TransportResult.success();
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package io.sentry.core.transport;

import io.sentry.core.SentryEnvelope;
import io.sentry.core.SentryEvent;
import java.io.Closeable;
import java.io.IOException;

/** A transport is in charge of sending the event to the Sentry server. */
public interface ITransport extends Closeable {
TransportResult send(SentryEvent event) throws IOException;

boolean isRetryAfter(String type);

TransportResult send(SentryEnvelope envelope) throws IOException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.sentry.core.transport;

import io.sentry.core.SentryEnvelope;
import io.sentry.core.SentryEvent;
import java.io.IOException;
import org.jetbrains.annotations.ApiStatus;

Expand All @@ -16,11 +15,6 @@ public static NoOpTransport getInstance() {

private NoOpTransport() {}

@Override
public TransportResult send(SentryEvent event) throws IOException {
return TransportResult.success();
}

@Override
public boolean isRetryAfter(String type) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.sentry.core.ISerializer;
import io.sentry.core.SentryEnvelope;
import io.sentry.core.SentryEvent;
import io.sentry.core.util.Objects;
import java.io.BufferedWriter;
import java.io.IOException;
Expand All @@ -22,17 +21,6 @@ public StdoutTransport(final @NotNull ISerializer serializer) {
this.serializer = Objects.requireNonNull(serializer, "Serializer is required");
}

@Override
public TransportResult send(final @NotNull SentryEvent event) throws IOException {
Objects.requireNonNull(event, "SentryEvent is required");

try (final Writer writer = new BufferedWriter(new OutputStreamWriter(System.out, UTF_8));
final Writer printWriter = new PrintWriter(writer)) {
serializer.serialize(event, printWriter);
return TransportResult.success();
}
}

@Override
public boolean isRetryAfter(String type) {
return false;
Expand All @@ -47,7 +35,7 @@ public TransportResult send(final @NotNull SentryEnvelope envelope) throws IOExc
serializer.serialize(envelope, printWriter);
return TransportResult.success();
} catch (Exception e) {
return TransportResult.error(-1);
return TransportResult.error();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package io.sentry.core.transport;

import io.sentry.core.SentryEvent;
import org.jetbrains.annotations.NotNull;

/**
* A result of {@link ITransport#send(SentryEvent)}. Note that this class is intentionally not
* subclassable and has only two factory methods to capture the 2 possible states - success or
* error.
* A result of {@link ITransport#send(io.sentry.core.SentryEnvelope)}. Note that this class is
* intentionally not subclassable and has only two factory methods to capture the 2 possible states
* - success or error.
*/
public abstract class TransportResult {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class AsyncConnectionTest {
// given
val ev = mock<SentryEvent>()
whenever(fixture.transportGate.isConnected).thenReturn(true)
whenever(fixture.transport.send(any<SentryEvent>())).thenReturn(TransportResult.success())
whenever(fixture.transport.send(any())).thenReturn(TransportResult.success())

// when
fixture.getSUT().send(ev)
Expand All @@ -68,7 +68,9 @@ class AsyncConnectionTest {
// because storeBeforeSend is enabled by default
order.verify(fixture.eventCache).store(eq(ev))

order.verify(fixture.transport).send(eq(ev))
order.verify(fixture.transport).send(check {
assertEquals(ev.eventId, it.header.eventId)
})
order.verify(fixture.eventCache).discard(eq(ev))
}

Expand Down Expand Up @@ -125,7 +127,7 @@ class AsyncConnectionTest {
// given
val ev = mock<SentryEvent>()
whenever(fixture.transportGate.isConnected).thenReturn(true)
whenever(fixture.transport.send(any<SentryEvent>())).thenReturn(TransportResult.error(500))
whenever(fixture.transport.send(any())).thenReturn(TransportResult.error(500))

// when
try {
Expand All @@ -140,7 +142,9 @@ class AsyncConnectionTest {
// because storeBeforeSend is enabled by default
order.verify(fixture.eventCache).store(eq(ev))

order.verify(fixture.transport).send(eq(ev))
order.verify(fixture.transport).send(check {
assertEquals(ev.eventId, it.header.eventId)
})
verify(fixture.eventCache, never()).discard(any())
}

Expand Down Expand Up @@ -173,7 +177,7 @@ class AsyncConnectionTest {
// given
val ev = mock<SentryEvent>()
whenever(fixture.transportGate.isConnected).thenReturn(true)
whenever(fixture.transport.send(any<SentryEvent>())).thenThrow(IOException())
whenever(fixture.transport.send(any())).thenThrow(IOException())

// when
try {
Expand All @@ -184,7 +188,9 @@ class AsyncConnectionTest {

// then
val order = inOrder(fixture.transport, fixture.eventCache)
order.verify(fixture.transport).send(eq(ev))
order.verify(fixture.transport).send(check {
assertEquals(ev.eventId, it.header.eventId)
})
verify(fixture.eventCache, never()).discard(any())
}

Expand Down
Loading