Skip to content

Commit cdfac96

Browse files
authored
fix(transport): Tag sockets traffic originating from Sentry's HttpConnection (#4340)
1 parent 2365d34 commit cdfac96

File tree

11 files changed

+133
-0
lines changed

11 files changed

+133
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
### Fixes
1010

1111
- Fix TTFD measurement when API called too early ([#4297](https://github.com/getsentry/sentry-java/pull/4297))
12+
- Tag sockets traffic originating from Sentry's HttpConnection ([#4340](https://github.com/getsentry/sentry-java/pull/4340))
13+
- This should suppress the StrictMode's `UntaggedSocketViolation`
1214
- Reduce debug logs verbosity ([#4341](https://github.com/getsentry/sentry-java/pull/4341))
1315
- Fix unregister `SystemEventsBroadcastReceiver` when entering background ([#4338](https://github.com/getsentry/sentry-java/pull/4338))
1416
- This should reduce ANRs seen with this class in the stack trace for Android 14 and above

sentry-android-core/api/sentry-android-core.api

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ public class io/sentry/android/core/AndroidProfiler$ProfileStartData {
111111
public fun <init> (JJLjava/util/Date;)V
112112
}
113113

114+
public final class io/sentry/android/core/AndroidSocketTagger : io/sentry/ISocketTagger {
115+
public static fun getInstance ()Lio/sentry/android/core/AndroidSocketTagger;
116+
public fun tagSockets ()V
117+
public fun untagSockets ()V
118+
}
119+
114120
public final class io/sentry/android/core/AnrIntegration : io/sentry/Integration, java/io/Closeable {
115121
public fun <init> (Landroid/content/Context;)V
116122
public fun close ()V

sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.sentry.NoOpCompositePerformanceCollector;
1616
import io.sentry.NoOpConnectionStatusProvider;
1717
import io.sentry.NoOpContinuousProfiler;
18+
import io.sentry.NoOpSocketTagger;
1819
import io.sentry.NoOpTransactionProfiler;
1920
import io.sentry.NoopVersionDetector;
2021
import io.sentry.ScopeType;
@@ -238,6 +239,9 @@ static void initializeIntegrationsAndProcessors(
238239
if (options.getThreadChecker() instanceof NoOpThreadChecker) {
239240
options.setThreadChecker(AndroidThreadChecker.getInstance());
240241
}
242+
if (options.getSocketTagger() instanceof NoOpSocketTagger) {
243+
options.setSocketTagger(AndroidSocketTagger.getInstance());
244+
}
241245
if (options.getPerformanceCollectors().isEmpty()) {
242246
options.addPerformanceCollector(new AndroidMemoryCollector());
243247
options.addPerformanceCollector(new AndroidCpuCollector(options.getLogger()));
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.sentry.android.core;
2+
3+
import android.net.TrafficStats;
4+
import io.sentry.ISocketTagger;
5+
import org.jetbrains.annotations.ApiStatus;
6+
7+
@ApiStatus.Internal
8+
public final class AndroidSocketTagger implements ISocketTagger {
9+
10+
// just a random number to tag outgoing traffic from the Sentry SDK
11+
private static final int SENTRY_TAG = 0xF001;
12+
13+
private static final AndroidSocketTagger instance = new AndroidSocketTagger();
14+
15+
private AndroidSocketTagger() {}
16+
17+
public static AndroidSocketTagger getInstance() {
18+
return instance;
19+
}
20+
21+
@Override
22+
public void tagSockets() {
23+
TrafficStats.setThreadStatsTag(SENTRY_TAG);
24+
}
25+
26+
@Override
27+
public void untagSockets() {
28+
TrafficStats.clearThreadStatsTag();
29+
}
30+
}

sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import io.sentry.DefaultCompositePerformanceCollector
1111
import io.sentry.IConnectionStatusProvider
1212
import io.sentry.IContinuousProfiler
1313
import io.sentry.ILogger
14+
import io.sentry.ISocketTagger
1415
import io.sentry.ITransactionProfiler
1516
import io.sentry.MainEventProcessor
1617
import io.sentry.NoOpContinuousProfiler
@@ -746,6 +747,13 @@ class AndroidOptionsInitializerTest {
746747
assertTrue { fixture.sentryOptions.threadChecker is AndroidThreadChecker }
747748
}
748749

750+
@Test
751+
fun `AndroidSocketTagger is set to options`() {
752+
fixture.initSut()
753+
754+
assertTrue { fixture.sentryOptions.socketTagger is AndroidSocketTagger }
755+
}
756+
749757
@Test
750758
fun `does not install ComposeGestureTargetLocator, if sentry-compose is not available`() {
751759
fixture.initSutWithClassLoader()
@@ -859,6 +867,7 @@ class AndroidOptionsInitializerTest {
859867
setModulesLoader(mock<IModulesLoader>())
860868
setDebugMetaLoader(mock<IDebugMetaLoader>())
861869
threadChecker = mock<IThreadChecker>()
870+
setSocketTagger(mock<ISocketTagger>())
862871
compositePerformanceCollector = mock<CompositePerformanceCollector>()
863872
})
864873

@@ -868,6 +877,7 @@ class AndroidOptionsInitializerTest {
868877
assertFalse { fixture.sentryOptions.modulesLoader is AssetsModulesLoader }
869878
assertFalse { fixture.sentryOptions.debugMetaLoader is AssetsDebugMetaLoader }
870879
assertFalse { fixture.sentryOptions.threadChecker is AndroidThreadChecker }
880+
assertFalse { fixture.sentryOptions.socketTagger is AndroidSocketTagger }
871881
assertFalse { fixture.sentryOptions.compositePerformanceCollector is DefaultCompositePerformanceCollector }
872882
}
873883
}

sentry/api/sentry.api

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,11 @@ public abstract interface class io/sentry/ISerializer {
10281028
public abstract fun serialize (Ljava/util/Map;)Ljava/lang/String;
10291029
}
10301030

1031+
public abstract interface class io/sentry/ISocketTagger {
1032+
public abstract fun tagSockets ()V
1033+
public abstract fun untagSockets ()V
1034+
}
1035+
10311036
public abstract interface class io/sentry/ISpan {
10321037
public abstract fun finish ()V
10331038
public abstract fun finish (Lio/sentry/SpanStatus;)V
@@ -1697,6 +1702,12 @@ public final class io/sentry/NoOpScopesStorage : io/sentry/IScopesStorage {
16971702
public fun set (Lio/sentry/IScopes;)Lio/sentry/ISentryLifecycleToken;
16981703
}
16991704

1705+
public final class io/sentry/NoOpSocketTagger : io/sentry/ISocketTagger {
1706+
public static fun getInstance ()Lio/sentry/ISocketTagger;
1707+
public fun tagSockets ()V
1708+
public fun untagSockets ()V
1709+
}
1710+
17001711
public final class io/sentry/NoOpSpan : io/sentry/ISpan {
17011712
public fun finish ()V
17021713
public fun finish (Lio/sentry/SpanStatus;)V
@@ -3108,6 +3119,7 @@ public class io/sentry/SentryOptions {
31083119
public fun getSessionReplay ()Lio/sentry/SentryReplayOptions;
31093120
public fun getSessionTrackingIntervalMillis ()J
31103121
public fun getShutdownTimeoutMillis ()J
3122+
public fun getSocketTagger ()Lio/sentry/ISocketTagger;
31113123
public fun getSpanFactory ()Lio/sentry/ISpanFactory;
31123124
public fun getSpotlightConnectionUrl ()Ljava/lang/String;
31133125
public fun getSslSocketFactory ()Ljavax/net/ssl/SSLSocketFactory;
@@ -3244,6 +3256,7 @@ public class io/sentry/SentryOptions {
32443256
public fun setSessionReplay (Lio/sentry/SentryReplayOptions;)V
32453257
public fun setSessionTrackingIntervalMillis (J)V
32463258
public fun setShutdownTimeoutMillis (J)V
3259+
public fun setSocketTagger (Lio/sentry/ISocketTagger;)V
32473260
public fun setSpanFactory (Lio/sentry/ISpanFactory;)V
32483261
public fun setSpotlightConnectionUrl (Ljava/lang/String;)V
32493262
public fun setSslSocketFactory (Ljavax/net/ssl/SSLSocketFactory;)V
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.sentry;
2+
3+
public interface ISocketTagger {
4+
/** Tags the sockets traffic originating from the Sentry HttpConnection thread. */
5+
void tagSockets();
6+
7+
/** Untags the sockets traffic originating from the Sentry HttpConnection thread. */
8+
void untagSockets();
9+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.sentry;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
public final class NoOpSocketTagger implements ISocketTagger {
6+
7+
private static final NoOpSocketTagger instance = new NoOpSocketTagger();
8+
9+
private NoOpSocketTagger() {}
10+
11+
public static @NotNull ISocketTagger getInstance() {
12+
return instance;
13+
}
14+
15+
@Override
16+
public void tagSockets() {
17+
// No operation
18+
}
19+
20+
@Override
21+
public void untagSockets() {
22+
// No operation
23+
}
24+
}

sentry/src/main/java/io/sentry/SentryOptions.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ public class SentryOptions {
566566
*/
567567
private boolean startProfilerOnAppStart = false;
568568

569+
private @NotNull ISocketTagger socketTagger = NoOpSocketTagger.getInstance();
570+
569571
/**
570572
* Adds an event processor
571573
*
@@ -2827,6 +2829,24 @@ public boolean isCaptureOpenTelemetryEvents() {
28272829
return captureOpenTelemetryEvents;
28282830
}
28292831

2832+
/**
2833+
* Returns the SocketTagger
2834+
*
2835+
* @return the socket tagger
2836+
*/
2837+
public @NotNull ISocketTagger getSocketTagger() {
2838+
return socketTagger;
2839+
}
2840+
2841+
/**
2842+
* Sets the SocketTagger
2843+
*
2844+
* @param socketTagger the socket tagger
2845+
*/
2846+
public void setSocketTagger(final @Nullable ISocketTagger socketTagger) {
2847+
this.socketTagger = socketTagger != null ? socketTagger : NoOpSocketTagger.getInstance();
2848+
}
2849+
28302850
/**
28312851
* Load the lazy fields. Useful to load in the background, so that results are already cached. DO
28322852
* NOT CALL THIS METHOD ON THE MAIN THREAD.

sentry/src/main/java/io/sentry/transport/HttpConnection.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ HttpURLConnection open() throws IOException {
146146
}
147147

148148
public @NotNull TransportResult send(final @NotNull SentryEnvelope envelope) throws IOException {
149+
options.getSocketTagger().tagSockets();
149150
final HttpURLConnection connection = createConnection();
150151
TransportResult result;
151152

@@ -161,6 +162,7 @@ HttpURLConnection open() throws IOException {
161162
"An exception occurred while submitting the envelope to the Sentry server.");
162163
} finally {
163164
result = readAndLog(connection);
165+
options.getSocketTagger().untagSockets();
164166
}
165167
return result;
166168
}

0 commit comments

Comments
 (0)