Skip to content

Commit

Permalink
Merge pull request #1619 from bugsnag/v5.20.0
Browse files Browse the repository at this point in the history
v5.20.0
  • Loading branch information
lemnik authored Mar 10, 2022
2 parents 4b7dad9 + 6a2dcdd commit ff29d29
Show file tree
Hide file tree
Showing 29 changed files with 979 additions and 734 deletions.
8 changes: 6 additions & 2 deletions .buildkite/pipeline.full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ steps:
- "--exclude=features/full_tests/[^a-m].*.feature"
- "--app=/app/build/release/fixture-r16.apk"
- "--farm=bs"
- "--device=ANDROID_6_0"
- "--device=ANDROID_6_0_MOTOROLA_MOTO_X_2ND_GEN"
- "--device=ANDROID_6_0_SAMSUNG_GALAXY_S7"
- "--device=ANDROID_6_0_GOOGLE_NEXUS_6"
- "--fail-fast"
concurrency: 9
concurrency_group: 'browserstack-app'
Expand All @@ -181,7 +183,9 @@ steps:
- "--exclude=features/full_tests/[^n-z].*.feature"
- "--app=/app/build/release/fixture-r16.apk"
- "--farm=bs"
- "--device=ANDROID_6_0"
- "--device=ANDROID_6_0_MOTOROLA_MOTO_X_2ND_GEN"
- "--device=ANDROID_6_0_SAMSUNG_GALAXY_S7"
- "--device=ANDROID_6_0_GOOGLE_NEXUS_6"
- "--fail-fast"
concurrency: 9
concurrency_group: 'browserstack-app'
Expand Down
4 changes: 3 additions & 1 deletion .buildkite/pipeline.quick.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ steps:
- "features/smoke_tests"
- "--app=/app/build/release/fixture-r16.apk"
- "--farm=bs"
- "--device=ANDROID_6_0"
- "--device=ANDROID_6_0_MOTOROLA_MOTO_X_2ND_GEN"
- "--device=ANDROID_6_0_SAMSUNG_GALAXY_S7"
- "--device=ANDROID_6_0_GOOGLE_NEXUS_6"
- "--fail-fast"
concurrency: 9
concurrency_group: 'browserstack-app'
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 5.20.0 (2022-03-10)

### Enhancements

* The number of threads reported can now be limited using `Configuration.setMaxReportedThreads` (defaulting to 200)
[#1607](https://github.com/bugsnag/bugsnag-android/pull/1607)

* Improved the performance and stability of the NDK and ANR plugins by caching JNI references on start
[#1596](https://github.com/bugsnag/bugsnag-android/pull/1596)
[#1601](https://github.com/bugsnag/bugsnag-android/pull/1601)

## 5.19.2 (2022-01-31)

### Bug fixes
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ source "https://rubygems.org"
#gem 'bugsnag-maze-runner', path: '../maze-runner'

# Or a specific release:
gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.8.0'
gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.9.3'

# Or follow master:
#gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner'
Expand Down
26 changes: 13 additions & 13 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
GIT
remote: https://github.com/bugsnag/maze-runner
revision: fe12189f83aad154f54221ee0fcd41b483d3c0d1
tag: v6.8.0
revision: 3230db9009a6f5ee9d8beac07deb0d87658521ea
tag: v6.9.3
specs:
bugsnag-maze-runner (6.8.0)
bugsnag-maze-runner (6.9.3)
appium_lib (~> 11.2.0)
bugsnag (~> 6.24)
cucumber (~> 7.1)
Expand All @@ -27,7 +27,7 @@ GEM
appium_lib_core (4.7.1)
faye-websocket (~> 0.11.0)
selenium-webdriver (~> 3.14, >= 3.14.1)
bugsnag (6.24.1)
bugsnag (6.24.2)
concurrent-ruby (~> 1.0)
builder (3.2.4)
childprocess (3.0.0)
Expand All @@ -45,10 +45,10 @@ GEM
mime-types (~> 3.3, >= 3.3.1)
multi_test (~> 0.1, >= 0.1.2)
sys-uname (~> 1.2, >= 1.2.2)
cucumber-core (10.1.0)
cucumber-core (10.1.1)
cucumber-gherkin (~> 22.0, >= 22.0.0)
cucumber-messages (~> 17.1, >= 17.1.1)
cucumber-tag-expressions (~> 4.0, >= 4.0.2)
cucumber-tag-expressions (~> 4.1, >= 4.1.0)
cucumber-create-meta (6.0.4)
cucumber-messages (~> 17.1, >= 17.1.1)
sys-uname (~> 1.2, >= 1.2.2)
Expand All @@ -60,17 +60,16 @@ GEM
cucumber-messages (~> 17.1, >= 17.1.0)
cucumber-messages (17.1.1)
cucumber-tag-expressions (4.1.0)
cucumber-wire (6.2.0)
cucumber-wire (6.2.1)
cucumber-core (~> 10.1, >= 10.1.0)
cucumber-cucumber-expressions (~> 14.0, >= 14.0.0)
cucumber-messages (~> 17.1, >= 17.1.1)
curb (0.9.11)
diff-lcs (1.4.4)
diff-lcs (1.5.0)
eventmachine (1.2.7)
faye-websocket (0.11.1)
eventmachine (>= 0.12.0)
websocket-driver (>= 0.5.1)
ffi (1.15.4)
ffi (1.15.5)
license_finder (6.15.0)
bundler
rubyzip (>= 1, < 3)
Expand All @@ -80,9 +79,9 @@ GEM
xml-simple (~> 1.1.5)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2021.1115)
mime-types-data (3.2022.0105)
multi_test (0.1.2)
nokogiri (1.12.5-x86_64-darwin)
nokogiri (1.13.1-x86_64-darwin)
racc (~> 1.4)
optimist (3.0.1)
os (1.0.1)
Expand Down Expand Up @@ -110,10 +109,11 @@ GEM

PLATFORMS
x86_64-darwin-19
x86_64-darwin-20

DEPENDENCIES
bugsnag-maze-runner!
license_finder (~> 6.13)

BUNDLED WITH
2.2.33
2.3.0
4 changes: 2 additions & 2 deletions bugsnag-android-core/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
<ID>LongParameterList:EventStorageModule.kt$EventStorageModule$( contextModule: ContextModule, configModule: ConfigModule, dataCollectionModule: DataCollectionModule, bgTaskService: BackgroundTaskService, trackerModule: TrackerModule, systemServiceModule: SystemServiceModule, notifier: Notifier, callbackState: CallbackState )</ID>
<ID>LongParameterList:NativeStackframe.kt$NativeStackframe$( /** * The name of the method that was being executed */ var method: String?, /** * The location of the source file */ var file: String?, /** * The line number within the source file this stackframe refers to */ var lineNumber: Number?, /** * The address of the instruction where the event occurred. */ var frameAddress: Long?, /** * The address of the function where the event occurred. */ var symbolAddress: Long?, /** * The address of the library where the event occurred. */ var loadAddress: Long?, /** * Whether this frame identifies the program counter */ var isPC: Boolean?, /** * The type of the error */ var type: ErrorType? = null )</ID>
<ID>LongParameterList:StateEvent.kt$StateEvent.Install$( @JvmField val apiKey: String, @JvmField val autoDetectNdkCrashes: Boolean, @JvmField val appVersion: String?, @JvmField val buildUuid: String?, @JvmField val releaseStage: String?, @JvmField val lastRunInfoPath: String, @JvmField val consecutiveLaunchCrashes: Int, @JvmField val sendThreads: ThreadSendPolicy )</ID>
<ID>LongParameterList:ThreadState.kt$ThreadState$( stackTraces: MutableMap&lt;java.lang.Thread, Array&lt;StackTraceElement>>, currentThread: java.lang.Thread, exc: Throwable?, isUnhandled: Boolean, projectPackages: Collection&lt;String>, logger: Logger )</ID>
<ID>LongParameterList:ThreadState.kt$ThreadState$( allThreads: List&lt;JavaThread>, currentThread: JavaThread, exc: Throwable?, isUnhandled: Boolean, maxThreadCount: Int, projectPackages: Collection&lt;String>, logger: Logger )</ID>
<ID>MagicNumber:DefaultDelivery.kt$DefaultDelivery$299</ID>
<ID>MagicNumber:DefaultDelivery.kt$DefaultDelivery$429</ID>
<ID>MagicNumber:DefaultDelivery.kt$DefaultDelivery$499</ID>
<ID>MagicNumber:LastRunInfoStore.kt$LastRunInfoStore$3</ID>
<ID>MaxLineLength:LastRunInfo.kt$LastRunInfo$return "LastRunInfo(consecutiveLaunchCrashes=$consecutiveLaunchCrashes, crashed=$crashed, crashedDuringLaunch=$crashedDuringLaunch)"</ID>
<ID>MaxLineLength:ThreadState.kt$ThreadState$Thread(thread.id, thread.name, ThreadType.ANDROID, errorThread, Thread.State.forThread(thread), stacktrace, logger)</ID>
<ID>MaxLineLength:ThreadState.kt$ThreadState$"[${allThreads.size - maxThreadCount} threads omitted as the maxReportedThreads limit ($maxThreadCount) was exceeded]"</ID>
<ID>ProtectedMemberInFinalClass:ConfigInternal.kt$ConfigInternal$protected val plugins = HashSet&lt;Plugin>()</ID>
<ID>ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun isAnr(event: Event): Boolean</ID>
<ID>ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun shouldDiscardClass(): Boolean</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,26 @@ class ThreadStateTest {
private val threadState = ThreadState(
null,
true,
1000,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
Thread.currentThread()
)
private val json = streamableToJsonArray(threadState)

private fun allThreads(): List<Thread> {
var rootGroup = Thread.currentThread().threadGroup!!
while (rootGroup.parent != null) {
rootGroup = rootGroup.parent
}

val threadCount = rootGroup.activeCount()
val threads: Array<Thread?> = arrayOfNulls(threadCount)
rootGroup.enumerate(threads)
return threads.filterNotNull()
}

/**
* Verifies that the current thread is serialised as an object, and that only this value
* contains the errorReportingThread boolean flag
Expand All @@ -50,11 +63,12 @@ class ThreadStateTest {
val state = ThreadState(
trace,
true,
1000,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
otherThread,
Thread.getAllStackTraces()
allThreads()
)
val json = streamableToJsonArray(state)
verifyCurrentThreadStructure(json, otherThread.id)
Expand All @@ -67,17 +81,20 @@ class ThreadStateTest {
@Test
fun testMissingCurrentThread() {
val currentThread = Thread.currentThread()
val missingTraces = Thread.getAllStackTraces()
missingTraces.remove(currentThread)
val allThreads = allThreads()
val missingThreads = allThreads.filter {
it.id != currentThread.id
}

val state = ThreadState(
trace,
true,
1000,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
currentThread,
missingTraces
missingThreads
)
val json = streamableToJsonArray(state)

Expand All @@ -92,35 +109,38 @@ class ThreadStateTest {
@Test
fun testHandledStacktrace() {
val currentThread = Thread.currentThread()
val allStackTraces = Thread.getAllStackTraces()
val allThreads = allThreads()
val state = ThreadState(
trace,
true,
1000,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
currentThread,
allStackTraces
allThreads
)
val json = streamableToJsonArray(state)

// find the stack trace for the current thread that was passed as a parameter
val expectedTrace = allStackTraces.filter {
it.key.id == currentThread.id
}.map { it.value }.first()
// find the stack trace for the current thread that was passed as a parameter.
// Drop the top 3 stack elements because we're capturing the trace from a different location.
val expectedTrace = allThreads.first {
it.id == currentThread.id
}.stackTrace.drop(3)

verifyCurrentThreadStructure(json, currentThread.id) {

// the thread id + name should always be used
assertEquals(currentThread.name, it.getString("name"))
assertEquals(currentThread.id, it.getLong("id"))

// stacktrace should come from the thread (check same length and line numbers)
// stacktrace should come from the thread (check same line numbers)
val serialisedTrace = it.getJSONArray("stacktrace")
assertEquals(expectedTrace.size, serialisedTrace.length())
// Only check the lower trace elements due to different trace capture locations.
val traceOffset = serialisedTrace.length() - expectedTrace.size

expectedTrace.forEachIndexed { index, element ->
val jsonObject = serialisedTrace.getJSONObject(index)
val jsonObject = serialisedTrace.getJSONObject(index + traceOffset)
assertEquals(element.lineNumber, jsonObject.getInt("lineNumber"))
}
}
Expand All @@ -138,6 +158,7 @@ class ThreadStateTest {
val state = ThreadState(
exc,
true,
1000,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
Expand All @@ -164,22 +185,77 @@ class ThreadStateTest {
assertTrue(json.length() > 1)
}

/**
* Verifies that maxReportedThreads is honored in a handled error
*/
@Test
fun testHandledStacktraceMaxReportedThreads() {
val currentThread = Thread.currentThread()
val allThreads = allThreads()
val state = ThreadState(
trace,
true,
2,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
currentThread,
allThreads
)
val json = streamableToJsonArray(state)

assertEquals(-1, json.getJSONObject(2).getInt("id"))
assert(
json.getJSONObject(2).getString("name").endsWith(
" threads omitted as the maxReportedThreads limit (2) was exceeded]",
)
)
}

/**
* Verifies that maxReportedThreads is honored in an unhandled error
*/
@Test
fun testUnhandledStacktraceMaxReportedThreads() {
val currentThread = Thread.currentThread()
val exc: Throwable = RuntimeException("Whoops")

val state = ThreadState(
exc,
true,
4,
ThreadSendPolicy.ALWAYS,
Collections.emptyList(),
NoopLogger,
currentThread
)
val json = streamableToJsonArray(state)

assertEquals(-1, json.getJSONObject(4).getInt("id"))
assert(
json.getJSONObject(4).getString("name").endsWith(
" threads omitted as the maxReportedThreads limit (4) was exceeded]",
)
)
}

/**
* Test that using [ThreadSendPolicy.NEVER] ignores any stack-traces and reports an empty
* array of Threads
*/
@Test
fun testNeverPolicyNeverSendsThreads() {
val currentThread = Thread.currentThread()
val allStackTraces = Thread.getAllStackTraces()
val allThreads = allThreads()
val state = ThreadState(
trace,
true,
1000,
ThreadSendPolicy.NEVER,
Collections.emptyList(),
NoopLogger,
currentThread,
allStackTraces
allThreads
)
val json = streamableToJsonArray(state)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ internal class ConfigInternal(
var maxBreadcrumbs: Int = DEFAULT_MAX_BREADCRUMBS
var maxPersistedEvents: Int = DEFAULT_MAX_PERSISTED_EVENTS
var maxPersistedSessions: Int = DEFAULT_MAX_PERSISTED_SESSIONS
var maxReportedThreads: Int = DEFAULT_MAX_REPORTED_THREADS
var context: String? = null

var redactedKeys: Set<String>
Expand Down Expand Up @@ -99,6 +100,7 @@ internal class ConfigInternal(
private const val DEFAULT_MAX_BREADCRUMBS = 50
private const val DEFAULT_MAX_PERSISTED_SESSIONS = 128
private const val DEFAULT_MAX_PERSISTED_EVENTS = 32
private const val DEFAULT_MAX_REPORTED_THREADS = 200
private const val DEFAULT_LAUNCH_CRASH_THRESHOLD_MS: Long = 5000

@JvmStatic
Expand Down
Loading

0 comments on commit ff29d29

Please sign in to comment.