Skip to content

Commit 3a3c7ba

Browse files
YYChen01988lemnik
andauthored
Trim excess threads onSend (#2148)
* feat(payload): add a substitute thread to the payload when excess threads have been trimmed in EventPayload * test(payload): test `EventPayload` trimming * chore(changelog): added CHANGELOG entry for thread trimming in `EventPayload.trimToSize` --------- Co-authored-by: jason <[email protected]>
1 parent e29746e commit 3a3c7ba

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## TBD
4+
5+
### Bug fixes
6+
7+
* Excess threads (over `Configuration.getMaxReportedThreads`) are trimmed more reliably when the payload is modified before sending (in an `OnSendCallback` for example)
8+
[#2148](https://github.com/bugsnag/bugsnag-android/pull/2148)
9+
310
## 6.12.0 (2025-02-18)
411

512
### Enhancements

bugsnag-android-core/src/main/java/com/bugsnag/android/EventPayload.kt

+23
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,29 @@ class EventPayload @JvmOverloads internal constructor(
8080
dataTrimmed
8181
)
8282

83+
val threadCount = event.threads.size
84+
val maxReportedThreads = config.maxReportedThreads
85+
if (threadCount > maxReportedThreads) {
86+
event.threads.subList(maxReportedThreads, threadCount).clear()
87+
88+
event.threads.add(
89+
Thread(
90+
"",
91+
"[${threadCount - maxReportedThreads} threads omitted as the " +
92+
"maxReportedThreads limit ($maxReportedThreads) was exceeded]",
93+
ErrorType.UNKNOWN,
94+
false,
95+
Thread.State.UNKNOWN,
96+
Stacktrace(
97+
arrayOf(StackTraceElement("", "", "-", 0)),
98+
config.projectPackages,
99+
logger
100+
),
101+
logger
102+
)
103+
)
104+
}
105+
83106
json = rebuildPayloadCache()
84107
if (json.size <= maxSizeBytes) {
85108
return this
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.bugsnag.android
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Test
5+
import org.junit.runner.RunWith
6+
import org.mockito.Mock
7+
import org.mockito.junit.MockitoJUnitRunner
8+
9+
private const val MAX_STRING_LENGTH = 256
10+
private const val BIG_STRING_LENGTH = MAX_STRING_LENGTH * 4
11+
12+
@RunWith(MockitoJUnitRunner::class)
13+
class EventPayloadTrimTest {
14+
15+
@Mock
16+
lateinit var client: Client
17+
18+
@Test
19+
fun testTrimPayload() {
20+
val event = BugsnagTestUtils.generateEvent()
21+
event.addMetadata("trimming", "bigString", "*".repeat(BIG_STRING_LENGTH))
22+
23+
// remove any existing threads to keep this test simple
24+
event.threads.clear()
25+
repeat(times = 10) { threadIdx ->
26+
event.addThread(threadIdx.toLong(), "test thread $threadIdx")
27+
}
28+
29+
event.breadcrumbs.clear()
30+
repeat(times = 10) { breadcrumbIdx ->
31+
event.leaveBreadcrumb("breadcrumb $breadcrumbIdx")
32+
}
33+
34+
val config = BugsnagTestUtils.generateImmutableConfig(
35+
Configuration("abc123").apply {
36+
maxBreadcrumbs = 2
37+
maxReportedThreads = 2
38+
maxStringValueLength = MAX_STRING_LENGTH
39+
}
40+
)
41+
42+
val notifier = Notifier(name = "Test Notifier", version = "9.9.9")
43+
val payload = EventPayload(null, event, null, notifier, config)
44+
val trimmed = requireNotNull(payload.trimToSize(BIG_STRING_LENGTH).event)
45+
46+
assertEquals(
47+
"${"*".repeat(MAX_STRING_LENGTH)}***<${BIG_STRING_LENGTH - MAX_STRING_LENGTH}> CHARS TRUNCATED***",
48+
trimmed.getMetadata("trimming")!!["bigString"]
49+
)
50+
51+
val threads = trimmed.threads
52+
assertEquals(3, threads.size)
53+
assertEquals("test thread 0", threads[0].name)
54+
assertEquals("test thread 1", threads[1].name)
55+
assertEquals(
56+
"[8 threads omitted as the maxReportedThreads limit (2) was exceeded]",
57+
threads[2].name
58+
)
59+
60+
val breadcrumbs = trimmed.breadcrumbs
61+
assertEquals(1, breadcrumbs.size)
62+
assertEquals("Removed, along with 9 older breadcrumbs, to reduce payload size", breadcrumbs[0].message)
63+
}
64+
}

0 commit comments

Comments
 (0)