Skip to content

Commit

Permalink
Merge c4c253e into 3695453
Browse files Browse the repository at this point in the history
  • Loading branch information
adinauer authored Nov 24, 2022
2 parents 3695453 + c4c253e commit 92bac29
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Add beforeSendTransaction which allows users to filter and change transactions ([#2388](https://github.com/getsentry/sentry-java/pull/2388))

### Fixes

- Use `canonicalName` in Fragment Integration for better de-obfuscation ([#2379](https://github.com/getsentry/sentry-java/pull/2379))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ public static void main(String[] args) throws InterruptedException {
return event;
});

options.setBeforeSendTransaction(
(transaction, hint) -> {
// Drop a transaction:
if (transaction.getTag("SomeTransactionTag") != null) {
return null;
}

return transaction;
});

// Allows inspecting and modifying, returning a new or simply rejecting (returning null)
options.setBeforeBreadcrumb(
(breadcrumb, hint) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ public void contextInitialized(ServletContextEvent sce) {
return event;
});

// Modifications to transaction before it goes out. Could replace the transaction
// altogether
options.setBeforeSendTransaction(
(transaction, hint) -> {
// Drop a transaction altogether:
if (transaction.getTag("SomeTag") != null) {
return null;
}
return transaction;
});

// Allows inspecting and modifying, returning a new or simply rejecting (returning null)
options.setBeforeBreadcrumb(
(breadcrumb, hint) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static class HubConfiguration {
@Order(Ordered.HIGHEST_PRECEDENCE)
public @NotNull Sentry.OptionsConfiguration<SentryOptions> sentryOptionsConfiguration(
final @NotNull ObjectProvider<SentryOptions.BeforeSendCallback> beforeSendCallback,
final @NotNull ObjectProvider<SentryOptions.BeforeSendTransactionCallback> beforeSendTransactionCallback,
final @NotNull ObjectProvider<SentryOptions.BeforeBreadcrumbCallback>
beforeBreadcrumbCallback,
final @NotNull ObjectProvider<SentryOptions.TracesSamplerCallback> tracesSamplerCallback,
Expand All @@ -81,6 +82,7 @@ static class HubConfiguration {
final @NotNull InAppIncludesResolver inAppPackagesResolver) {
return options -> {
beforeSendCallback.ifAvailable(options::setBeforeSend);
beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction);
beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb);
tracesSamplerCallback.ifAvailable(options::setTracesSampler);
eventProcessors.forEach(options::addEventProcessor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import io.sentry.SentryEvent
import io.sentry.SentryLevel
import io.sentry.SentryOptions
import io.sentry.checkEvent
import io.sentry.protocol.SentryTransaction
import io.sentry.protocol.User
import io.sentry.spring.jakarta.ContextTagsEventProcessor
import io.sentry.spring.jakarta.HttpServletRequestSentryUserProvider
Expand Down Expand Up @@ -275,6 +276,15 @@ class SentryAutoConfigurationTest {
}
}

@Test
fun `registers beforeSendTransactionCallback on SentryOptions`() {
contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj")
.withUserConfiguration(CustomBeforeSendTransactionCallbackConfiguration::class.java)
.run {
assertThat(it.getBean(SentryOptions::class.java).beforeSendTransaction).isInstanceOf(CustomBeforeSendTransactionCallback::class.java)
}
}

@Test
fun `registers beforeBreadcrumbCallback on SentryOptions`() {
contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj")
Expand Down Expand Up @@ -720,6 +730,17 @@ class SentryAutoConfigurationTest {
override fun execute(event: SentryEvent, hint: Hint): SentryEvent? = null
}

@Configuration(proxyBeanMethods = false)
open class CustomBeforeSendTransactionCallbackConfiguration {

@Bean
open fun beforeSendTransactionCallback() = CustomBeforeSendTransactionCallback()
}

class CustomBeforeSendTransactionCallback : SentryOptions.BeforeSendTransactionCallback {
override fun execute(event: SentryTransaction, hint: Hint): SentryTransaction? = null
}

@Configuration(proxyBeanMethods = false)
open class CustomBeforeBreadcrumbCallbackConfiguration {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ static class HubConfiguration {
@Order(Ordered.HIGHEST_PRECEDENCE)
public @NotNull Sentry.OptionsConfiguration<SentryOptions> sentryOptionsConfiguration(
final @NotNull ObjectProvider<SentryOptions.BeforeSendCallback> beforeSendCallback,
final @NotNull ObjectProvider<SentryOptions.BeforeSendTransactionCallback>
beforeSendTransactionCallback,
final @NotNull ObjectProvider<SentryOptions.BeforeBreadcrumbCallback>
beforeBreadcrumbCallback,
final @NotNull ObjectProvider<SentryOptions.TracesSamplerCallback> tracesSamplerCallback,
Expand All @@ -81,6 +83,7 @@ static class HubConfiguration {
final @NotNull InAppIncludesResolver inAppPackagesResolver) {
return options -> {
beforeSendCallback.ifAvailable(options::setBeforeSend);
beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction);
beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb);
tracesSamplerCallback.ifAvailable(options::setTracesSampler);
eventProcessors.forEach(options::addEventProcessor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import io.sentry.SentryEvent
import io.sentry.SentryLevel
import io.sentry.SentryOptions
import io.sentry.checkEvent
import io.sentry.protocol.SentryTransaction
import io.sentry.protocol.User
import io.sentry.spring.ContextTagsEventProcessor
import io.sentry.spring.HttpServletRequestSentryUserProvider
Expand Down Expand Up @@ -275,6 +276,15 @@ class SentryAutoConfigurationTest {
}
}

@Test
fun `registers beforeSendTransactionCallback on SentryOptions`() {
contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj")
.withUserConfiguration(CustomBeforeSendTransactionCallbackConfiguration::class.java)
.run {
assertThat(it.getBean(SentryOptions::class.java).beforeSendTransaction).isInstanceOf(CustomBeforeSendTransactionCallback::class.java)
}
}

@Test
fun `registers beforeBreadcrumbCallback on SentryOptions`() {
contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj")
Expand Down Expand Up @@ -720,6 +730,17 @@ class SentryAutoConfigurationTest {
override fun execute(event: SentryEvent, hint: Hint): SentryEvent? = null
}

@Configuration(proxyBeanMethods = false)
open class CustomBeforeSendTransactionCallbackConfiguration {

@Bean
open fun beforeSendTransactionCallback() = CustomBeforeSendTransactionCallback()
}

class CustomBeforeSendTransactionCallback : SentryOptions.BeforeSendTransactionCallback {
override fun execute(event: SentryTransaction, hint: Hint): SentryTransaction? = null
}

@Configuration(proxyBeanMethods = false)
open class CustomBeforeBreadcrumbCallbackConfiguration {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public SentryInitBeanPostProcessor() {
applicationContext
.getBeanProvider(SentryOptions.BeforeSendCallback.class)
.ifAvailable(options::setBeforeSend);
applicationContext
.getBeanProvider(SentryOptions.BeforeSendTransactionCallback.class)
.ifAvailable(options::setBeforeSendTransaction);
applicationContext
.getBeanProvider(SentryOptions.BeforeBreadcrumbCallback.class)
.ifAvailable(options::setBeforeBreadcrumb);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public SentryInitBeanPostProcessor() {
applicationContext
.getBeanProvider(SentryOptions.BeforeSendCallback.class)
.ifAvailable(options::setBeforeSend);
applicationContext
.getBeanProvider(SentryOptions.BeforeSendTransactionCallback.class)
.ifAvailable(options::setBeforeSendTransaction);
applicationContext
.getBeanProvider(SentryOptions.BeforeBreadcrumbCallback.class)
.ifAvailable(options::setBeforeBreadcrumb);
Expand Down
6 changes: 6 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ public class io/sentry/SentryOptions {
public fun addTracingOrigin (Ljava/lang/String;)V
public fun getBeforeBreadcrumb ()Lio/sentry/SentryOptions$BeforeBreadcrumbCallback;
public fun getBeforeSend ()Lio/sentry/SentryOptions$BeforeSendCallback;
public fun getBeforeSendTransaction ()Lio/sentry/SentryOptions$BeforeSendTransactionCallback;
public fun getCacheDirPath ()Ljava/lang/String;
public fun getClientReportRecorder ()Lio/sentry/clientreport/IClientReportRecorder;
public fun getConnectionTimeoutMillis ()I
Expand Down Expand Up @@ -1432,6 +1433,7 @@ public class io/sentry/SentryOptions {
public fun setAttachThreads (Z)V
public fun setBeforeBreadcrumb (Lio/sentry/SentryOptions$BeforeBreadcrumbCallback;)V
public fun setBeforeSend (Lio/sentry/SentryOptions$BeforeSendCallback;)V
public fun setBeforeSendTransaction (Lio/sentry/SentryOptions$BeforeSendTransactionCallback;)V
public fun setCacheDirPath (Ljava/lang/String;)V
public fun setConnectionTimeoutMillis (I)V
public fun setDebug (Z)V
Expand Down Expand Up @@ -1501,6 +1503,10 @@ public abstract interface class io/sentry/SentryOptions$BeforeSendCallback {
public abstract fun execute (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
}

public abstract interface class io/sentry/SentryOptions$BeforeSendTransactionCallback {
public abstract fun execute (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction;
}

public abstract interface class io/sentry/SentryOptions$ProfilesSamplerCallback {
public abstract fun sample (Lio/sentry/SamplingContext;)Ljava/lang/Double;
}
Expand Down
41 changes: 41 additions & 0 deletions sentry/src/main/java/io/sentry/SentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,18 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint
return SentryId.EMPTY_ID;
}

transaction = executeBeforeSendTransaction(transaction, hint);

if (transaction == null) {
options
.getLogger()
.log(SentryLevel.DEBUG, "Transaction was dropped by beforeSendTransaction.");
options
.getClientReportRecorder()
.recordLostEvent(DiscardReason.BEFORE_SEND, DataCategory.Transaction);
return SentryId.EMPTY_ID;
}

try {
final SentryEnvelope envelope =
buildEnvelope(
Expand Down Expand Up @@ -711,6 +723,35 @@ private void sortBreadcrumbsByDate(
return event;
}

private @Nullable SentryTransaction executeBeforeSendTransaction(
@NotNull SentryTransaction transaction, final @NotNull Hint hint) {
final SentryOptions.BeforeSendTransactionCallback beforeSendTransaction =
options.getBeforeSendTransaction();
if (beforeSendTransaction != null) {
try {
transaction = beforeSendTransaction.execute(transaction, hint);
} catch (Throwable e) {
options
.getLogger()
.log(
SentryLevel.ERROR,
"The BeforeSendTransaction callback threw an exception. It will be added as breadcrumb and continue.",
e);

final Breadcrumb breadcrumb = new Breadcrumb();
breadcrumb.setMessage("BeforeSendTransaction callback failed.");
breadcrumb.setCategory("SentryClient");
breadcrumb.setLevel(SentryLevel.ERROR);
if (e.getMessage() != null) {
breadcrumb.setData("sentry:message", e.getMessage());
}

transaction.addBreadcrumb(breadcrumb);
}
}
return transaction;
}

@Override
public void close() {
options.getLogger().log(SentryLevel.INFO, "Closing SentryClient.");
Expand Down
41 changes: 41 additions & 0 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.sentry.internal.modules.IModulesLoader;
import io.sentry.internal.modules.NoOpModulesLoader;
import io.sentry.protocol.SdkVersion;
import io.sentry.protocol.SentryTransaction;
import io.sentry.transport.ITransport;
import io.sentry.transport.ITransportGate;
import io.sentry.transport.NoOpEnvelopeCache;
Expand Down Expand Up @@ -115,6 +116,12 @@ public class SentryOptions {
*/
private @Nullable BeforeSendCallback beforeSend;

/**
* This function is called with an SDK specific transaction object and can return a modified
* transaction object or nothing to skip reporting the transaction
*/
private @Nullable BeforeSendTransactionCallback beforeSendTransaction;

/**
* This function is called with an SDK specific breadcrumb object before the breadcrumb is added
* to the scope. When nothing is returned from the function, the breadcrumb is dropped
Expand Down Expand Up @@ -612,6 +619,25 @@ public void setBeforeSend(@Nullable BeforeSendCallback beforeSend) {
this.beforeSend = beforeSend;
}

/**
* Returns the BeforeSendTransaction callback
*
* @return the beforeSendTransaction callback or null if not set
*/
public @Nullable BeforeSendTransactionCallback getBeforeSendTransaction() {
return beforeSendTransaction;
}

/**
* Sets the beforeSendTransaction callback
*
* @param beforeSendTransaction the beforeSendTransaction callback
*/
public void setBeforeSendTransaction(
@Nullable BeforeSendTransactionCallback beforeSendTransaction) {
this.beforeSendTransaction = beforeSendTransaction;
}

/**
* Returns the beforeBreadcrumb callback
*
Expand Down Expand Up @@ -1780,6 +1806,21 @@ public interface BeforeSendCallback {
SentryEvent execute(@NotNull SentryEvent event, @NotNull Hint hint);
}

/** The BeforeSendTransaction callback */
public interface BeforeSendTransactionCallback {

/**
* Mutates or drop a transaction before being sent
*
* @param transaction the transaction
* @param hint the hints
* @return the original transaction or the mutated transaction or null if transaction was
* dropped
*/
@Nullable
SentryTransaction execute(@NotNull SentryTransaction transaction, @NotNull Hint hint);
}

/** The BeforeBreadcrumb callback */
public interface BeforeBreadcrumbCallback {

Expand Down
Loading

0 comments on commit 92bac29

Please sign in to comment.