Skip to content
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
### Fixes

- Fix TTFD measurement when API called too early ([#4297](https://github.com/getsentry/sentry-java/pull/4297))
- Tag sockets traffic originating from Sentry's HttpConnection ([#4340](https://github.com/getsentry/sentry-java/pull/4340))
- This should suppress the StrictMode's `UntaggedSocketViolation`
- Reduce debug logs verbosity ([#4341](https://github.com/getsentry/sentry-java/pull/4341))
- Fix unregister `SystemEventsBroadcastReceiver` when entering background ([#4338](https://github.com/getsentry/sentry-java/pull/4338))
- This should reduce ANRs seen with this class in the stack trace for Android 14 and above
Expand Down
6 changes: 6 additions & 0 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ public class io/sentry/android/core/AndroidProfiler$ProfileStartData {
public fun <init> (JJLjava/util/Date;)V
}

public final class io/sentry/android/core/AndroidSocketTagger : io/sentry/ISocketTagger {
public static fun getInstance ()Lio/sentry/android/core/AndroidSocketTagger;
public fun tagSockets ()V
public fun untagSockets ()V
}

public final class io/sentry/android/core/AnrIntegration : io/sentry/Integration, java/io/Closeable {
public fun <init> (Landroid/content/Context;)V
public fun close ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.sentry.NoOpCompositePerformanceCollector;
import io.sentry.NoOpConnectionStatusProvider;
import io.sentry.NoOpContinuousProfiler;
import io.sentry.NoOpSocketTagger;
import io.sentry.NoOpTransactionProfiler;
import io.sentry.NoopVersionDetector;
import io.sentry.ScopeType;
Expand Down Expand Up @@ -238,6 +239,9 @@ static void initializeIntegrationsAndProcessors(
if (options.getThreadChecker() instanceof NoOpThreadChecker) {
options.setThreadChecker(AndroidThreadChecker.getInstance());
}
if (options.getSocketTagger() instanceof NoOpSocketTagger) {
options.setSocketTagger(AndroidSocketTagger.getInstance());
}
if (options.getPerformanceCollectors().isEmpty()) {
options.addPerformanceCollector(new AndroidMemoryCollector());
options.addPerformanceCollector(new AndroidCpuCollector(options.getLogger()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.sentry.android.core;

import android.net.TrafficStats;
import io.sentry.ISocketTagger;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public final class AndroidSocketTagger implements ISocketTagger {

// just a random number to tag outgoing traffic from the Sentry SDK
private static final int SENTRY_TAG = 0xF001;

private static final AndroidSocketTagger instance = new AndroidSocketTagger();

private AndroidSocketTagger() {}

public static AndroidSocketTagger getInstance() {
return instance;
}

@Override
public void tagSockets() {
TrafficStats.setThreadStatsTag(SENTRY_TAG);
}

@Override
public void untagSockets() {
TrafficStats.clearThreadStatsTag();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.sentry.DefaultCompositePerformanceCollector
import io.sentry.IConnectionStatusProvider
import io.sentry.IContinuousProfiler
import io.sentry.ILogger
import io.sentry.ISocketTagger
import io.sentry.ITransactionProfiler
import io.sentry.MainEventProcessor
import io.sentry.NoOpContinuousProfiler
Expand Down Expand Up @@ -746,6 +747,13 @@ class AndroidOptionsInitializerTest {
assertTrue { fixture.sentryOptions.threadChecker is AndroidThreadChecker }
}

@Test
fun `AndroidSocketTagger is set to options`() {
fixture.initSut()

assertTrue { fixture.sentryOptions.socketTagger is AndroidSocketTagger }
}

@Test
fun `does not install ComposeGestureTargetLocator, if sentry-compose is not available`() {
fixture.initSutWithClassLoader()
Expand Down Expand Up @@ -859,6 +867,7 @@ class AndroidOptionsInitializerTest {
setModulesLoader(mock<IModulesLoader>())
setDebugMetaLoader(mock<IDebugMetaLoader>())
threadChecker = mock<IThreadChecker>()
setSocketTagger(mock<ISocketTagger>())
compositePerformanceCollector = mock<CompositePerformanceCollector>()
})

Expand All @@ -868,6 +877,7 @@ class AndroidOptionsInitializerTest {
assertFalse { fixture.sentryOptions.modulesLoader is AssetsModulesLoader }
assertFalse { fixture.sentryOptions.debugMetaLoader is AssetsDebugMetaLoader }
assertFalse { fixture.sentryOptions.threadChecker is AndroidThreadChecker }
assertFalse { fixture.sentryOptions.socketTagger is AndroidSocketTagger }
assertFalse { fixture.sentryOptions.compositePerformanceCollector is DefaultCompositePerformanceCollector }
}
}
13 changes: 13 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,11 @@ public abstract interface class io/sentry/ISerializer {
public abstract fun serialize (Ljava/util/Map;)Ljava/lang/String;
}

public abstract interface class io/sentry/ISocketTagger {
public abstract fun tagSockets ()V
public abstract fun untagSockets ()V
}

public abstract interface class io/sentry/ISpan {
public abstract fun finish ()V
public abstract fun finish (Lio/sentry/SpanStatus;)V
Expand Down Expand Up @@ -1697,6 +1702,12 @@ public final class io/sentry/NoOpScopesStorage : io/sentry/IScopesStorage {
public fun set (Lio/sentry/IScopes;)Lio/sentry/ISentryLifecycleToken;
}

public final class io/sentry/NoOpSocketTagger : io/sentry/ISocketTagger {
public static fun getInstance ()Lio/sentry/ISocketTagger;
public fun tagSockets ()V
public fun untagSockets ()V
}

public final class io/sentry/NoOpSpan : io/sentry/ISpan {
public fun finish ()V
public fun finish (Lio/sentry/SpanStatus;)V
Expand Down Expand Up @@ -3108,6 +3119,7 @@ public class io/sentry/SentryOptions {
public fun getSessionReplay ()Lio/sentry/SentryReplayOptions;
public fun getSessionTrackingIntervalMillis ()J
public fun getShutdownTimeoutMillis ()J
public fun getSocketTagger ()Lio/sentry/ISocketTagger;
public fun getSpanFactory ()Lio/sentry/ISpanFactory;
public fun getSpotlightConnectionUrl ()Ljava/lang/String;
public fun getSslSocketFactory ()Ljavax/net/ssl/SSLSocketFactory;
Expand Down Expand Up @@ -3244,6 +3256,7 @@ public class io/sentry/SentryOptions {
public fun setSessionReplay (Lio/sentry/SentryReplayOptions;)V
public fun setSessionTrackingIntervalMillis (J)V
public fun setShutdownTimeoutMillis (J)V
public fun setSocketTagger (Lio/sentry/ISocketTagger;)V
public fun setSpanFactory (Lio/sentry/ISpanFactory;)V
public fun setSpotlightConnectionUrl (Ljava/lang/String;)V
public fun setSslSocketFactory (Ljavax/net/ssl/SSLSocketFactory;)V
Expand Down
9 changes: 9 additions & 0 deletions sentry/src/main/java/io/sentry/ISocketTagger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.sentry;

public interface ISocketTagger {
/** Tags the sockets traffic originating from the Sentry HttpConnection thread. */
void tagSockets();

/** Untags the sockets traffic originating from the Sentry HttpConnection thread. */
void untagSockets();
}
24 changes: 24 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpSocketTagger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.sentry;

import org.jetbrains.annotations.NotNull;

public final class NoOpSocketTagger implements ISocketTagger {

private static final NoOpSocketTagger instance = new NoOpSocketTagger();

private NoOpSocketTagger() {}

public static @NotNull ISocketTagger getInstance() {
return instance;
}

@Override
public void tagSockets() {
// No operation
}

@Override
public void untagSockets() {
// No operation
}
}
20 changes: 20 additions & 0 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,8 @@ public class SentryOptions {
*/
private boolean startProfilerOnAppStart = false;

private @NotNull ISocketTagger socketTagger = NoOpSocketTagger.getInstance();

/**
* Adds an event processor
*
Expand Down Expand Up @@ -2827,6 +2829,24 @@ public boolean isCaptureOpenTelemetryEvents() {
return captureOpenTelemetryEvents;
}

/**
* Returns the SocketTagger
*
* @return the socket tagger
*/
public @NotNull ISocketTagger getSocketTagger() {
return socketTagger;
}

/**
* Sets the SocketTagger
*
* @param socketTagger the socket tagger
*/
public void setSocketTagger(final @Nullable ISocketTagger socketTagger) {
this.socketTagger = socketTagger != null ? socketTagger : NoOpSocketTagger.getInstance();
}

/**
* Load the lazy fields. Useful to load in the background, so that results are already cached. DO
* NOT CALL THIS METHOD ON THE MAIN THREAD.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ HttpURLConnection open() throws IOException {
}

public @NotNull TransportResult send(final @NotNull SentryEnvelope envelope) throws IOException {
options.getSocketTagger().tagSockets();
final HttpURLConnection connection = createConnection();
TransportResult result;

Expand All @@ -161,6 +162,7 @@ HttpURLConnection open() throws IOException {
"An exception occurred while submitting the envelope to the Sentry server.");
} finally {
result = readAndLog(connection);
options.getSocketTagger().untagSockets();
}
return result;
}
Expand Down
13 changes: 13 additions & 0 deletions sentry/src/test/java/io/sentry/transport/HttpConnectionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.sentry.transport

import io.sentry.ILogger
import io.sentry.ISerializer
import io.sentry.ISocketTagger
import io.sentry.RequestDetails
import io.sentry.SentryEnvelope
import io.sentry.SentryEvent
Expand Down Expand Up @@ -41,6 +42,7 @@ class HttpConnectionTest {
val rateLimiter = mock<RateLimiter>()
var sslSocketFactory: SSLSocketFactory? = null
val requestDetails = mock<RequestDetails>()
val socketTagger = mock<ISocketTagger>()
val options = SentryOptions()

init {
Expand All @@ -58,6 +60,7 @@ class HttpConnectionTest {
options.setSerializer(serializer)
options.proxy = proxy
options.sslSocketFactory = sslSocketFactory
options.setSocketTagger(socketTagger)

return HttpConnection(options, requestDetails, authenticatorWrapper, rateLimiter)
}
Expand Down Expand Up @@ -262,6 +265,16 @@ class HttpConnectionTest {
verify(fixture.requestDetails.url).openConnection()
}

@Test
fun `tags sockets`() {
val transport = fixture.getSUT()

transport.send(createEnvelope())

verify(fixture.socketTagger).tagSockets()
verify(fixture.socketTagger).untagSockets()
}

private fun createSession(): Session {
return Session("123", User(), "env", "release")
}
Expand Down
Loading