diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index bb4cc40b..1fced5c1 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -53,8 +53,6 @@ steps: - label: ':bitbar: iOS 14 end-to-end tests 3.10.0' depends_on: "ios-fixture-3-10-0" timeout_in_minutes: 20 - env: - FLUTTER_BIN: "/opt/flutter/3.10.0/bin/flutter" agents: queue: opensource plugins: @@ -93,11 +91,9 @@ steps: from: "features/fixtures/app/build/app/outputs/flutter-apk/app-release.apk" to: "features/fixtures/app/build/app/outputs/flutter-apk/app-release-3.10.0.apk" - - label: ':bitbar: Android 12 end-to-end tests 3.10.0' + - label: ':browserstack: Android 12 end-to-end tests 3.10.0' depends_on: "android-fixture-3-10-0" timeout_in_minutes: 20 - env: - FLUTTER_BIN: "/opt/flutter/3.10.0/bin/flutter" agents: queue: opensource plugins: @@ -110,11 +106,10 @@ steps: service-ports: true command: - "--app=/app/features/fixtures/app/build/app/outputs/flutter-apk/app-release-3.10.0.apk" - - "--farm=bb" - - "--device=ANDROID_10|ANDROID_11|ANDROID_12|ANDROID_13" - - "--no-tunnel" - - "--aws-public-ip" + - "--farm=bs" + - "--device=ANDROID_12" + - "--appium-version=1.22.0" - "--fail-fast" - concurrency: 25 - concurrency_group: 'bitbar' + concurrency: 5 + concurrency_group: 'browserstack-app' concurrency_method: eager diff --git a/CHANGELOG.md b/CHANGELOG.md index 6645c3ce..48c16982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 4.0.0 (2024-07-29) + +### Breaking Changes + +- The configuration options `discardClasses` and `redactedKeys` are now `RegExp`s instead of strings. This allows developers to have more control over how they perform. + [249](https://github.com/bugsnag/bugsnag-flutter/pull/249) + +- Getting the correlation trace ID and span ID through `flutter_bridge` and adding it to events. + [251](https://github.com/bugsnag/bugsnag-flutter/pull/251) + +Please see our [Upgrading guide](./UPGRADING.MD) for more information on upgrading to v4.x. + ## 3.1.1 (2024-04-24) - Fixed: Navigator.pushAndRemoveUntil throws exception [#242](https://github.com/bugsnag/bugsnag-flutter/pull/242) diff --git a/Gemfile b/Gemfile index 703d9dbd..850c43c3 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' # A reference to Maze Runner is only needed for running tests locally and if committed it must be # portable for CI, e.g. a specific release. However, leaving it commented out would mean quicker CI. -gem 'bugsnag-maze-runner', '~> 8.0' +gem 'bugsnag-maze-runner', '~> 9.0' gem 'cocoapods' # Use a specific branch diff --git a/Gemfile.lock b/Gemfile.lock index 44415772..457998bd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,25 @@ GEM remote: https://rubygems.org/ specs: + CFPropertyList (3.0.7) + base64 + nkf + rexml + activesupport (7.1.3.2) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) appium_lib (12.0.1) appium_lib_core (~> 5.0) nokogiri (~> 1.8, >= 1.8.1) @@ -8,9 +27,12 @@ GEM appium_lib_core (5.4.0) faye-websocket (~> 0.11.0) selenium-webdriver (~> 4.2, < 4.6) - bugsnag (6.26.0) + atomos (0.1.3) + base64 (0.2.0) + bigdecimal (3.1.7) + bugsnag (6.27.1) concurrent-ruby (~> 1.0) - bugsnag-maze-runner (8.2.0) + bugsnag-maze-runner (9.11.1) appium_lib (~> 12.0.0) appium_lib_core (~> 5.4.0) bugsnag (~> 6.24) @@ -27,9 +49,49 @@ GEM selenium-webdriver (~> 4.0) test-unit (~> 3.5.2) webrick (~> 1.7.0) - builder (3.2.4) + builder (3.3.0) childprocess (4.1.0) + claide (1.1.0) + cocoapods (1.15.2) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.15.2) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.23.0, < 2.0) + cocoapods-core (1.15.2) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (2.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored2 (3.1.2) concurrent-ruby (1.2.2) + connection_pool (2.4.1) cucumber (7.1.0) builder (~> 3.2, >= 3.2.4) cucumber-core (~> 10.1, >= 10.1.0) @@ -62,65 +124,97 @@ GEM cucumber-core (~> 10.1, >= 10.1.0) cucumber-cucumber-expressions (~> 14.0, >= 14.0.0) curb (0.9.11) - diff-lcs (1.5.0) + diff-lcs (1.5.1) dogstatsd-ruby (5.5.0) + drb (2.2.1) ecma-re-validator (0.4.0) regexp_parser (~> 2.2) + escape (0.0.4) + ethon (0.16.0) + ffi (>= 1.15.0) eventmachine (1.2.7) faye-websocket (0.11.3) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) ffi (1.15.5) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) hana (1.3.7) + httpclient (2.8.3) + i18n (1.14.4) + concurrent-ruby (~> 1.0) + json (2.7.2) json_schemer (0.2.25) ecma-re-validator (~> 0.3) hana (~> 1.3) regexp_parser (~> 2.0) simpleidn (~> 0.2) uri_template (~> 0.7) - mime-types (3.4.1) + mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2023.0218.1) + mime-types-data (3.2024.0702) + minitest (5.22.3) + molinillo (0.8.0) multi_test (0.1.2) - nokogiri (1.15.3-x86_64-darwin) + mutex_m (0.2.0) + nanaimo (0.3.0) + nap (1.1.0) + netrc (0.11.0) + nkf (0.2.0) + nokogiri (1.16.6-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.6-x86_64-darwin) racc (~> 1.4) optimist (3.0.1) os (1.0.1) power_assert (2.0.3) - racc (1.7.1) - rack (2.2.8) + public_suffix (4.0.7) + racc (1.8.0) + rack (2.2.9) rake (12.3.3) - regexp_parser (2.8.1) + regexp_parser (2.9.2) rexml (3.2.6) + ruby-macho (2.5.1) rubyzip (2.3.2) selenium-webdriver (4.5.0) childprocess (>= 0.5, < 5.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - simpleidn (0.2.1) - unf (~> 0.1.4) - sys-uname (1.2.3) + simpleidn (0.2.3) + sys-uname (1.3.0) ffi (~> 1.1) test-unit (3.5.9) power_assert tomlrb (2.0.3) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) + typhoeus (1.4.1) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) uri_template (0.7.0) webrick (1.7.0) - websocket (1.2.9) + websocket (1.2.11) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + xcodeproj (1.24.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) PLATFORMS + arm64-darwin-22 x86_64-darwin-20 x86_64-darwin-21 + x86_64-darwin-23 DEPENDENCIES - bugsnag-maze-runner (~> 8.0) + bugsnag-maze-runner (~> 9.0) + cocoapods BUNDLED WITH - 2.4.8 + 2.4.18 diff --git a/Makefile b/Makefile index e492f841..1339432b 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ staging/bugsnag_flutter: mkdir -p staging/bugsnag_flutter cd packages/bugsnag_flutter && cp -a . ../../staging/bugsnag_flutter rm -f staging/bugsnag_flutter/pubspec.lock - cp -r examples staging/bugsnag_flutter/examples + cp -r examples/flutter staging/bugsnag_flutter/example cp README.md staging/bugsnag_flutter/. cp LICENSE staging/bugsnag_flutter/. cp CHANGELOG.md staging/bugsnag_flutter/. @@ -111,4 +111,4 @@ else ifeq ($(SUBMODULE), bugsnag-cocoa) $(MAKE) update-bugsnag-cocoa else @$(error SUBMODULE must be one of bugsnag-android or bugsnag-cocoa) -endif \ No newline at end of file +endif diff --git a/README.md b/README.md index 7715968b..f96b9980 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Bugsnag error monitoring & reporting for Flutter apps [![Documentation](https://img.shields.io/badge/documentation-latest-blue.svg)](https://docs.bugsnag.com/platforms/flutter/) -[![Build status](https://badge.buildkite.com/e5d6c82f7202bbfe7114be8b8cb245b447a29470cd9320658b.svg)](https://buildkite.com/bugsnag/bugsnag-flutter) +[![Build status](https://badge.buildkite.com/e5d6c82f7202bbfe7114be8b8cb245b447a29470cd9320658b.svg?branch=main)](https://buildkite.com/bugsnag/bugsnag-flutter) The [Bugsnag](https://www.bugsnag.com) error reporting library automatically detects Dart errors and native crashes in Flutter apps running on iOS and Android, collecting diagnostic information and diff --git a/UPGRADING.MD b/UPGRADING.MD index bede4de5..8976759d 100644 --- a/UPGRADING.MD +++ b/UPGRADING.MD @@ -1,6 +1,29 @@ Upgrading ========= +## 3.x to 4.x + +### Key points + +- The configuration options `discardClasses` and `redactedKeys` are now `RegExp`s instead of strings. This allows developers to have more control over how they perform. + +### Starting the client + +`bugsnag.start` accepts `Set` for `redactedKeys` and `discardClasses`. To specify them use: + +```dart +bugsnag.start( + // ... + redactedKeys: { + RegExp('password'), + RegExp('^[A-Fa-f0-9]{16}\$', multiLine: true) + }, + discardClasses: { + RegExp('sec', caseSensitive: false), + }, + // ... +); + ## 2.x to 3.x A minimum of Flutter version of 3.10.0 is now required. diff --git a/docker-compose.yml b/docker-compose.yml index ba7d647e..bf1d84d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.6' services: maze-runner: - image: 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v8-cli + image: 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v9-cli environment: DEBUG: BITBAR_USERNAME: @@ -21,6 +21,8 @@ services: BUILDKITE_RETRY_COUNT: BUILDKITE_STEP_KEY: MAZE_BUGSNAG_API_KEY: + BROWSER_STACK_USERNAME: + BROWSER_STACK_ACCESS_KEY: ports: - "9000-9499:9339" volumes: diff --git a/examples/flutter/.metadata b/examples/flutter/.metadata index fd70cabc..f991a3ab 100644 --- a/examples/flutter/.metadata +++ b/examples/flutter/.metadata @@ -1,10 +1,33 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b + revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + - platform: android + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + - platform: ios + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/examples/flutter/android/app/build.gradle b/examples/flutter/android/app/build.gradle index a8066dfd..18f40c36 100644 --- a/examples/flutter/android/app/build.gradle +++ b/examples/flutter/android/app/build.gradle @@ -22,16 +22,27 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion flutter.hasProperty('compileSdkVersion') ? flutter.compileSdkVersion : 30 + namespace "com.bugsnag.examples.flutter" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + defaultConfig { applicationId "com.bugsnag.examples.flutter" minSdkVersion flutter.hasProperty('minSdkVersion') ? flutter.minSdkVersion : 16 @@ -51,3 +62,7 @@ android { flutter { source '../..' } + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/examples/flutter/android/app/src/debug/AndroidManifest.xml b/examples/flutter/android/app/src/debug/AndroidManifest.xml index 8d760c33..399f6981 100644 --- a/examples/flutter/android/app/src/debug/AndroidManifest.xml +++ b/examples/flutter/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,6 @@ - - diff --git a/examples/flutter/android/app/src/main/AndroidManifest.xml b/examples/flutter/android/app/src/main/AndroidManifest.xml index 7b20627d..d29131e9 100644 --- a/examples/flutter/android/app/src/main/AndroidManifest.xml +++ b/examples/flutter/android/app/src/main/AndroidManifest.xml @@ -1,27 +1,27 @@ - - + + android:label="Bugsnag Flutter Example" + android:name="${applicationName}" + android:icon="@mipmap/ic_launcher"> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> - - + + diff --git a/examples/flutter/android/build.gradle b/examples/flutter/android/build.gradle index 80476457..f7eb7f63 100644 --- a/examples/flutter/android/build.gradle +++ b/examples/flutter/android/build.gradle @@ -1,17 +1,18 @@ buildscript { + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { - mavenLocal() google() mavenCentral() } @@ -25,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/examples/flutter/android/gradle/wrapper/gradle-wrapper.properties b/examples/flutter/android/gradle/wrapper/gradle-wrapper.properties index bc6a58af..3c472b99 100644 --- a/examples/flutter/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/flutter/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/examples/flutter/ios/Runner.xcodeproj/project.pbxproj b/examples/flutter/ios/Runner.xcodeproj/project.pbxproj index 09342ae7..664e7602 100644 --- a/examples/flutter/ios/Runner.xcodeproj/project.pbxproj +++ b/examples/flutter/ios/Runner.xcodeproj/project.pbxproj @@ -149,6 +149,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9BFDAD3CEB135709170D6F87 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -259,6 +260,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + 9BFDAD3CEB135709170D6F87 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 28c6bf03..7353c41e 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 2ccbfd96..797d452e 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index f091b6b0..6ed2d933 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde1211..4cd7b009 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index d0ef06e7..fe730945 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index dcdc2306..321773cd 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 2ccbfd96..797d452e 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index c8f9ed8f..502f463a 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b860..0ec30343 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b860..0ec30343 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d164..e9f5fea2 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d3..84ac32ae 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 6a84f41e..8953cba0 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index d0e1f585..0467bf12 100644 Binary files a/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/examples/flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/features/fixtures/app/.metadata b/features/fixtures/app/.metadata index fd70cabc..f991a3ab 100644 --- a/features/fixtures/app/.metadata +++ b/features/fixtures/app/.metadata @@ -1,10 +1,33 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b + revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + - platform: android + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + - platform: ios + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/features/fixtures/app/android/app/build.gradle b/features/fixtures/app/android/app/build.gradle index 0b6a8586..228cee60 100644 --- a/features/fixtures/app/android/app/build.gradle +++ b/features/fixtures/app/android/app/build.gradle @@ -22,16 +22,27 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion flutter.hasProperty('compileSdkVersion') ? flutter.compileSdkVersion : 30 + namespace "com.bugsnag.flutter.test.app" + ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + defaultConfig { applicationId "com.bugsnag.flutter.test.app" minSdkVersion 16 @@ -64,18 +75,18 @@ android { signingConfig signingConfigs.debug minifyEnabled true - useProguard true + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } -dependencies { - // TODO: this will need to change at some point to a`bugsnag-android-flutter` project - implementation 'com.bugsnag:bugsnag-android:5.19.1' -} - flutter { source '../..' } + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.bugsnag:bugsnag-android:5.19.1' +} diff --git a/features/fixtures/app/android/app/src/debug/AndroidManifest.xml b/features/fixtures/app/android/app/src/debug/AndroidManifest.xml index 4e36f3f2..399f6981 100644 --- a/features/fixtures/app/android/app/src/debug/AndroidManifest.xml +++ b/features/fixtures/app/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,6 @@ - - diff --git a/features/fixtures/app/android/app/src/main/AndroidManifest.xml b/features/fixtures/app/android/app/src/main/AndroidManifest.xml index dee939ed..f1d5fb5c 100644 --- a/features/fixtures/app/android/app/src/main/AndroidManifest.xml +++ b/features/fixtures/app/android/app/src/main/AndroidManifest.xml @@ -5,8 +5,9 @@ + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> - - + + diff --git a/features/fixtures/app/android/build.gradle b/features/fixtures/app/android/build.gradle index 06f2b41d..f7eb7f63 100644 --- a/features/fixtures/app/android/build.gradle +++ b/features/fixtures/app/android/build.gradle @@ -1,11 +1,13 @@ buildscript { + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/features/fixtures/app/android/gradle.properties b/features/fixtures/app/android/gradle.properties index 4d3226ab..94adc3a3 100644 --- a/features/fixtures/app/android/gradle.properties +++ b/features/fixtures/app/android/gradle.properties @@ -1,3 +1,3 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true diff --git a/features/fixtures/app/android/gradle/wrapper/gradle-wrapper.properties b/features/fixtures/app/android/gradle/wrapper/gradle-wrapper.properties index 595fb867..3c472b99 100644 --- a/features/fixtures/app/android/gradle/wrapper/gradle-wrapper.properties +++ b/features/fixtures/app/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 28c6bf03..7353c41e 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 2ccbfd96..797d452e 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index f091b6b0..6ed2d933 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde1211..4cd7b009 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index d0ef06e7..fe730945 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index dcdc2306..321773cd 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 2ccbfd96..797d452e 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index c8f9ed8f..502f463a 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b860..0ec30343 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b860..0ec30343 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d164..e9f5fea2 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d3..84ac32ae 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 6a84f41e..8953cba0 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index d0e1f585..0467bf12 100644 Binary files a/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/features/fixtures/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/features/fixtures/app/ios/Runner/Info.plist b/features/fixtures/app/ios/Runner/Info.plist index 5dd9cb75..2e7211d1 100644 --- a/features/fixtures/app/ios/Runner/Info.plist +++ b/features/fixtures/app/ios/Runner/Info.plist @@ -53,6 +53,10 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents bugsnag diff --git a/features/fixtures/app/lib/scenarios/discard_classes_scenario.dart b/features/fixtures/app/lib/scenarios/discard_classes_scenario.dart index 2b3f699e..91a6c565 100644 --- a/features/fixtures/app/lib/scenarios/discard_classes_scenario.dart +++ b/features/fixtures/app/lib/scenarios/discard_classes_scenario.dart @@ -9,9 +9,9 @@ class DiscardClassesScenario extends Scenario { await bugsnag.start( endpoints: endpoints, - discardClasses: const { - '_Exception', - } + discardClasses: { + RegExp('_Exception'), + }, ); try { throw Exception('this should be discarded'); diff --git a/features/fixtures/app/lib/scenarios/start_bugsnag_scenario.dart b/features/fixtures/app/lib/scenarios/start_bugsnag_scenario.dart index 657f4a1f..8a967a62 100644 --- a/features/fixtures/app/lib/scenarios/start_bugsnag_scenario.dart +++ b/features/fixtures/app/lib/scenarios/start_bugsnag_scenario.dart @@ -6,33 +6,33 @@ class StartBugsnagScenario extends Scenario { @override Future run() async { await bugsnag.start( - apiKey: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - appType: 'test', - appVersion: '1.2.3', - versionCode: 4321, - context: 'awesome', - user: BugsnagUser( - id: '123', - name: 'From Config', - ), - redactedKeys: {'secret'}, - releaseStage: 'testing', - enabledReleaseStages: {'testing'}, - enabledBreadcrumbTypes: {BugsnagEnabledBreadcrumbType.error}, - endpoints: endpoints, - featureFlags: const [ - BugsnagFeatureFlag('demo-mode'), - BugsnagFeatureFlag('sample-group', '123'), - ], - metadata: const { - 'custom': { - 'foo': 'bar', - 'secret': 'should be hidden', - 'password': 'not redacted' - } - }, - sendThreads: BugsnagThreadSendPolicy.never - ); + apiKey: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + appType: 'test', + appVersion: '1.2.3', + versionCode: 4321, + context: 'awesome', + user: BugsnagUser( + id: '123', + name: 'From Config', + ), + redactedKeys: {RegExp('secret')}, + releaseStage: 'testing', + enabledReleaseStages: {'testing'}, + enabledBreadcrumbTypes: {BugsnagEnabledBreadcrumbType.error}, + endpoints: endpoints, + featureFlags: const [ + BugsnagFeatureFlag('demo-mode'), + BugsnagFeatureFlag('sample-group', '123'), + ], + metadata: const { + 'custom': { + 'foo': 'bar', + 'secret': 'should be hidden', + 'password': 'not redacted' + } + }, + sendThreads: BugsnagThreadSendPolicy.never, + ); await bugsnag.notify( Exception('Exception with attached info'), StackTrace.current, diff --git a/features/fixtures/app/pubspec.lock b/features/fixtures/app/pubspec.lock index c367adea..1b2c248c 100644 --- a/features/fixtures/app/pubspec.lock +++ b/features/fixtures/app/pubspec.lock @@ -17,13 +17,36 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + bugsnag_bridge: + dependency: transitive + description: + path: "packages/bugsnag-flutter-bridge" + ref: HEAD + resolved-ref: "0a2b35f8b0a5908082ce0f57e85fa9c027a0f0ad" + url: "https://github.com/bugsnag/bugsnag-flutter-common" + source: git + version: "0.1.0" bugsnag_flutter: dependency: "direct main" description: path: "../../../packages/bugsnag_flutter" relative: true source: path - version: "3.0.0" + version: "3.1.1" + bugsnag_flutter_dart_io_http_client: + dependency: "direct main" + description: + path: "../../../packages/bugsnag_flutter_dart_io_http_client" + relative: true + source: path + version: "1.1.1" + bugsnag_http_client: + dependency: "direct main" + description: + path: "../../../packages/bugsnag_http_client" + relative: true + source: path + version: "1.1.0" characters: dependency: transitive description: @@ -32,14 +55,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - charcode: - dependency: transitive - description: - name: charcode - sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 - url: "https://pub.dev" - source: hosted - version: "1.3.1" clock: dependency: transitive description: @@ -52,18 +67,18 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: "1989d917fbe8e6b39806207df5a3fdd3d816cbd090fac2ce26fb45e9a71476e5" + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.6" fake_async: dependency: transitive description: @@ -76,10 +91,10 @@ packages: dependency: transitive description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" flutter: dependency: "direct main" description: flutter @@ -102,18 +117,18 @@ packages: dependency: "direct main" description: name: http - sha256: "2ed163531e071c2c6b7c659635112f24cb64ecbebf6af46b550d536c0b1aa112" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.4" + version: "1.1.0" http_parser: dependency: transitive description: name: http_parser - sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185 + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.2" js: dependency: transitive description: @@ -134,18 +149,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -166,66 +181,66 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8" + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.8" sky_engine: dependency: transitive description: flutter @@ -235,10 +250,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -275,18 +290,18 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" typed_data: dependency: transitive description: name: typed_data - sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.2" vector_math: dependency: transitive description: @@ -295,22 +310,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" win32: dependency: transitive description: name: win32 - sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "5.0.6" + version: "5.0.9" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.4" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/packages/bugsnag_breadcrumbs_dart_io/pubspec.yaml b/packages/bugsnag_breadcrumbs_dart_io/pubspec.yaml index d38d916f..cf7878ca 100644 --- a/packages/bugsnag_breadcrumbs_dart_io/pubspec.yaml +++ b/packages/bugsnag_breadcrumbs_dart_io/pubspec.yaml @@ -1,6 +1,6 @@ name: bugsnag_breadcrumbs_dart_io description: Bugsnag network breadcrumbs for dart:io's HttpClient -version: 3.0.2 +version: 4.0.0 homepage: https://www.bugsnag.com/ documentation: https://docs.bugsnag.com/platforms/flutter/ repository: https://github.com/bugsnag/bugsnag-flutter diff --git a/packages/bugsnag_breadcrumbs_http/pubspec.yaml b/packages/bugsnag_breadcrumbs_http/pubspec.yaml index 5abd1c8a..ed08db7d 100644 --- a/packages/bugsnag_breadcrumbs_http/pubspec.yaml +++ b/packages/bugsnag_breadcrumbs_http/pubspec.yaml @@ -1,6 +1,6 @@ name: bugsnag_breadcrumbs_http description: Bugsnag network breadcrumbs for https://pub.dev/packages/http -version: 3.0.2 +version: 4.0.0 homepage: https://www.bugsnag.com/ documentation: https://docs.bugsnag.com/platforms/flutter/ repository: https://github.com/bugsnag/bugsnag-flutter diff --git a/packages/bugsnag_flutter/android/build.gradle b/packages/bugsnag_flutter/android/build.gradle index 9a83e700..3efdec7d 100644 --- a/packages/bugsnag_flutter/android/build.gradle +++ b/packages/bugsnag_flutter/android/build.gradle @@ -50,7 +50,7 @@ android { } dependencies { - implementation 'com.bugsnag:bugsnag-android:5.31.3' + implementation 'com.bugsnag:bugsnag-android:6.6.0' testImplementation 'junit:junit:4.12' } diff --git a/packages/bugsnag_flutter/android/src/main/java/com/bugsnag/flutter/BugsnagFlutter.java b/packages/bugsnag_flutter/android/src/main/java/com/bugsnag/flutter/BugsnagFlutter.java index 447cde66..aa5f9960 100644 --- a/packages/bugsnag_flutter/android/src/main/java/com/bugsnag/flutter/BugsnagFlutter.java +++ b/packages/bugsnag_flutter/android/src/main/java/com/bugsnag/flutter/BugsnagFlutter.java @@ -32,6 +32,8 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; +import java.util.UUID; class BugsnagFlutter { @@ -42,6 +44,8 @@ class BugsnagFlutter { private static boolean isAnyStarted = false; private boolean isStarted = false; + static final int HEX_LONG_LENGTH = 16; + /* *********************************************************************************************** * All methods listed here must also be registered in the BugsnagFlutterPlugin otherwise they @@ -91,7 +95,8 @@ Void start(@Nullable JSONObject args) throws Exception { } if (isAnyStarted) { - Log.i("BugsnagFlutter", "bugsnag.start() was called from a previous Flutter context. Ignoring."); + Log.w("BugsnagFlutter", "bugsnag.start() was called from a previous Flutter context. Reusing existing client. Config not applied."); + client = new InternalHooks(InternalHooks.getClient()); return null; } @@ -119,11 +124,11 @@ Void start(@Nullable JSONObject args) throws Exception { configuration.setPersistUser(arguments.optBoolean("persistUser", configuration.getPersistUser())); if (arguments.has("redactedKeys")) { - configuration.setRedactedKeys(unwrap(arguments.optJSONArray("redactedKeys"), new HashSet<>())); + configuration.setRedactedKeys(regexSetFromArray(arguments.optJSONArray("redactedKeys"))); } if (arguments.has("discardClasses")) { - configuration.setDiscardClasses(unwrap(arguments.optJSONArray("discardClasses"), new HashSet<>())); + configuration.setDiscardClasses(regexSetFromArray(arguments.optJSONArray("discardClasses"))); } if (arguments.has("enabledReleaseStages")) { @@ -343,6 +348,29 @@ Void markLaunchCompleted(@Nullable Void args) { return null; } + Set regexSetFromArray(JSONArray array) throws JSONException { + HashSet result = new HashSet<>(array.length()); + for (int i = 0; i < array.length(); i++) { + JSONObject element = array.getJSONObject(i); + String pattern = getString(element, "pattern"); + int flags = 0; + if (element.optBoolean("isDotAll")) { + flags |= Pattern.DOTALL; + } + if (!element.optBoolean("isCaseSensitive")) { + flags |= Pattern.CASE_INSENSITIVE; + } + if (element.optBoolean("isMultiLine")) { + flags |= Pattern.MULTILINE; + } + + if (pattern != null) { + result.add(Pattern.compile(pattern, flags)); + } + } + return result; + } + JSONObject getLastRunInfo(@Nullable Void args) throws JSONException { LastRunInfo lastRunInfo = Bugsnag.getLastRunInfo(); return (lastRunInfo == null) ? null : new JSONObject() @@ -353,7 +381,7 @@ JSONObject getLastRunInfo(@Nullable Void args) throws JSONException { @SuppressWarnings("unchecked") JSONObject createEvent(@Nullable JSONObject args) throws JSONException { - if (args == null || !args.has("error")) { + if (args == null || !args.has("error") || client == null) { return null; } @@ -381,6 +409,26 @@ JSONObject createEvent(@Nullable JSONObject args) throws JSONException { event.addMetadata("flutter", (Map) flutterMetadata); } + JSONObject correlation = args.optJSONObject("correlation"); + if (correlation != null) { + try { + String traceId = getString(correlation, "traceId"); + String spanId = getString(correlation, "spanId"); + if (traceId != null && + traceId.length() == HEX_LONG_LENGTH * 2 && + spanId != null && + spanId.length() == HEX_LONG_LENGTH + ) { + long traceIdMostSignificantBits = hexToLong(traceId.substring(0, HEX_LONG_LENGTH)); + long traceIdLeastSignificantBits = hexToLong(traceId.substring(HEX_LONG_LENGTH)); + long spanIdAsLong = hexToLong(spanId); + event.setTraceCorrelation(new UUID(traceIdMostSignificantBits, traceIdLeastSignificantBits), spanIdAsLong); + } + } catch(Exception e) { + // ignore the error, the error correlation will be missing + } + } + if (deliver) { // Flutter layer has asked us to deliver the Event immediately client.deliverEvent(event); @@ -391,7 +439,7 @@ JSONObject createEvent(@Nullable JSONObject args) throws JSONException { } JSONObject deliverEvent(@Nullable JSONObject eventJson) { - if (eventJson == null) { + if (eventJson == null || client == null) { return null; } @@ -417,4 +465,9 @@ JSONObject deliverEvent(@Nullable JSONObject eventJson) { boolean hasString(JSONObject args, String key) { return getString(args, key) != null; } + + private static long hexToLong(String hex) { + return Long.parseLong(hex.substring(0, 2), 16) << 56 | + Long.parseLong(hex.substring(2), 16); + } } diff --git a/packages/bugsnag_flutter/ios/Classes/BugsnagFlutterPlugin.m b/packages/bugsnag_flutter/ios/Classes/BugsnagFlutterPlugin.m index caea782e..04463132 100644 --- a/packages/bugsnag_flutter/ios/Classes/BugsnagFlutterPlugin.m +++ b/packages/bugsnag_flutter/ios/Classes/BugsnagFlutterPlugin.m @@ -51,6 +51,31 @@ static void DyldImageAdded(const struct mach_header *mh, intptr_t slide) { return [value isKindOfClass:[NSString class]] ? value : nil; } +static NSArray *jsonToRegularExpressions(NSArray *source) { + NSMutableArray *result = [NSMutableArray new]; + for (NSDictionary *element in source) { + NSString *pattern = element[@"pattern"]; + NSInteger options = 0; + if ([element[@"isDotAll"] boolValue]) { + options |= NSRegularExpressionDotMatchesLineSeparators; + } + if (![element[@"isCaseSensitive"] boolValue]) { + options |= NSRegularExpressionCaseInsensitive; + } + if ([element[@"isMultiLine"] boolValue]) { + options |= NSRegularExpressionAnchorsMatchLines; + } + NSError *error = nil; + NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:options error:&error]; + if (expression != nil) { + [result addObject: expression]; + } else if (error) { + NSLog(@"Error encountered while parsing regular expression %@", error); + } + } + return result; +} + @interface BugsnagEvent (BugsnagFlutterPlugin) @property (nullable, nonatomic) NSArray *projectPackages; @@ -278,12 +303,12 @@ - (void)start:(NSDictionary *)arguments { NSArray *redactedKeys = arguments[@"redactedKeys"]; if ([redactedKeys isKindOfClass:[NSArray class]]) { - configuration.redactedKeys = [NSSet setWithArray:redactedKeys]; + configuration.redactedKeys = [NSSet setWithArray: jsonToRegularExpressions(redactedKeys)]; } NSArray *discardClasses = arguments[@"discardClasses"]; if ([discardClasses isKindOfClass:[NSArray class]]) { - configuration.discardClasses = [NSSet setWithArray:discardClasses]; + configuration.discardClasses = [NSSet setWithArray: jsonToRegularExpressions(discardClasses)]; } NSArray *enabledReleaseStages = arguments[@"enabledReleaseStages"]; @@ -450,6 +475,15 @@ - (NSDictionary *)createEvent:(NSDictionary *)json { [event addMetadata:DartCodeBuildId withKey:@"buildID" toSection:@"flutter"]; } } + + NSDictionary *correlation = json[@"correlation"]; + if (correlation != nil) { + NSString *traceId = correlation[@"traceId"]; + NSString *spanId = correlation[@"spanId"]; + if (traceId != nil && spanId != nil) { + [event setCorrelationTraceId:traceId spanId:spanId]; + } + } if ([json[@"deliver"] boolValue]) { [client notifyInternal:event block:nil]; diff --git a/packages/bugsnag_flutter/ios/bugsnag_flutter.podspec b/packages/bugsnag_flutter/ios/bugsnag_flutter.podspec index cc1d834c..87b8db25 100644 --- a/packages/bugsnag_flutter/ios/bugsnag_flutter.podspec +++ b/packages/bugsnag_flutter/ios/bugsnag_flutter.podspec @@ -16,5 +16,5 @@ Bugsnag crash monitoring and reporting tool for Flutter apps s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.dependency 'Flutter' - s.dependency 'Bugsnag', '6.28.0' + s.dependency 'Bugsnag', '6.30.0' end diff --git a/packages/bugsnag_flutter/lib/src/client.dart b/packages/bugsnag_flutter/lib/src/client.dart index 372d9d6d..063f2d15 100644 --- a/packages/bugsnag_flutter/lib/src/client.dart +++ b/packages/bugsnag_flutter/lib/src/client.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:ui'; +import 'package:bugsnag_bridge/bugsnag_bridge.dart'; import 'package:bugsnag_flutter/src/error_factory.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/scheduler.dart'; @@ -13,15 +14,15 @@ import 'config.dart'; import 'enum_utils.dart'; import 'last_run_info.dart'; import 'model.dart'; +import 'regexp_json.dart'; final _notifier = { 'name': 'Flutter Bugsnag Notifier', 'url': 'https://github.com/bugsnag/bugsnag-flutter', - 'version': '3.1.1' + 'version': '4.0.0' }; abstract class BugsnagClient { - final Map _openNetworkRequests = {}; /// An utility error handling function that will send reported errors to @@ -256,45 +257,47 @@ abstract class BugsnagClient { } void _onRequestStarted(String requestId) { - final stopwatch = Stopwatch()..start(); - _openNetworkRequests[requestId] = stopwatch; + final stopwatch = Stopwatch()..start(); + _openNetworkRequests[requestId] = stopwatch; } void _onRequestComplete(String requestId, dynamic data) { - final stopwatch = _openNetworkRequests.remove(requestId); - if (stopwatch != null && data is Map) { - final duration = stopwatch.elapsedMilliseconds; - final String? clientName = data["client"]; - if (clientName == null) return; - - String params = ""; - final url = data["url"]; - final splitUrl = url.split("?"); - if (splitUrl != null && splitUrl.length > 1) { - params = splitUrl.last; - } - final int? statusCode = data["status_code"]; - if (statusCode == null) return; - - final String status = statusCode < 400 ? "succeeded" : "failed"; - // Assuming leaveBreadcrumb is a predefined method to log the event - leaveBreadcrumb("$clientName request $status", metadata: { + final stopwatch = _openNetworkRequests.remove(requestId); + if (stopwatch != null && data is Map) { + final duration = stopwatch.elapsedMilliseconds; + final String? clientName = data["client"]; + if (clientName == null) return; + + String params = ""; + final url = data["url"]; + final splitUrl = url.split("?"); + if (splitUrl != null && splitUrl.length > 1) { + params = splitUrl.last; + } + final int? statusCode = data["status_code"]; + if (statusCode == null) return; + + final String status = statusCode < 400 ? "succeeded" : "failed"; + // Assuming leaveBreadcrumb is a predefined method to log the event + leaveBreadcrumb( + "$clientName request $status", + metadata: { "duration": duration, "method": data["http_method"], "url": splitUrl.first, - if(params.isNotEmpty) - "urlParams": params, - if(data["request_content_length"] != null && data["request_content_length"] > 0) - "requestContentLength": data["request_content_length"], - if(data["response_content_length"] != null && data["response_content_length"] > 0) - "responseContentLength": data["response_content_length"], + if (params.isNotEmpty) "urlParams": params, + if (data["request_content_length"] != null && + data["request_content_length"] > 0) + "requestContentLength": data["request_content_length"], + if (data["response_content_length"] != null && + data["response_content_length"] > 0) + "responseContentLength": data["response_content_length"], "status": statusCode, - }, - type: BugsnagBreadcrumbType.request, - ); - } + }, + type: BugsnagBreadcrumbType.request, + ); + } } - } mixin DelegateClient implements BugsnagClient { @@ -419,6 +422,8 @@ class ChannelClient extends BugsnagClient { final CallbackCollection _onErrorCallbacks = {}; + final contextProvider = BugsnagContextProviderImpl(); + @override void Function(dynamic error, StackTrace? stack) get errorHandler => _notifyUnhandled; @@ -614,13 +619,21 @@ class ChannelClient extends BugsnagClient { PlatformDispatcher.instance.initialLifecycleState, if (lifecycleState != null) 'lifecycleState': lifecycleState, }; + final traceContext = contextProvider.getCurrentTraceContext(); + final correlation = traceContext != null + ? { + 'spanId': traceContext.spanId, + 'traceId': traceContext.traceId, + } + : null; final eventJson = await _channel.invokeMethod( 'createEvent', { 'error': error, 'flutterMetadata': metadata, 'unhandled': unhandled, - 'deliver': deliver + 'deliver': deliver, + if (correlation != null) 'correlation': correlation, }, ); @@ -742,8 +755,8 @@ class Bugsnag extends BugsnagClient with DelegateClient { int launchDurationMillis = 5000, bool sendLaunchCrashesSynchronously = true, int appHangThresholdMillis = appHangThresholdFatalOnly, - Set redactedKeys = const {'password'}, - Set discardClasses = const {}, + Set? redactedKeys, + Set discardClasses = const {}, Set? enabledReleaseStages, Set? enabledBreadcrumbTypes, BugsnagProjectPackages projectPackages = @@ -786,8 +799,10 @@ class Bugsnag extends BugsnagClient with DelegateClient { 'launchDurationMillis': launchDurationMillis, 'sendLaunchCrashesSynchronously': sendLaunchCrashesSynchronously, 'appHangThresholdMillis': appHangThresholdMillis, - 'redactedKeys': List.from(redactedKeys), - 'discardClasses': List.from(discardClasses), + 'redactedKeys': List.from(redactedKeys?.map((e) => e.toJson()) ?? + {RegExp('password').toJson()}), + 'discardClasses': + List.from(discardClasses.map((e) => e.toJson())), if (enabledReleaseStages != null) 'enabledReleaseStages': enabledReleaseStages.toList(), 'enabledBreadcrumbTypes': @@ -833,7 +848,6 @@ class Bugsnag extends BugsnagClient with DelegateClient { return const {}; } - } /// In order to determine where a crash happens Bugsnag needs to know which diff --git a/packages/bugsnag_flutter/lib/src/regexp_json.dart b/packages/bugsnag_flutter/lib/src/regexp_json.dart new file mode 100644 index 00000000..8726a0ad --- /dev/null +++ b/packages/bugsnag_flutter/lib/src/regexp_json.dart @@ -0,0 +1,8 @@ +extension RegExpJSON on RegExp { + dynamic toJson() => { + 'pattern': pattern, + 'isDotAll': isDotAll, + 'isCaseSensitive': isCaseSensitive, + 'isMultiLine': isMultiLine, + }; +} diff --git a/packages/bugsnag_flutter/pubspec.yaml b/packages/bugsnag_flutter/pubspec.yaml index 06cafd34..29cd9e84 100644 --- a/packages/bugsnag_flutter/pubspec.yaml +++ b/packages/bugsnag_flutter/pubspec.yaml @@ -1,6 +1,6 @@ name: bugsnag_flutter description: Bugsnag crash monitoring and reporting tool for Flutter apps -version: 3.1.1 +version: 4.0.0 homepage: https://www.bugsnag.com/ documentation: https://docs.bugsnag.com/platforms/flutter/ repository: https://github.com/bugsnag/bugsnag-flutter @@ -13,6 +13,7 @@ environment: dependencies: flutter: sdk: flutter + bugsnag_bridge: ^2.0.0 dev_dependencies: flutter_test: