Skip to content

Commit

Permalink
Merge pull request #2084 from bugsnag/release/v6.8.0
Browse files Browse the repository at this point in the history
Release/v6.8.0
  • Loading branch information
YYChen01988 authored Sep 30, 2024
2 parents 874d9e3 + 75e705d commit 740783a
Show file tree
Hide file tree
Showing 22 changed files with 1,024 additions and 354 deletions.
457 changes: 457 additions & 0 deletions .buildkite/pipeline.full.yml

Large diffs are not rendered by default.

366 changes: 366 additions & 0 deletions .buildkite/pipeline.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ bugsnag_test
.cxx/
.project
decisions.yml
Gemfile.lock
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## 6.8.0 (2024-09-30)

### Enhancements

* Add original error class and message to metadata for link errors loading BugSnag libraries
[#2070](https://github.com/bugsnag/bugsnag-android/pull/2070)

### Bug fixes

* Sending startup crashes synchronously now uses a flexible timeout so that apps with slower startups don't ANR
[#2075](https://github.com/bugsnag/bugsnag-android/pull/2075)
[#2080](https://github.com/bugsnag/bugsnag-android/pull/2080)
* Work around a possible platform NullPointerException when calling `Intent.getExtras` (https://github.com/bugsnag/bugsnag-android/issues/2082)
[#2083](https://github.com/bugsnag/bugsnag-android/pull/2083)

## 6.7.0 (2024-08-08)

### Enhancements
Expand Down
141 changes: 0 additions & 141 deletions Gemfile.lock

This file was deleted.

1 change: 1 addition & 0 deletions bugsnag-android-core/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<ID>ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun updateSeverityReason(@SeverityReason.SeverityReasonType reason: String)</ID>
<ID>ReturnCount:DefaultDelivery.kt$DefaultDelivery$fun deliver( urlString: String, json: ByteArray, headers: Map&lt;String, String?> ): DeliveryStatus</ID>
<ID>SpreadOperator:FileStore.kt$FileStore$(*listFiles)</ID>
<ID>SwallowedException:ActivityBreadcrumbCollector.kt$ActivityBreadcrumbCollector$re: Exception</ID>
<ID>SwallowedException:AppDataCollector.kt$AppDataCollector$e: Exception</ID>
<ID>SwallowedException:BugsnagEventMapper.kt$BugsnagEventMapper$pe: IllegalArgumentException</ID>
<ID>SwallowedException:ConnectivityCompat.kt$ConnectivityLegacy$e: NullPointerException</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ internal class ActivityBreadcrumbCollector(
}

set("hasData", intent.data != null)
set("hasExtras", intent.extras?.keySet()?.joinToString(", ") ?: false)

try {
set("hasExtras", intent.extras?.keySet()?.joinToString(", ") ?: false)
} catch (re: Exception) {
// deliberately ignore
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package com.bugsnag.android

import android.os.SystemClock
import com.bugsnag.android.EventFilenameInfo.Companion.findTimestampInFilename
import com.bugsnag.android.EventFilenameInfo.Companion.fromEvent
import com.bugsnag.android.EventFilenameInfo.Companion.fromFile
import com.bugsnag.android.JsonStream.Streamable
import com.bugsnag.android.internal.BackgroundTaskService
import com.bugsnag.android.internal.ForegroundDetector
import com.bugsnag.android.internal.ImmutableConfig
import com.bugsnag.android.internal.TaskType
import java.io.File
import java.util.Calendar
import java.util.Comparator
import java.util.Date
import java.util.concurrent.Callable
import java.util.concurrent.ExecutionException
Expand All @@ -19,8 +20,7 @@ import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException

/**
* Store and flush Event reports which couldn't be sent immediately due to
* lack of network connectivity.
* Store and flush Event reports.
*/
internal class EventStore(
private val config: ImmutableConfig,
Expand All @@ -42,7 +42,8 @@ internal class EventStore(
override val logger: Logger

/**
* Flush startup crashes synchronously on the main thread
* Flush startup crashes synchronously on the main thread. Startup crashes block the main thread
* when being sent (subject to [Configuration.setSendLaunchCrashesSynchronously])
*/
fun flushOnLaunch() {
if (!config.sendLaunchCrashesSynchronously) {
Expand All @@ -58,13 +59,28 @@ internal class EventStore(
return
}
try {
future.get(LAUNCH_CRASH_TIMEOUT_MS, TimeUnit.MILLISECONDS)
// Calculate the maximum amount of time we are prepared to block while sending
// startup crashes, based on how long we think startup has taken so-far.
// This attempts to mitigate possible startup ANRs that can occur when other SDKs
// have blocked the main thread before this code is reached.
val currentStartupDuration =
SystemClock.elapsedRealtime() - ForegroundDetector.startupTime
var timeout = LAUNCH_CRASH_TIMEOUT_MS - currentStartupDuration

if (timeout <= 0) {
// if Bugsnag.start is called too long after Application.onCreate is expected to
// have returned, we use a full LAUNCH_CRASH_TIMEOUT_MS instead of a calculated one
// assuming that the app is already fully started
timeout = LAUNCH_CRASH_TIMEOUT_MS
}

future.get(timeout, TimeUnit.MILLISECONDS)
} catch (exc: InterruptedException) {
logger.d("Failed to send launch crash reports within 2s timeout, continuing.", exc)
logger.d("Failed to send launch crash reports within timeout, continuing.", exc)
} catch (exc: ExecutionException) {
logger.d("Failed to send launch crash reports within 2s timeout, continuing.", exc)
logger.d("Failed to send launch crash reports within timeout, continuing.", exc)
} catch (exc: TimeoutException) {
logger.d("Failed to send launch crash reports within 2s timeout, continuing.", exc)
logger.d("Failed to send launch crash reports within timeout, continuing.", exc)
}
}

Expand Down Expand Up @@ -159,6 +175,7 @@ internal class EventStore(
deleteStoredFiles(setOf(eventFile))
logger.i("Deleting sent error file $eventFile.name")
}

DeliveryStatus.UNDELIVERED -> undeliveredEventPayload(eventFile)
DeliveryStatus.FAILURE -> {
val exc: Exception = RuntimeException("Failed to deliver event payload")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.io.IOException
*/
class Notifier @JvmOverloads constructor(
var name: String = "Android Bugsnag Notifier",
var version: String = "6.7.0",
var version: String = "6.8.0",
var url: String = "https://bugsnag.com"
) : JsonStream.Streamable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ internal object ForegroundDetector : ActivityLifecycleCallbacks, Handler.Callbac

private var waitingForActivityRestart: Boolean = false

/**
* Marks the timestamp (relative to [SystemClock.elapsedRealtime]) that we initialised for the
* first time.
*/
internal val startupTime = SystemClock.elapsedRealtime()

@VisibleForTesting
internal var backgroundSent = true

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bugsnag.android

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
Expand All @@ -10,6 +11,8 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnitRunner

@RunWith(MockitoJUnitRunner::class)
Expand Down Expand Up @@ -120,4 +123,15 @@ internal class ActivityLifecycleBreadcrumbTest {
tracker.onActivityStarted(activity2)
assertEquals("onCreate()", resultMetadata!!["previous"])
}

@Test
fun failGetExtras() {
val mockIntent = mock(Intent::class.java)
`when`(mockIntent.extras).thenThrow(NullPointerException())
`when`(activity.intent).thenReturn(mockIntent)

tracker.onActivityCreated(activity, null)
assertFalse(resultMetadata!!["hasBundle"] as Boolean)
assertFalse(resultMetadata!!["hasData"] as Boolean)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ internal class AnrPlugin : Plugin {
private fun performOneTimeSetup(client: Client) {
val isLoaded = libraryLoader.loadLibrary("bugsnag-plugin-android-anr", client) {
val error = it.errors[0]
it.addMetadata("LinkError", "errorClass", error.errorClass)
it.addMetadata("LinkError", "errorMessage", error.errorMessage)

error.errorClass = "AnrLinkError"
error.errorMessage = LOAD_ERR_MSG
true
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@ services:
<<: *common-environment
BITBAR_USERNAME:
BITBAR_ACCESS_KEY:
BROWSER_STACK_USERNAME:
BROWSER_STACK_ACCESS_KEY:
ports:
- "9000-9499:9339"
volumes:
- ./build:/app/build
- ./features/:/app/features/
- ./maze_output:/app/maze_output
- ./reports/:/app/reports/
- /var/run/docker.sock:/var/run/docker.sock

android-license-audit:
Expand Down
4 changes: 2 additions & 2 deletions examples/sdk-app-example/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ android {
}

dependencies {
implementation "com.bugsnag:bugsnag-android:6.7.0"
implementation "com.bugsnag:bugsnag-plugin-android-okhttp:6.7.0"
implementation "com.bugsnag:bugsnag-android:6.8.0"
implementation "com.bugsnag:bugsnag-plugin-android-okhttp:6.8.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.appcompat:appcompat:1.6.1"
implementation "com.google.android.material:material:1.11.0"
Expand Down
Loading

0 comments on commit 740783a

Please sign in to comment.