Skip to content

Commit 592d21b

Browse files
Add configurable auto transaction deadline timeout with manifest support
Co-authored-by: stefano.siano <stefano.siano@sentry.io>
1 parent 14ea3ae commit 592d21b

File tree

9 files changed

+93
-38
lines changed

9 files changed

+93
-38
lines changed

IMPLEMENTATION_SUMMARY.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ Added a new configuration option `autoTransactionDeadlineTimeoutMillis` to `Sent
1111
#### 1. Added New Option to SentryAndroidOptions
1212
**File**: `/workspace/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroidOptions.java`
1313

14-
- Added field `autoTransactionDeadlineTimeoutMillis` with default value `0`
14+
- Added field `autoTransactionDeadlineTimeoutMillis` with default value `30000`
1515
- Added getter `getAutoTransactionDeadlineTimeoutMillis()`
1616
- Added setter `setAutoTransactionDeadlineTimeoutMillis(long autoTransactionDeadlineTimeoutMillis)`
1717

1818
**Behavior**:
19-
- `0` (default): Use the existing 30-second default timeout
19+
- `30000` (default): 30-second timeout (same as previous behavior)
2020
- Positive value: Use the specified timeout in milliseconds
21-
- Negative value: No deadline (transactions only finish when explicitly finished or activity lifecycle ends)
21+
- Zero or negative value: No deadline (transactions only finish when explicitly finished or activity lifecycle ends)
2222

2323
#### 2. Updated ActivityLifecycleIntegration
2424
**File**: `/workspace/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java`
@@ -35,36 +35,51 @@ Applied the same deadline timeout configuration logic for user interaction trans
3535

3636
Modified to use the new configuration option with appropriate type checking since navigation listener works with base `SentryOptions`.
3737

38-
#### 5. Added Tests
38+
#### 5. Added Manifest Support
39+
**File**: `/workspace/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java`
40+
41+
Added support for configuring the option via AndroidManifest.xml using the key `io.sentry.traces.auto-transaction-deadline-timeout-millis`.
42+
43+
#### 6. Added Tests
3944
**Files**:
4045
- `/workspace/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt`
4146
- `/workspace/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt`
47+
- `/workspace/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt`
4248

4349
Added comprehensive tests to verify:
44-
- Option defaults to 0
50+
- Option defaults to 30000
4551
- Option can be set to positive, negative, and zero values
4652
- ActivityLifecycleIntegration respects the new option
4753
- All three timeout behaviors work correctly (default, custom, disabled)
54+
- Manifest reading works correctly
4855

4956
### Usage Example
5057

5158
```kotlin
52-
// Disable deadline timeout (transactions only finish manually or on activity lifecycle)
59+
// Disable deadline timeout (solve the original issue - transactions only finish manually or on activity lifecycle)
5360
SentryAndroid.init(this) { options ->
54-
options.autoTransactionDeadlineTimeoutMillis = -1
61+
options.autoTransactionDeadlineTimeoutMillis = 0 // or any negative value
5562
}
5663

5764
// Set custom 60-second timeout
5865
SentryAndroid.init(this) { options ->
5966
options.autoTransactionDeadlineTimeoutMillis = 60000
6067
}
6168

