Skip to content

Commit 26abccf

Browse files
committed
make span creation for db transactions opt-in
1 parent dc92478 commit 26abccf

10 files changed

Lines changed: 154 additions & 18 deletions

File tree

sentry-jdbc/src/main/java/io/sentry/jdbc/SentryJdbcEventListener.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public void onBeforeSetAutoCommit(
6969
final @NotNull ConnectionInformation connectionInformation,
7070
boolean newAutoCommit,
7171
boolean currentAutoCommit) {
72+
if (!isDatabaseTransactionTracingEnabled()) {
73+
return;
74+
}
7275
final boolean isSwitchingToManualCommit = !newAutoCommit && currentAutoCommit;
7376
if (isSwitchingToManualCommit) {
7477
startSpan(CURRENT_TRANSACTION_SPAN, "db.sql.transaction.begin", "BEGIN");
@@ -81,6 +84,9 @@ public void onAfterSetAutoCommit(
8184
final boolean newAutoCommit,
8285
final boolean oldAutoCommit,
8386
final @Nullable SQLException e) {
87+
if (!isDatabaseTransactionTracingEnabled()) {
88+
return;
89+
}
8490
final boolean isSwitchingToManualCommit = !newAutoCommit && oldAutoCommit;
8591
if (isSwitchingToManualCommit) {
8692
finishSpan(CURRENT_TRANSACTION_SPAN, connectionInformation, e);
@@ -89,6 +95,9 @@ public void onAfterSetAutoCommit(
8995

9096
@Override
9197
public void onBeforeCommit(final @NotNull ConnectionInformation connectionInformation) {
98+
if (!isDatabaseTransactionTracingEnabled()) {
99+
return;
100+
}
92101
startSpan(CURRENT_TRANSACTION_SPAN, "db.sql.transaction.commit", "COMMIT");
93102
}
94103

@@ -97,11 +106,17 @@ public void onAfterCommit(
97106
final @NotNull ConnectionInformation connectionInformation,
98107
final long timeElapsedNanos,
99108
final @Nullable SQLException e) {
109+
if (!isDatabaseTransactionTracingEnabled()) {
110+
return;
111+
}
100112
finishSpan(CURRENT_TRANSACTION_SPAN, connectionInformation, e);
101113
}
102114

103115
@Override
104116
public void onBeforeRollback(final @NotNull ConnectionInformation connectionInformation) {
117+
if (!isDatabaseTransactionTracingEnabled()) {
118+
return;
119+
}
105120
startSpan(CURRENT_TRANSACTION_SPAN, "db.sql.transaction.rollback", "ROLLBACK");
106121
}
107122

@@ -110,9 +125,16 @@ public void onAfterRollback(
110125
final @NotNull ConnectionInformation connectionInformation,
111126
final long timeElapsedNanos,
112127
final @Nullable SQLException e) {
128+
if (!isDatabaseTransactionTracingEnabled()) {
129+
return;
130+
}
113131
finishSpan(CURRENT_TRANSACTION_SPAN, connectionInformation, e);
114132
}
115133

134+
private boolean isDatabaseTransactionTracingEnabled() {
135+
return scopes.getOptions().isEnableDatabaseTransactionTracing();
136+
}
137+
116138
private void startSpan(
117139
final @NotNull ThreadLocal<ISpan> spanHolder,
118140
final @NotNull String operation,

sentry-jdbc/src/test/kotlin/io/sentry/jdbc/SentryJdbcEventListenerTest.kt

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,22 @@ import org.mockito.kotlin.whenever
2525

2626
class SentryJdbcEventListenerTest {
2727
class Fixture {
28+
lateinit var options: SentryOptions
2829
val scopes =
29-
mock<IScopes>().apply {
30-
whenever(options)
31-
.thenReturn(SentryOptions().apply { sdkVersion = SdkVersion("test", "1.2.3") })
32-
}
30+
mock<IScopes>().apply { whenever(this.options).thenAnswer { this@Fixture.options } }
3331
lateinit var tx: SentryTracer
3432
val actualDataSource = JDBCDataSource()
3533

36-
fun getSut(withRunningTransaction: Boolean = true, existingRow: Int? = null): DataSource {
34+
fun getSut(
35+
withRunningTransaction: Boolean = true,
36+
existingRow: Int? = null,
37+
enableDatabaseTransactionTracing: Boolean = false,
38+
): DataSource {
39+
options =
40+
SentryOptions().apply {
41+
sdkVersion = SdkVersion("test", "1.2.3")
42+
isEnableDatabaseTransactionTracing = enableDatabaseTransactionTracing
43+
}
3744
tx = SentryTracer(TransactionContext("name", "op"), scopes)
3845
if (withRunningTransaction) {
3946
whenever(scopes.span).thenReturn(tx)
@@ -171,8 +178,8 @@ class SentryJdbcEventListenerTest {
171178
}
172179

173180
@Test
174-
fun `creates span for commit`() {
175-
val sut = fixture.getSut()
181+
fun `creates span for commit when database transaction tracing is enabled`() {
182+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
176183

177184
sut.connection.use {
178185
it.autoCommit = false
@@ -187,8 +194,8 @@ class SentryJdbcEventListenerTest {
187194
}
188195

189196
@Test
190-
fun `creates span for rollback`() {
191-
val sut = fixture.getSut()
197+
fun `creates span for rollback when database transaction tracing is enabled`() {
198+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
192199

193200
sut.connection.use {
194201
it.autoCommit = false
@@ -204,7 +211,7 @@ class SentryJdbcEventListenerTest {
204211

205212
@Test
206213
fun `commit span has database details`() {
207-
val sut = fixture.getSut()
214+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
208215

209216
sut.connection.use {
210217
it.autoCommit = false
@@ -220,7 +227,7 @@ class SentryJdbcEventListenerTest {
220227

221228
@Test
222229
fun `rollback span has database details`() {
223-
val sut = fixture.getSut()
230+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
224231

225232
sut.connection.use {
226233
it.autoCommit = false
@@ -236,7 +243,8 @@ class SentryJdbcEventListenerTest {
236243

237244
@Test
238245
fun `does not create commit span when there is no running transaction`() {
239-
val sut = fixture.getSut(withRunningTransaction = false)
246+
val sut =
247+
fixture.getSut(withRunningTransaction = false, enableDatabaseTransactionTracing = true)
240248

241249
sut.connection.use {
242250
it.autoCommit = false
@@ -250,7 +258,8 @@ class SentryJdbcEventListenerTest {
250258

251259
@Test
252260
fun `does not create rollback span when there is no running transaction`() {
253-
val sut = fixture.getSut(withRunningTransaction = false)
261+
val sut =
262+
fixture.getSut(withRunningTransaction = false, enableDatabaseTransactionTracing = true)
254263

255264
sut.connection.use {
256265
it.autoCommit = false
@@ -263,8 +272,8 @@ class SentryJdbcEventListenerTest {
263272
}
264273

265274
@Test
266-
fun `creates span for transaction begin when setAutoCommit false`() {
267-
val sut = fixture.getSut()
275+
fun `creates span for transaction begin when setAutoCommit false and database transaction tracing is enabled`() {
276+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
268277

269278
sut.connection.use {
270279
it.autoCommit = false
@@ -280,7 +289,7 @@ class SentryJdbcEventListenerTest {
280289

281290
@Test
282291
fun `transaction begin span has database details`() {
283-
val sut = fixture.getSut()
292+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
284293

285294
sut.connection.use {
286295
it.autoCommit = false
@@ -296,7 +305,7 @@ class SentryJdbcEventListenerTest {
296305

297306
@Test
298307
fun `does not create begin span when already in manual commit mode`() {
299-
val sut = fixture.getSut()
308+
val sut = fixture.getSut(enableDatabaseTransactionTracing = true)
300309

301310
sut.connection.use {
302311
it.autoCommit = false
@@ -311,7 +320,22 @@ class SentryJdbcEventListenerTest {
311320

312321
@Test
313322
fun `does not create begin span when there is no running transaction`() {
314-
val sut = fixture.getSut(withRunningTransaction = false)
323+
val sut =
324+
fixture.getSut(withRunningTransaction = false, enableDatabaseTransactionTracing = true)
325+
326+
sut.connection.use {
327+
it.autoCommit = false
328+
it.prepareStatement("INSERT INTO foo VALUES (1)").executeUpdate()
329+
it.commit()
330+
}
331+
332+
val beginSpans = fixture.tx.children.filter { it.operation == "db.sql.transaction.begin" }
333+
assertTrue(beginSpans.isEmpty())
334+
}
335+
336+
@Test
337+
fun `does not create transaction spans when database transaction tracing is disabled`() {
338+
val sut = fixture.getSut(enableDatabaseTransactionTracing = false)
315339

316340
sut.connection.use {
317341
it.autoCommit = false
@@ -320,6 +344,28 @@ class SentryJdbcEventListenerTest {
320344
}
321345

322346
val beginSpans = fixture.tx.children.filter { it.operation == "db.sql.transaction.begin" }
347+
val commitSpans = fixture.tx.children.filter { it.operation == "db.sql.transaction.commit" }
323348
assertTrue(beginSpans.isEmpty())
349+
assertTrue(commitSpans.isEmpty())
350+
// Query spans should still be created
351+
val querySpans = fixture.tx.children.filter { it.operation == "db.query" }
352+
assertEquals(1, querySpans.size)
353+
}
354+
355+
@Test
356+
fun `does not create rollback span when database transaction tracing is disabled`() {
357+
val sut = fixture.getSut(enableDatabaseTransactionTracing = false)
358+
359+
sut.connection.use {
360+
it.autoCommit = false
361+
it.prepareStatement("INSERT INTO foo VALUES (1)").executeUpdate()
362+
it.rollback()
363+
}
364+
365+
val rollbackSpans = fixture.tx.children.filter { it.operation == "db.sql.transaction.rollback" }
366+
assertTrue(rollbackSpans.isEmpty())
367+
// Query spans should still be created
368+
val querySpans = fixture.tx.children.filter { it.operation == "db.query" }
369+
assertEquals(1, querySpans.size)
324370
}
325371
}

sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ class SentryAutoConfigurationTest {
198198
"sentry.ignored-errors=Some error,Another .*",
199199
"sentry.ignored-transactions=transactionName1,transactionNameB",
200200
"sentry.enable-backpressure-handling=false",
201+
"sentry.enable-database-transaction-tracing=true",
201202
"sentry.enable-spotlight=true",
202203
"sentry.spotlight-connection-url=http://local.sentry.io:1234",
203204
"sentry.force-init=true",
@@ -250,6 +251,7 @@ class SentryAutoConfigurationTest {
250251
assertThat(options.ignoredTransactions)
251252
.containsOnly(FilterString("transactionName1"), FilterString("transactionNameB"))
252253
assertThat(options.isEnableBackpressureHandling).isEqualTo(false)
254+
assertThat(options.isEnableDatabaseTransactionTracing).isEqualTo(true)
253255
assertThat(options.isForceInit).isEqualTo(true)
254256
assertThat(options.isGlobalHubMode).isEqualTo(true)
255257
assertThat(options.isCaptureOpenTelemetryEvents).isEqualTo(true)

sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ class SentryAutoConfigurationTest {
202202
"sentry.ignored-errors=Some error,Another .*",
203203
"sentry.ignored-transactions=transactionName1,transactionNameB",
204204
"sentry.enable-backpressure-handling=false",
205+
"sentry.enable-database-transaction-tracing=true",
205206
"sentry.enable-spotlight=true",
206207
"sentry.spotlight-connection-url=http://local.sentry.io:1234",
207208
"sentry.force-init=true",
@@ -257,6 +258,7 @@ class SentryAutoConfigurationTest {
257258
assertThat(options.ignoredTransactions)
258259
.containsOnly(FilterString("transactionName1"), FilterString("transactionNameB"))
259260
assertThat(options.isEnableBackpressureHandling).isEqualTo(false)
261+
assertThat(options.isEnableDatabaseTransactionTracing).isEqualTo(true)
260262
assertThat(options.isForceInit).isEqualTo(true)
261263
assertThat(options.isGlobalHubMode).isEqualTo(true)
262264
assertThat(options.isCaptureOpenTelemetryEvents).isEqualTo(true)

sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ class SentryAutoConfigurationTest {
201201
"sentry.ignored-errors=Some error,Another .*",
202202
"sentry.ignored-transactions=transactionName1,transactionNameB",
203203
"sentry.enable-backpressure-handling=false",
204+
"sentry.enable-database-transaction-tracing=true",
204205
"sentry.enable-spotlight=true",
205206
"sentry.spotlight-connection-url=http://local.sentry.io:1234",
206207
"sentry.force-init=true",
@@ -256,6 +257,7 @@ class SentryAutoConfigurationTest {
256257
assertThat(options.ignoredTransactions)
257258
.containsOnly(FilterString("transactionName1"), FilterString("transactionNameB"))
258259
assertThat(options.isEnableBackpressureHandling).isEqualTo(false)
260+
assertThat(options.isEnableDatabaseTransactionTracing).isEqualTo(true)
259261
assertThat(options.isForceInit).isEqualTo(true)
260262
assertThat(options.isGlobalHubMode).isEqualTo(true)
261263
assertThat(options.isCaptureOpenTelemetryEvents).isEqualTo(true)

sentry/api/sentry.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ public final class io/sentry/ExternalOptions {
512512
public fun getTracesSampleRate ()Ljava/lang/Double;
513513
public fun isCaptureOpenTelemetryEvents ()Ljava/lang/Boolean;
514514
public fun isEnableBackpressureHandling ()Ljava/lang/Boolean;
515+
public fun isEnableDatabaseTransactionTracing ()Ljava/lang/Boolean;
515516
public fun isEnableLogs ()Ljava/lang/Boolean;
516517
public fun isEnableMetrics ()Ljava/lang/Boolean;
517518
public fun isEnablePrettySerializationOutput ()Ljava/lang/Boolean;
@@ -527,6 +528,7 @@ public final class io/sentry/ExternalOptions {
527528
public fun setDist (Ljava/lang/String;)V
528529
public fun setDsn (Ljava/lang/String;)V
529530
public fun setEnableBackpressureHandling (Ljava/lang/Boolean;)V
531+
public fun setEnableDatabaseTransactionTracing (Ljava/lang/Boolean;)V
530532
public fun setEnableDeduplication (Ljava/lang/Boolean;)V
531533
public fun setEnableLogs (Ljava/lang/Boolean;)V
532534
public fun setEnableMetrics (Ljava/lang/Boolean;)V
@@ -3553,6 +3555,7 @@ public class io/sentry/SentryOptions {
35533555
public fun isEnableAppStartProfiling ()Z
35543556
public fun isEnableAutoSessionTracking ()Z
35553557
public fun isEnableBackpressureHandling ()Z
3558+
public fun isEnableDatabaseTransactionTracing ()Z
35563559
public fun isEnableDeduplication ()Z
35573560
public fun isEnableEventSizeLimiting ()Z
35583561
public fun isEnableExternalConfiguration ()Z
@@ -3610,6 +3613,7 @@ public class io/sentry/SentryOptions {
36103613
public fun setEnableAppStartProfiling (Z)V
36113614
public fun setEnableAutoSessionTracking (Z)V
36123615
public fun setEnableBackpressureHandling (Z)V
3616+
public fun setEnableDatabaseTransactionTracing (Z)V
36133617
public fun setEnableDeduplication (Z)V
36143618
public fun setEnableEventSizeLimiting (Z)V
36153619
public fun setEnableExternalConfiguration (Z)V

sentry/src/main/java/io/sentry/ExternalOptions.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public final class ExternalOptions {
5353
private @Nullable Boolean sendModules;
5454
private @Nullable Boolean sendDefaultPii;
5555
private @Nullable Boolean enableBackpressureHandling;
56+
private @Nullable Boolean enableDatabaseTransactionTracing;
5657
private @Nullable Boolean globalHubMode;
5758
private @Nullable Boolean forceInit;
5859
private @Nullable Boolean captureOpenTelemetryEvents;
@@ -151,6 +152,9 @@ public final class ExternalOptions {
151152
options.setEnableBackpressureHandling(
152153
propertiesProvider.getBooleanProperty("enable-backpressure-handling"));
153154

155+
options.setEnableDatabaseTransactionTracing(
156+
propertiesProvider.getBooleanProperty("enable-database-transaction-tracing"));
157+
154158
options.setGlobalHubMode(propertiesProvider.getBooleanProperty("global-hub-mode"));
155159

156160
options.setCaptureOpenTelemetryEvents(
@@ -479,6 +483,15 @@ public void setEnableBackpressureHandling(final @Nullable Boolean enableBackpres
479483
return enableBackpressureHandling;
480484
}
481485

486+
public void setEnableDatabaseTransactionTracing(
487+
final @Nullable Boolean enableDatabaseTransactionTracing) {
488+
this.enableDatabaseTransactionTracing = enableDatabaseTransactionTracing;
489+
}
490+
491+
public @Nullable Boolean isEnableDatabaseTransactionTracing() {
492+
return enableDatabaseTransactionTracing;
493+
}
494+
482495
public void setGlobalHubMode(final @Nullable Boolean globalHubMode) {
483496
this.globalHubMode = globalHubMode;
484497
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ public class SentryOptions {
482482
/** Whether OPTIONS requests should be traced. */
483483
private boolean traceOptionsRequests = true;
484484

485+
/** Whether database transaction spans (BEGIN, COMMIT, ROLLBACK) should be traced. */
486+
private boolean enableDatabaseTransactionTracing = false;
487+
485488
/** Date provider to retrieve the current date from. */
486489
@ApiStatus.Internal
487490
private final @NotNull LazyEvaluator<SentryDateProvider> dateProvider =
@@ -2581,6 +2584,24 @@ public void setTraceOptionsRequests(boolean traceOptionsRequests) {
25812584
this.traceOptionsRequests = traceOptionsRequests;
25822585
}
25832586

2587+
/**
2588+
* Whether database transaction spans (BEGIN, COMMIT, ROLLBACK) should be traced.
2589+
*
2590+
* @return true if database transaction spans should be traced
2591+
*/
2592+
public boolean isEnableDatabaseTransactionTracing() {
2593+
return enableDatabaseTransactionTracing;
2594+
}
2595+
2596+
/**
2597+
* Whether database transaction spans (BEGIN, COMMIT, ROLLBACK) should be traced.
2598+
*
2599+
* @param enableDatabaseTransactionTracing true if database transaction spans should be traced
2600+
*/
2601+
public void setEnableDatabaseTransactionTracing(boolean enableDatabaseTransactionTracing) {
2602+
this.enableDatabaseTransactionTracing = enableDatabaseTransactionTracing;
2603+
}
2604+
25842605
/**
25852606
* Whether Sentry is enabled.
25862607
*
@@ -3432,6 +3453,9 @@ public void merge(final @NotNull ExternalOptions options) {
34323453
if (options.isEnableBackpressureHandling() != null) {
34333454
setEnableBackpressureHandling(options.isEnableBackpressureHandling());
34343455
}
3456+
if (options.isEnableDatabaseTransactionTracing() != null) {
3457+
setEnableDatabaseTransactionTracing(options.isEnableDatabaseTransactionTracing());
3458+
}
34353459
if (options.getMaxRequestBodySize() != null) {
34363460
setMaxRequestBodySize(options.getMaxRequestBodySize());
34373461
}

0 commit comments

Comments
 (0)