Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5.20.0 #1619

Merged
merged 12 commits into from
Mar 10, 2022
Merged

v5.20.0 #1619

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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