Skip to content

Commit 8c459df

Browse files
authored
Lazily retrieve HostnameCache in MainEventProcessor (#2170)
* Prevent ANR by HostnameCache * Add changelog
1 parent f160e0d commit 8c459df

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Lazily retrieve HostnameCache in MainEventProcessor ([#2170](https://github.com/getsentry/sentry-java/pull/2170))
8+
39
## 6.2.1
410

511
### Fixes

sentry/src/main/java/io/sentry/MainEventProcessor.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,10 @@ public final class MainEventProcessor implements EventProcessor, Closeable {
3131
private final @NotNull SentryOptions options;
3232
private final @NotNull SentryThreadFactory sentryThreadFactory;
3333
private final @NotNull SentryExceptionFactory sentryExceptionFactory;
34-
private final @Nullable HostnameCache hostnameCache;
34+
private volatile @Nullable HostnameCache hostnameCache = null;
3535

3636
public MainEventProcessor(final @NotNull SentryOptions options) {
37-
this(options, options.isAttachServerName() ? HostnameCache.getInstance() : null);
38-
}
39-
40-
MainEventProcessor(
41-
final @NotNull SentryOptions options, final @Nullable HostnameCache hostnameCache) {
4237
this.options = Objects.requireNonNull(options, "The SentryOptions is required.");
43-
this.hostnameCache = hostnameCache;
4438

4539
final SentryStackTraceFactory sentryStackTraceFactory =
4640
new SentryStackTraceFactory(
@@ -53,14 +47,12 @@ public MainEventProcessor(final @NotNull SentryOptions options) {
5347
MainEventProcessor(
5448
final @NotNull SentryOptions options,
5549
final @NotNull SentryThreadFactory sentryThreadFactory,
56-
final @NotNull SentryExceptionFactory sentryExceptionFactory,
57-
final @NotNull HostnameCache hostnameCache) {
50+
final @NotNull SentryExceptionFactory sentryExceptionFactory) {
5851
this.options = Objects.requireNonNull(options, "The SentryOptions is required.");
5952
this.sentryThreadFactory =
6053
Objects.requireNonNull(sentryThreadFactory, "The SentryThreadFactory is required.");
6154
this.sentryExceptionFactory =
6255
Objects.requireNonNull(sentryExceptionFactory, "The SentryExceptionFactory is required.");
63-
this.hostnameCache = Objects.requireNonNull(hostnameCache, "The HostnameCache is required");
6456
}
6557

6658
@Override
@@ -164,8 +156,21 @@ private void setServerName(final @NotNull SentryBaseEvent event) {
164156
event.setServerName(options.getServerName());
165157
}
166158

167-
if (options.isAttachServerName() && hostnameCache != null && event.getServerName() == null) {
168-
event.setServerName(hostnameCache.getHostname());
159+
if (options.isAttachServerName() && event.getServerName() == null) {
160+
ensureHostnameCache();
161+
if (hostnameCache != null) {
162+
event.setServerName(hostnameCache.getHostname());
163+
}
164+
}
165+
}
166+
167+
private void ensureHostnameCache() {
168+
if (hostnameCache == null) {
169+
synchronized (this) {
170+
if (hostnameCache == null) {
171+
hostnameCache = HostnameCache.getInstance();
172+
}
173+
}
169174
}
170175
}
171176

sentry/src/test/java/io/sentry/MainEventProcessorTest.kt

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import io.sentry.protocol.SentryTransaction
1212
import io.sentry.protocol.User
1313
import io.sentry.util.HintUtils
1414
import org.awaitility.kotlin.await
15+
import org.mockito.Mockito
1516
import java.lang.RuntimeException
1617
import java.net.InetAddress
18+
import kotlin.test.AfterTest
1719
import kotlin.test.Test
1820
import kotlin.test.assertEquals
1921
import kotlin.test.assertFalse
@@ -32,10 +34,12 @@ class MainEventProcessorTest {
3234
}
3335
val getLocalhost = mock<InetAddress>()
3436
val sentryTracer = SentryTracer(TransactionContext("", ""), mock())
37+
private val hostnameCacheMock = Mockito.mockStatic(HostnameCache::class.java)
3538

3639
fun getSut(attachThreads: Boolean = true, attachStackTrace: Boolean = true, environment: String? = "environment", tags: Map<String, String> = emptyMap(), sendDefaultPii: Boolean? = null, serverName: String? = "server", host: String? = null, resolveHostDelay: Long? = null, hostnameCacheDuration: Long = 10, proguardUuid: String? = null): MainEventProcessor {
3740
sentryOptions.isAttachThreads = attachThreads
3841
sentryOptions.isAttachStacktrace = attachStackTrace
42+
sentryOptions.isAttachServerName = true
3943
sentryOptions.environment = environment
4044
sentryOptions.serverName = serverName
4145
if (sendDefaultPii != null) {
@@ -52,10 +56,21 @@ class MainEventProcessorTest {
5256
host
5357
}
5458
val hostnameCache = HostnameCache(hostnameCacheDuration) { getLocalhost }
55-
return MainEventProcessor(sentryOptions, hostnameCache)
59+
hostnameCacheMock.`when`<Any> { HostnameCache.getInstance() }.thenReturn(hostnameCache)
60+
61+
return MainEventProcessor(sentryOptions)
62+
}
63+
64+
fun teardown() {
65+
hostnameCacheMock.close()
5666
}
5767
}
5868

69+
@AfterTest
70+
fun teardown() {
71+
fixture.teardown()
72+
}
73+
5974
private val fixture = Fixture()
6075

6176
@Test
@@ -448,7 +463,10 @@ class MainEventProcessorTest {
448463

449464
@Test
450465
fun `when processor is closed, closes hostname cache`() {
451-
val sut = fixture.getSut()
466+
val sut = fixture.getSut(serverName = null)
467+
468+
sut.process(SentryTransaction(fixture.sentryTracer), Hint())
469+
452470
sut.close()
453471
assertNotNull(sut.hostnameCache) {
454472
assertTrue(it.isClosed())

0 commit comments

Comments
 (0)