Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce main thread work on init #3036

Merged
merged 15 commits into from
Nov 27, 2023
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Unreleased

### Fixes

- Reduce main thread work on init ([#3036](https://github.com/getsentry/sentry-java/pull/3036))
- Move Integrations registration to background on init ([#3043](https://github.com/getsentry/sentry-java/pull/3043))

## 6.34.0

### Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
public final class AnrIntegration implements Integration, Closeable {

private final @NotNull Context context;
private boolean isClosed = false;
private final @NotNull Object startLock = new Object();

public AnrIntegration(final @NotNull Context context) {
this.context = context;
Expand Down Expand Up @@ -55,27 +57,47 @@ private void register(final @NotNull IHub hub, final @NotNull SentryAndroidOptio
.log(SentryLevel.DEBUG, "AnrIntegration enabled: %s", options.isAnrEnabled());

if (options.isAnrEnabled()) {
synchronized (watchDogLock) {
if (anrWatchDog == null) {
options
.getLogger()
.log(
SentryLevel.DEBUG,
"ANR timeout in milliseconds: %d",
options.getAnrTimeoutIntervalMillis());

anrWatchDog =
new ANRWatchDog(
options.getAnrTimeoutIntervalMillis(),
options.isAnrReportInDebug(),
error -> reportANR(hub, options, error),
options.getLogger(),
context);
anrWatchDog.start();

options.getLogger().log(SentryLevel.DEBUG, "AnrIntegration installed.");
addIntegrationToSdkVersion();
}
addIntegrationToSdkVersion();
try {
options
.getExecutorService()
.submit(
() -> {
synchronized (startLock) {
if (!isClosed) {
startAnrWatchdog(hub, options);
}
}
});
} catch (Throwable e) {
options
.getLogger()
.log(SentryLevel.DEBUG, "Failed to start AnrIntegration on executor thread.", e);
}
}
}

private void startAnrWatchdog(
final @NotNull IHub hub, final @NotNull SentryAndroidOptions options) {
synchronized (watchDogLock) {
if (anrWatchDog == null) {
options
.getLogger()
.log(
SentryLevel.DEBUG,
"ANR timeout in milliseconds: %d",
options.getAnrTimeoutIntervalMillis());

anrWatchDog =
new ANRWatchDog(
options.getAnrTimeoutIntervalMillis(),
options.isAnrReportInDebug(),
error -> reportANR(hub, options, error),
options.getLogger(),
context);
anrWatchDog.start();

options.getLogger().log(SentryLevel.DEBUG, "AnrIntegration installed.");
}
}
}
Expand Down Expand Up @@ -126,6 +148,9 @@ ANRWatchDog getANRWatchDog() {

@Override
public void close() throws IOException {
synchronized (startLock) {
isClosed = true;
}
synchronized (watchDogLock) {
if (anrWatchDog != null) {
anrWatchDog.interrupt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
public abstract class EnvelopeFileObserverIntegration implements Integration, Closeable {
private @Nullable EnvelopeFileObserver observer;
private @Nullable ILogger logger;
private boolean isClosed = false;
private final @NotNull Object startLock = new Object();

public static @NotNull EnvelopeFileObserverIntegration getOutboxFileObserver() {
return new OutboxEnvelopeFileObserverIntegration();
Expand All @@ -37,30 +39,55 @@ public final void register(final @NotNull IHub hub, final @NotNull SentryOptions
logger.log(
SentryLevel.DEBUG, "Registering EnvelopeFileObserverIntegration for path: %s", path);

final OutboxSender outboxSender =
new OutboxSender(
hub,
options.getEnvelopeReader(),
options.getSerializer(),
logger,
options.getFlushTimeoutMillis());

observer =
new EnvelopeFileObserver(path, outboxSender, logger, options.getFlushTimeoutMillis());
try {
observer.startWatching();
logger.log(SentryLevel.DEBUG, "EnvelopeFileObserverIntegration installed.");
} catch (Throwable e) {
// it could throw eg NoSuchFileException or NullPointerException
options
.getLogger()
.log(SentryLevel.ERROR, "Failed to initialize EnvelopeFileObserverIntegration.", e);
.getExecutorService()
.submit(
() -> {
synchronized (startLock) {
if (!isClosed) {
startOutboxSender(hub, options, path);
}
}
});
} catch (Throwable e) {
logger.log(
SentryLevel.DEBUG,
"Failed to start EnvelopeFileObserverIntegration on executor thread.",
e);
}
}
}

private void startOutboxSender(
stefanosiano marked this conversation as resolved.
Show resolved Hide resolved
final @NotNull IHub hub, final @NotNull SentryOptions options, final @NotNull String path) {
final OutboxSender outboxSender =
new OutboxSender(
hub,
options.getEnvelopeReader(),
options.getSerializer(),
options.getLogger(),
options.getFlushTimeoutMillis());

observer =
new EnvelopeFileObserver(
path, outboxSender, options.getLogger(), options.getFlushTimeoutMillis());
try {
observer.startWatching();
options.getLogger().log(SentryLevel.DEBUG, "EnvelopeFileObserverIntegration installed.");
} catch (Throwable e) {
// it could throw eg NoSuchFileException or NullPointerException
options
.getLogger()
.log(SentryLevel.ERROR, "Failed to initialize EnvelopeFileObserverIntegration.", e);
}
}

@Override
public void close() {
synchronized (startLock) {
isClosed = true;
}
if (observer != null) {
observer.stopWatching();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ public final class PhoneStateBreadcrumbsIntegration implements Integration, Clos
private @Nullable SentryAndroidOptions options;
@TestOnly @Nullable PhoneStateChangeListener listener;
private @Nullable TelephonyManager telephonyManager;
private boolean isClosed = false;
private final @NotNull Object startLock = new Object();

public PhoneStateBreadcrumbsIntegration(final @NotNull Context context) {
this.context = Objects.requireNonNull(context, "Context is required");
}

@SuppressWarnings("deprecation")
@Override
public void register(final @NotNull IHub hub, final @NotNull SentryOptions options) {
Objects.requireNonNull(hub, "Hub is required");
Expand All @@ -46,28 +47,55 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio

if (this.options.isEnableSystemEventBreadcrumbs()
&& Permissions.hasPermission(context, READ_PHONE_STATE)) {
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
try {
listener = new PhoneStateChangeListener(hub);
telephonyManager.listen(listener, android.telephony.PhoneStateListener.LISTEN_CALL_STATE);

options.getLogger().log(SentryLevel.DEBUG, "PhoneStateBreadcrumbsIntegration installed.");
addIntegrationToSdkVersion();
} catch (Throwable e) {
this.options
.getLogger()
.log(SentryLevel.INFO, e, "TelephonyManager is not available or ready to use.");
}
} else {
this.options.getLogger().log(SentryLevel.INFO, "TelephonyManager is not available");
try {
options
.getExecutorService()
.submit(
() -> {
synchronized (startLock) {
if (!isClosed) {
startTelephonyListener(hub, options);
}
}
});
} catch (Throwable e) {
options
.getLogger()
.log(
SentryLevel.DEBUG,
"Failed to start PhoneStateBreadcrumbsIntegration on executor thread.",
e);
}
}
}

@SuppressWarnings("deprecation")
private void startTelephonyListener(
final @NotNull IHub hub, final @NotNull SentryOptions options) {
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
try {
listener = new PhoneStateChangeListener(hub);
telephonyManager.listen(listener, android.telephony.PhoneStateListener.LISTEN_CALL_STATE);

options.getLogger().log(SentryLevel.DEBUG, "PhoneStateBreadcrumbsIntegration installed.");
addIntegrationToSdkVersion();
} catch (Throwable e) {
options
.getLogger()
.log(SentryLevel.INFO, e, "TelephonyManager is not available or ready to use.");
}
} else {
options.getLogger().log(SentryLevel.INFO, "TelephonyManager is not available");
}
}

@SuppressWarnings("deprecation")
@Override
public void close() throws IOException {
synchronized (startLock) {
isClosed = true;
}
if (telephonyManager != null && listener != null) {
telephonyManager.listen(listener, android.telephony.PhoneStateListener.LISTEN_NONE);
listener = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,21 @@ public void register(@NotNull IHub hub, @NotNull SentryOptions options) {
return;
}

final SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForget sender =
factory.create(hub, androidOptions);

if (sender == null) {
androidOptions.getLogger().log(SentryLevel.ERROR, "SendFireAndForget factory is null.");
return;
}

try {
Future<?> future =
androidOptions
.getExecutorService()
.submit(
() -> {
final SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForget sender =
factory.create(hub, androidOptions);

if (sender == null) {
androidOptions
.getLogger()
.log(SentryLevel.ERROR, "SendFireAndForget factory is null.");
return;
}
try {
sender.send();
} catch (Throwable e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public final class SystemEventsBreadcrumbsIntegration implements Integration, Cl
private @Nullable SentryAndroidOptions options;

private final @NotNull List<String> actions;
private boolean isClosed = false;
private final @NotNull Object startLock = new Object();

public SystemEventsBreadcrumbsIntegration(final @NotNull Context context) {
this(context, getDefaultActions());
Expand Down Expand Up @@ -92,27 +94,49 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio
this.options.isEnableSystemEventBreadcrumbs());

if (this.options.isEnableSystemEventBreadcrumbs()) {
receiver = new SystemEventsBroadcastReceiver(hub, this.options.getLogger());
final IntentFilter filter = new IntentFilter();
for (String item : actions) {
filter.addAction(item);
}

try {
// registerReceiver can throw SecurityException but it's not documented in the official docs
ContextUtils.registerReceiver(context, options, receiver, filter);
this.options
.getLogger()
.log(SentryLevel.DEBUG, "SystemEventsBreadcrumbsIntegration installed.");
addIntegrationToSdkVersion();
options
.getExecutorService()
.submit(
() -> {
synchronized (startLock) {
if (!isClosed) {
startSystemEventsReceiver(hub, (SentryAndroidOptions) options);
}
}
});
} catch (Throwable e) {
this.options.setEnableSystemEventBreadcrumbs(false);
this.options
options
.getLogger()
.log(SentryLevel.ERROR, "Failed to initialize SystemEventsBreadcrumbsIntegration.", e);
.log(
SentryLevel.DEBUG,
"Failed to start SystemEventsBreadcrumbsIntegration on executor thread.",
e);
}
}
}

private void startSystemEventsReceiver(
final @NotNull IHub hub, final @NotNull SentryAndroidOptions options) {
receiver = new SystemEventsBroadcastReceiver(hub, options.getLogger());
final IntentFilter filter = new IntentFilter();
for (String item : actions) {
filter.addAction(item);
}
try {
// registerReceiver can throw SecurityException but it's not documented in the official docs
ContextUtils.registerReceiver(context, options, receiver, filter);
options.getLogger().log(SentryLevel.DEBUG, "SystemEventsBreadcrumbsIntegration installed.");
addIntegrationToSdkVersion();
} catch (Throwable e) {
options.setEnableSystemEventBreadcrumbs(false);
options
.getLogger()
.log(SentryLevel.ERROR, "Failed to initialize SystemEventsBreadcrumbsIntegration.", e);
}
}

@SuppressWarnings("deprecation")
private static @NotNull List<String> getDefaultActions() {
final List<String> actions = new ArrayList<>();
Expand Down Expand Up @@ -164,6 +188,9 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio

@Override
public void close() throws IOException {
synchronized (startLock) {
isClosed = true;
}
if (receiver != null) {
context.unregisterReceiver(receiver);
receiver = null;
Expand Down
Loading