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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
- Report process init time as a span for app start performance ([#3159](https://github.com/getsentry/sentry-java/pull/3159))
- (perf-v2): Calculate frame delay on a span level ([#3197](https://github.com/getsentry/sentry-java/pull/3197))
- Resolve spring properties in @SentryCheckIn annotation ([#3194](https://github.com/getsentry/sentry-java/pull/3194))
- Experimental: Add Spotlight integration ([#3166](https://github.com/getsentry/sentry-java/pull/3166))
- For more details about Spotlight head over to https://spotlightjs.com/
- Set `options.isEnableSpotlight = true` to enable Spotlight

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryOptions.BeforeSendCallback
import io.sentry.Session
import io.sentry.ShutdownHookIntegration
import io.sentry.SpotlightIntegration
import io.sentry.SystemOutLogger
import io.sentry.UncaughtExceptionHandlerIntegration
import io.sentry.android.core.cache.AndroidEnvelopeCache
Expand Down Expand Up @@ -412,7 +413,7 @@ class SentryAndroidTest {
fixture.initSut(context = mock<Application>()) { options ->
optionsRef = options
options.dsn = "https://[email protected]/123"
assertEquals(19, options.integrations.size)
assertEquals(20, options.integrations.size)
options.integrations.removeAll {
it is UncaughtExceptionHandlerIntegration ||
it is ShutdownHookIntegration ||
Expand All @@ -431,7 +432,8 @@ class SentryAndroidTest {
it is SystemEventsBreadcrumbsIntegration ||
it is NetworkBreadcrumbsIntegration ||
it is TempSensorBreadcrumbsIntegration ||
it is PhoneStateBreadcrumbsIntegration
it is PhoneStateBreadcrumbsIntegration ||
it is SpotlightIntegration
}
}
assertEquals(0, optionsRef.integrations.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network"
tools:ignore="GoogleAppIndexingWarning, UnusedAttribute">

<activity
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<!-- To enable spotlight we need to allow cleartext traffic from the emulator to the host machine for now-->
<!-- See https://developer.android.com/studio/run/emulator-networking for more details -->
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ sentry.ignored-checkins=ignored_monitor_slug_1,ignored_monitor_slug_2
sentry.debug=true
sentry.graphql.ignored-error-types=SOME_ERROR,ANOTHER_ERROR
sentry.enable-backpressure-handling=true
sentry.enable-spotlight=true
sentry.enablePrettySerializationOutput=false
in-app-includes="io.sentry.samples"

# Uncomment and set to true to enable aot compatibility
Expand Down
18 changes: 18 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,7 @@ public class io/sentry/SentryOptions {
public static fun empty ()Lio/sentry/SentryOptions;
public fun getBackpressureMonitor ()Lio/sentry/backpressure/IBackpressureMonitor;
public fun getBeforeBreadcrumb ()Lio/sentry/SentryOptions$BeforeBreadcrumbCallback;
public fun getBeforeEnvelopeCallback ()Lio/sentry/SentryOptions$BeforeEnvelopeCallback;
public fun getBeforeSend ()Lio/sentry/SentryOptions$BeforeSendCallback;
public fun getBeforeSendTransaction ()Lio/sentry/SentryOptions$BeforeSendTransactionCallback;
public fun getBundleIds ()Ljava/util/Set;
Expand Down Expand Up @@ -2221,6 +2222,7 @@ public class io/sentry/SentryOptions {
public fun getSessionTrackingIntervalMillis ()J
public fun getShutdownTimeout ()J
public fun getShutdownTimeoutMillis ()J
public fun getSpotlightConnectionUrl ()Ljava/lang/String;
public fun getSslSocketFactory ()Ljavax/net/ssl/SSLSocketFactory;
public fun getTags ()Ljava/util/Map;
public fun getTracePropagationTargets ()Ljava/util/List;
Expand All @@ -2243,6 +2245,7 @@ public class io/sentry/SentryOptions {
public fun isEnableExternalConfiguration ()Z
public fun isEnablePrettySerializationOutput ()Z
public fun isEnableShutdownHook ()Z
public fun isEnableSpotlight ()Z
public fun isEnableTimeToFullDisplayTracing ()Z
public fun isEnableUncaughtExceptionHandler ()Z
public fun isEnableUserInteractionBreadcrumbs ()Z
Expand All @@ -2262,6 +2265,7 @@ public class io/sentry/SentryOptions {
public fun setAttachThreads (Z)V
public fun setBackpressureMonitor (Lio/sentry/backpressure/IBackpressureMonitor;)V
public fun setBeforeBreadcrumb (Lio/sentry/SentryOptions$BeforeBreadcrumbCallback;)V
public fun setBeforeEnvelopeCallback (Lio/sentry/SentryOptions$BeforeEnvelopeCallback;)V
public fun setBeforeSend (Lio/sentry/SentryOptions$BeforeSendCallback;)V
public fun setBeforeSendTransaction (Lio/sentry/SentryOptions$BeforeSendTransactionCallback;)V
public fun setCacheDirPath (Ljava/lang/String;)V
Expand All @@ -2281,6 +2285,7 @@ public class io/sentry/SentryOptions {
public fun setEnableExternalConfiguration (Z)V
public fun setEnablePrettySerializationOutput (Z)V
public fun setEnableShutdownHook (Z)V
public fun setEnableSpotlight (Z)V
public fun setEnableTimeToFullDisplayTracing (Z)V
public fun setEnableTracing (Ljava/lang/Boolean;)V
public fun setEnableUncaughtExceptionHandler (Z)V
Expand Down Expand Up @@ -2328,6 +2333,7 @@ public class io/sentry/SentryOptions {
public fun setSessionTrackingIntervalMillis (J)V
public fun setShutdownTimeout (J)V
public fun setShutdownTimeoutMillis (J)V
public fun setSpotlightConnectionUrl (Ljava/lang/String;)V
public fun setSslSocketFactory (Ljavax/net/ssl/SSLSocketFactory;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTraceOptionsRequests (Z)V
Expand All @@ -2347,6 +2353,10 @@ public abstract interface class io/sentry/SentryOptions$BeforeBreadcrumbCallback
public abstract fun execute (Lio/sentry/Breadcrumb;Lio/sentry/Hint;)Lio/sentry/Breadcrumb;
}

public abstract interface class io/sentry/SentryOptions$BeforeEnvelopeCallback {
public abstract fun execute (Lio/sentry/SentryEnvelope;Lio/sentry/Hint;)V
}

public abstract interface class io/sentry/SentryOptions$BeforeSendCallback {
public abstract fun execute (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
}
Expand Down Expand Up @@ -2721,6 +2731,14 @@ public final class io/sentry/SpanStatus$Deserializer : io/sentry/JsonDeserialize
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/SpotlightIntegration : io/sentry/Integration, io/sentry/SentryOptions$BeforeEnvelopeCallback, java/io/Closeable {
public fun <init> ()V
public fun close ()V
public fun execute (Lio/sentry/SentryEnvelope;Lio/sentry/Hint;)V
public fun getSpotlightConnectionUrl ()Ljava/lang/String;
public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V
}

public final class io/sentry/SystemOutLogger : io/sentry/ILogger {
public fun <init> ()V
public fun isEnabled (Lio/sentry/SentryLevel;)Z
Expand Down
44 changes: 29 additions & 15 deletions sentry/src/main/java/io/sentry/SentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,12 @@ private boolean shouldApplyScopeData(final @NotNull CheckIn event, final @NotNul

final boolean shouldSendAttachments = event != null;
List<Attachment> attachments = shouldSendAttachments ? getAttachments(hint) : null;
final SentryEnvelope envelope =
final @Nullable SentryEnvelope envelope =
buildEnvelope(event, attachments, session, traceContext, null);

hint.clear();
if (envelope != null) {
transport.send(envelope, hint);
sentryId = sendEnvelope(envelope, hint);
}
} catch (IOException | SentryEnvelopeException e) {
options.getLogger().log(SentryLevel.WARNING, e, "Capturing event %s failed.", sentryId);
Expand Down Expand Up @@ -445,8 +445,8 @@ public void captureUserFeedback(final @NotNull UserFeedback userFeedback) {
.log(SentryLevel.DEBUG, "Capturing userFeedback: %s", userFeedback.getEventId());

try {
final SentryEnvelope envelope = buildEnvelope(userFeedback);
transport.send(envelope);
final @NotNull SentryEnvelope envelope = buildEnvelope(userFeedback);
sendEnvelope(envelope, null);
} catch (IOException e) {
options
.getLogger()
Expand Down Expand Up @@ -582,17 +582,33 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint

try {
hint.clear();
transport.send(envelope, hint);
return sendEnvelope(envelope, hint);
} catch (IOException e) {
options.getLogger().log(SentryLevel.ERROR, "Failed to capture envelope.", e);
return SentryId.EMPTY_ID;
}
final SentryId eventId = envelope.getHeader().getEventId();
if (eventId != null) {
return eventId;
return SentryId.EMPTY_ID;
}

private @NotNull SentryId sendEnvelope(
@NotNull final SentryEnvelope envelope, @Nullable final Hint hint) throws IOException {
final @Nullable SentryOptions.BeforeEnvelopeCallback beforeEnvelopeCallback =
options.getBeforeEnvelopeCallback();
if (beforeEnvelopeCallback != null) {
try {
beforeEnvelopeCallback.execute(envelope, hint);
} catch (Throwable e) {
options
.getLogger()
.log(SentryLevel.ERROR, "The BeforeEnvelope callback threw an exception.", e);
}
}
if (hint == null) {
transport.send(envelope);
} else {
return SentryId.EMPTY_ID;
transport.send(envelope, hint);
}
final @Nullable SentryId id = envelope.getHeader().getEventId();
return id != null ? id : SentryId.EMPTY_ID;
}

@Override
Expand Down Expand Up @@ -665,9 +681,7 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint

hint.clear();
if (envelope != null) {
transport.send(envelope, hint);
} else {
sentryId = SentryId.EMPTY_ID;
sentryId = sendEnvelope(envelope, hint);
}
} catch (IOException | SentryEnvelopeException e) {
options.getLogger().log(SentryLevel.WARNING, e, "Capturing transaction %s failed.", sentryId);
Expand Down Expand Up @@ -729,10 +743,10 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint
}
}

final SentryEnvelope envelope = buildEnvelope(checkIn, traceContext);
final @NotNull SentryEnvelope envelope = buildEnvelope(checkIn, traceContext);

hint.clear();
transport.send(envelope, hint);
sentryId = sendEnvelope(envelope, hint);
} catch (IOException e) {
options.getLogger().log(SentryLevel.WARNING, e, "Capturing check-in %s failed.", sentryId);
// if there was an error capturing the event, we return an emptyId
Expand Down
53 changes: 53 additions & 0 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,12 @@ public class SentryOptions {
/** Whether to send modules containing information about versions. */
private boolean sendModules = true;

private @Nullable BeforeEnvelopeCallback beforeEnvelopeCallback;

private boolean enableSpotlight = false;

private @Nullable String spotlightConnectionUrl;

/** Contains a list of monitor slugs for which check-ins should not be sent. */
@ApiStatus.Experimental private @Nullable List<String> ignoredCheckIns = null;

Expand Down Expand Up @@ -2274,6 +2280,39 @@ public void setSessionFlushTimeoutMillis(final long sessionFlushTimeoutMillis) {
this.sessionFlushTimeoutMillis = sessionFlushTimeoutMillis;
}

@ApiStatus.Internal
@Nullable
public BeforeEnvelopeCallback getBeforeEnvelopeCallback() {
return beforeEnvelopeCallback;
}

@ApiStatus.Internal
public void setBeforeEnvelopeCallback(
@Nullable final BeforeEnvelopeCallback beforeEnvelopeCallback) {
this.beforeEnvelopeCallback = beforeEnvelopeCallback;
}

@ApiStatus.Experimental
@Nullable
public String getSpotlightConnectionUrl() {
return spotlightConnectionUrl;
}

@ApiStatus.Experimental
public void setSpotlightConnectionUrl(final @Nullable String spotlightConnectionUrl) {
this.spotlightConnectionUrl = spotlightConnectionUrl;
}

@ApiStatus.Experimental
public boolean isEnableSpotlight() {
return enableSpotlight;
}

@ApiStatus.Experimental
public void setEnableSpotlight(final boolean enableSpotlight) {
this.enableSpotlight = enableSpotlight;
}

/** The BeforeSend callback */
public interface BeforeSendCallback {

Expand Down Expand Up @@ -2345,6 +2384,19 @@ public interface ProfilesSamplerCallback {
Double sample(@NotNull SamplingContext samplingContext);
}

/** The BeforeEnvelope callback */
@ApiStatus.Internal
public interface BeforeEnvelopeCallback {

/**
* A callback which gets called right before an envelope is about to be sent
*
* @param envelope the envelope
* @param hint the hints
*/
void execute(@NotNull SentryEnvelope envelope, @Nullable Hint hint);
}

/**
* Creates SentryOptions instance without initializing any of the internal parts.
*
Expand Down Expand Up @@ -2378,6 +2430,7 @@ private SentryOptions(final boolean empty) {
integrations.add(new UncaughtExceptionHandlerIntegration());

integrations.add(new ShutdownHookIntegration());
integrations.add(new SpotlightIntegration());

eventProcessors.add(new MainEventProcessor(this));
eventProcessors.add(new DuplicateEventDetectionEventProcessor(this));
Expand Down
Loading