62-
// Use default 30-second timeout (default behavior)
69+
// Use default 30-second timeout (default behavior - no configuration needed)
6370
SentryAndroid.init(this) { options ->
64-
options.autoTransactionDeadlineTimeoutMillis = 0 // or just don't set it
71+
// autoTransactionDeadlineTimeoutMillis defaults to 30000
6572
}
6673
```
6774

75+
**Via AndroidManifest.xml:**
76+
77+
```xml
78+
<application>
79+
<meta-data android:name="io.sentry.traces.auto-transaction-deadline-timeout-millis" android:value="0" />
80+
</application>
81+
```
82+
6883
### Backward Compatibility
6984
This change is fully backward compatible. Existing code will continue to work with the default 30-second timeout behavior. Only users who explicitly set the new option will experience different behavior.
7085

sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,9 @@ private void startTracing(final @NotNull Activity activity) {
192192

193193
// Set deadline timeout based on configured option
194194
final long deadlineTimeoutMillis = options.getAutoTransactionDeadlineTimeoutMillis();
195-
if (deadlineTimeoutMillis < 0) {
196-
// No deadline when negative value is set
195+
if (deadlineTimeoutMillis <= 0) {
196+
// No deadline when zero or negative value is set
197197
transactionOptions.setDeadlineTimeout(null);
198-
} else if (deadlineTimeoutMillis == 0) {
199-
// Use default timeout when 0 is set
200-
transactionOptions.setDeadlineTimeout(
201-
TransactionOptions.DEFAULT_DEADLINE_TIMEOUT_AUTO_TRANSACTION);
202198
} else {
203199
// Use configured timeout when positive value is set
204200
transactionOptions.setDeadlineTimeout(deadlineTimeoutMillis);

sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ final class ManifestMetadataReader {
127127
static final String ENABLE_AUTO_TRACE_ID_GENERATION =
128128
"io.sentry.traces.enable-auto-id-generation";
129129

130+
static final String AUTO_TRANSACTION_DEADLINE_TIMEOUT_MILLIS =
131+
"io.sentry.traces.auto-transaction-deadline-timeout-millis";
132+
130133
static final String FEEDBACK_NAME_REQUIRED = "io.sentry.feedback.is-name-required";
131134

132135
static final String FEEDBACK_SHOW_NAME = "io.sentry.feedback.show-name";
@@ -446,6 +449,13 @@ static void applyMetadata(
446449
ENABLE_AUTO_TRACE_ID_GENERATION,
447450
options.isEnableAutoTraceIdGeneration()));
448451

452+
options.setAutoTransactionDeadlineTimeoutMillis(
453+
readLong(
454+
metadata,
455+
logger,
456+
AUTO_TRANSACTION_DEADLINE_TIMEOUT_MILLIS,
457+
options.getAutoTransactionDeadlineTimeoutMillis()));
458+
449459
if (options.getSessionReplay().getSessionSampleRate() == null) {
450460
final double sessionSampleRate =
451461
readDouble(metadata, logger, REPLAYS_SESSION_SAMPLE_RATE);

sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroidOptions.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,14 @@ public final class SentryAndroidOptions extends SentryOptions {
174174
private boolean enableAutoTraceIdGeneration = true;
175175

176176
/**
177-
* Controls the deadline timeout in milliseconds for automatic transactions. When set to 0,
178-
* the default timeout of 30 seconds is used. When set to a value greater than 0, that value
179-
* is used as the deadline timeout. When set to a value less than 0, no deadline is applied
180-
* and transactions will only finish when explicitly finished or when the activity lifecycle ends.
177+
* Controls the deadline timeout in milliseconds for automatic transactions. When set to a
178+
* positive value, that value is used as the deadline timeout. When set to a value less than
179+
* or equal to 0, no deadline is applied and transactions will only finish when explicitly
180+
* finished or when the activity lifecycle ends.
181181
*
182-
* <p>Default is 0 (use default 30 second timeout).
182+
* <p>Default is 30000 (30 seconds).
183183
*/
184-
private long autoTransactionDeadlineTimeoutMillis = 0;
184+
private long autoTransactionDeadlineTimeoutMillis = 30000;
185185

186186
public interface BeforeCaptureCallback {
187187

sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,9 @@ private void startTracing(final @NotNull UiElement target, final @NotNull Gestur
252252

253253
// Set deadline timeout based on configured option
254254
final long deadlineTimeoutMillis = options.getAutoTransactionDeadlineTimeoutMillis();
255-
if (deadlineTimeoutMillis < 0) {
256-
// No deadline when negative value is set
255+
if (deadlineTimeoutMillis <= 0) {
256+
// No deadline when zero or negative value is set
257257
transactionOptions.setDeadlineTimeout(null);
258-
} else if (deadlineTimeoutMillis == 0) {
259-
// Use default timeout when 0 is set
260-
transactionOptions.setDeadlineTimeout(
261-
TransactionOptions.DEFAULT_DEADLINE_TIMEOUT_AUTO_TRANSACTION);
262258
} else {
263259
// Use configured timeout when positive value is set
264260
transactionOptions.setDeadlineTimeout(deadlineTimeoutMillis);

sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,27 @@ class ActivityLifecycleIntegrationTest {
246246
)
247247
}
248248

249+
@Test
250+
fun `Activity transaction uses no deadline timeout when autoTransactionDeadlineTimeoutMillis is set to zero`() {
251+
val sut = fixture.getSut()
252+
fixture.options.tracesSampleRate = 1.0
253+
fixture.options.autoTransactionDeadlineTimeoutMillis = 0L // No deadline
254+
sut.register(fixture.scopes, fixture.options)
255+
256+
setAppStartTime()
257+
258+
val activity = mock<Activity>()
259+
sut.onActivityCreated(activity, fixture.bundle)
260+
261+
verify(fixture.scopes)
262+
.startTransaction(
263+
any<TransactionContext>(),
264+
check<TransactionOptions> { transactionOptions ->
265+
assertNull(transactionOptions.deadlineTimeout)
266+
},
267+
)
268+
}
269+
249270
@Test
250271
fun `Activity transaction uses no deadline timeout when autoTransactionDeadlineTimeoutMillis is set to negative value`() {
251272
val sut = fixture.getSut()
@@ -268,10 +289,10 @@ class ActivityLifecycleIntegrationTest {
268289
}
269290

270291
@Test
271-
fun `Activity transaction uses default deadline timeout when autoTransactionDeadlineTimeoutMillis is set to 0`() {
292+
fun `Activity transaction uses default deadline timeout when autoTransactionDeadlineTimeoutMillis is default`() {
272293
val sut = fixture.getSut()
273294
fixture.options.tracesSampleRate = 1.0
274-
fixture.options.autoTransactionDeadlineTimeoutMillis = 0L // Use default
295+
// Don't set autoTransactionDeadlineTimeoutMillis, use default (30000)
275296
sut.register(fixture.scopes, fixture.options)
276297

277298
setAppStartTime()
@@ -283,10 +304,7 @@ class ActivityLifecycleIntegrationTest {
283304
.startTransaction(
284305
any<TransactionContext>(),
285306
check<TransactionOptions> { transactionOptions ->
286-
assertEquals(
287-
TransactionOptions.DEFAULT_DEADLINE_TIMEOUT_AUTO_TRANSACTION,
288-
transactionOptions.deadlineTimeout,
289-
)
307+
assertEquals(30000L, transactionOptions.deadlineTimeout)
290308
},
291309
)
292310
}

sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,20 @@ class ManifestMetadataReaderTest {
10911091
assertEquals(expectedIdleTimeout.toLong(), fixture.options.idleTimeout)
10921092
}
10931093

1094+
@Test
1095+
fun `applyMetadata reads autoTransactionDeadlineTimeoutMillis from metadata`() {
1096+
// Arrange
1097+
val expectedTimeout = 60000
1098+
val bundle = bundleOf(ManifestMetadataReader.AUTO_TRANSACTION_DEADLINE_TIMEOUT_MILLIS to expectedTimeout)
1099+
val context = fixture.getContext(metaData = bundle)
1100+
1101+
// Act
1102+
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)
1103+
1104+
// Assert
1105+
assertEquals(expectedTimeout.toLong(), fixture.options.autoTransactionDeadlineTimeoutMillis)
1106+
}
1107+
10941108
@Test
10951109
fun `applyMetadata without specifying idleTimeout, stays default`() {
10961110
// Arrange

sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,9 @@ class SentryAndroidOptionsTest {
182182
}
183183

184184
@Test
185-
fun `autoTransactionDeadlineTimeoutMillis option defaults to 0`() {
185+
fun `autoTransactionDeadlineTimeoutMillis option defaults to 30000`() {
186186
val sentryOptions = SentryAndroidOptions()
187-
assertEquals(0L, sentryOptions.autoTransactionDeadlineTimeoutMillis)
187+
assertEquals(30000L, sentryOptions.autoTransactionDeadlineTimeoutMillis)
188188
}
189189

190190
@Test
@@ -194,6 +194,13 @@ class SentryAndroidOptionsTest {
194194
assertEquals(60000L, sentryOptions.autoTransactionDeadlineTimeoutMillis)
195195
}
196196

197+
@Test
198+
fun `autoTransactionDeadlineTimeoutMillis option can be set to zero value`() {
199+
val sentryOptions = SentryAndroidOptions()
200+
sentryOptions.autoTransactionDeadlineTimeoutMillis = 0L
201+
assertEquals(0L, sentryOptions.autoTransactionDeadlineTimeoutMillis)
202+
}
203+
197204
@Test
198205
fun `autoTransactionDeadlineTimeoutMillis option can be set to negative value`() {
199206
val sentryOptions = SentryAndroidOptions()

sentry-android-navigation/src/main/java/io/sentry/android/navigation/SentryNavigationListener.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,10 @@ constructor(
138138
} else {
139139
null
140140
}
141-
val deadlineTimeoutMillis = androidOptions?.autoTransactionDeadlineTimeoutMillis ?: 0L
141+
val deadlineTimeoutMillis = androidOptions?.autoTransactionDeadlineTimeoutMillis ?: TransactionOptions.DEFAULT_DEADLINE_TIMEOUT_AUTO_TRANSACTION
142142

143143
it.deadlineTimeout = when {
144-
deadlineTimeoutMillis < 0 -> null // No deadline when negative value is set
145-
deadlineTimeoutMillis == 0L -> TransactionOptions.DEFAULT_DEADLINE_TIMEOUT_AUTO_TRANSACTION // Use default timeout when 0 is set
144+
deadlineTimeoutMillis <= 0 -> null // No deadline when zero or negative value is set
146145
else -> deadlineTimeoutMillis // Use configured timeout when positive value is set
147146
}
148147

0 commit comments

Comments
 (0)